backup: save local changes on 2025-09-26
1975
dist/main/_internal/Utils/Dy/DyUtils.py
vendored
Normal file
0
dist/main/_internal/Utils/Dy/__init__.py
vendored
Normal file
BIN
dist/main/_internal/Utils/Dy/__pycache__/DyUtils.cpython-313.pyc
vendored
Normal file
BIN
dist/main/_internal/Utils/Dy/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
BIN
dist/main/_internal/Utils/Dy/__pycache__/message_arg.cpython-313.pyc
vendored
Normal file
375
dist/main/_internal/Utils/Dy/message_arg.py
vendored
Normal file
@@ -0,0 +1,375 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# python let's go
|
||||
# 编辑人:kris思成
|
||||
|
||||
# coding=utf-8
|
||||
import time
|
||||
import uuid
|
||||
import json
|
||||
|
||||
|
||||
# 发送消息
|
||||
def send_message(pigeon_sign: str, token: str, receiver_id: str, shop_id: str, talk_id: int, session_did: str, p_id: int, user_code: str, text: str):
|
||||
"""
|
||||
构造发送消息消息体
|
||||
:param pigeon_sign: 接口返回
|
||||
:param token: 接口返回
|
||||
:param receiver_id: wss消息返回 对方用户id
|
||||
:param shop_id: cookie自带
|
||||
:param talk_id: wss消息返回 激活窗口id
|
||||
:param session_did: cookie自带
|
||||
:param p_id: wss消息返回
|
||||
:param user_code: 用户token
|
||||
:param text: 文本内容
|
||||
:return:
|
||||
"""
|
||||
value = {
|
||||
'1': 11778,
|
||||
'2': int(time.time() * 1000),
|
||||
'3': 10001,
|
||||
'4': 1,
|
||||
'5': [
|
||||
{'1': b'pigeon_source', '2': b'web'},
|
||||
{'1': b'PIGEON_BIZ_TYPE', '2': b'2'},
|
||||
{'1': b'pigeon_sign', '2': pigeon_sign.encode()},
|
||||
],
|
||||
'7': {'14': 98},
|
||||
'8': {
|
||||
'1': 100,
|
||||
'2': 11778,
|
||||
'3': b'1.0.4-beta.2',
|
||||
'4': token.encode(),
|
||||
'5': 3,
|
||||
'6': 3,
|
||||
'7': b'2d97ea6:feat/add_init_callback',
|
||||
'8': {
|
||||
'100': {
|
||||
'1': f"{receiver_id}:{shop_id}::2:1:pigeon".encode(),
|
||||
'2': 11,
|
||||
'3': p_id,
|
||||
'4': text.encode(),
|
||||
'5': [
|
||||
{'1': b'type', '2': b'text'},
|
||||
{'1': b'shop_id', '2': shop_id.encode()},
|
||||
{'1': b'sender_role', '2': b'2'},
|
||||
{'1': b'PIGEON_BIZ_TYPE', '2': b'2'},
|
||||
{'1': b'src', '2': b'pc'},
|
||||
{'1': b'srcType', '2': b'1'},
|
||||
{'1': b'source', '2': b'pc-web'},
|
||||
{'1': b'receiver_id', '2': str(receiver_id).encode()},
|
||||
{'1': b'hierarchical_dimension', '2': b'{"dynamic_dimension":"4541_1131_9042_6599_9420_6832_4050_3823_3994_8564_1528_0388_8667_2179_7948_1870_1949_0989_8012_6240_7898_7548_8852_6245_9393_3650_8570_4026_4034_4057_6537_8632_2068_8958_0363_2387_9033_3425_2238_0982_1935_8188_3817_8557_7931_3278_4065_1893_6049_6961_3814_4883_4401_6637_7282_3652_9354_0437_4769_4815_9572_7230_5054_3951_4852_2188_3505_6813_2570_5394_0729","goofy_id":"1.0.1.1508","desk_version":"0.0.0","open_stores":"0","memL":"","cpuL":"","session_throughput":0,"message_throughput_send":0,"message_throughput_revice":0}'},
|
||||
{'1': b'p:check_Send', '2': str(uuid.uuid4()).encode()},
|
||||
{'1': b'track_info','2': json.dumps({"send_time": int(time.time() * 1000), "_send_delta": "77","_send_delta_2": "216"}).encode()},
|
||||
{'1': b'user_agent', '2': b'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'sender_id', '2': b''},
|
||||
{'1': b'biz_ext', '2': b'{}'},
|
||||
{'1': b'p:from_source', '2': b'web'},
|
||||
{'1': b's:mentioned_users', '2': b''},
|
||||
{'1': b's:client_message_id', '2': str(uuid.uuid4()).encode()}
|
||||
],
|
||||
'6': 1000,
|
||||
'7': user_code.encode(),
|
||||
'8': str(uuid.uuid4()).encode(),
|
||||
'14': talk_id # 激活聊天窗口id
|
||||
}
|
||||
},
|
||||
'9': session_did.encode(),
|
||||
'11': b'web',
|
||||
'15': [
|
||||
{'1': b'pigeon_source', '2': b'web'},
|
||||
{'1': b'PIGEON_BIZ_TYPE', '2': b'2'},
|
||||
{'1': b'pigeon_sign', '2': b'MIG6BAz2BNUON43WdlOBuGYEgZcsIho9ZjVP4yyExLShzXgAZtsvUMj2e3jZWeMZv+6+TNVQQMq3xSLrqiwcs2cCaOVBDuS6zGsWm5gBlGtlvOOLM5td2/9OS8P37t1sdkjN4BSH2mB7FlGItioZIsTh1sodn6pYCGj+45mtId3Itenufgai3Mnkpt573uoWJmagF8J3jVPHMFtdwd25Qf5vsWC2kB30glpQBBCbk2VO2ubMqctqQSzhI6uD'},
|
||||
{'1': b'session_aid', '2': b'1383'},
|
||||
{'1': b'session_did', '2': session_did.encode()},
|
||||
{'1': b'app_name', '2': b'im'},
|
||||
{'1': b'priority_region', '2': b'cn'},
|
||||
{'1': b'user_agent','2': b'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'cookie_enabled', '2': b'true'},
|
||||
{'1': b'browser_language', '2': b'zh-CN'},
|
||||
{'1': b'browser_platform', '2': b'Win32'},
|
||||
{'1': b'browser_name', '2': b'Mozilla'},
|
||||
{'1': b'browser_version', '2': b'5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'browser_online', '2': b'true'},
|
||||
{'1': b'screen_width', '2': b'1707'},
|
||||
{'1': b'screen_height', '2': b'1067'},
|
||||
{'1': b'referer', '2': b''},
|
||||
{'1': b'timezone_name', '2': b'Asia/Shanghai'}
|
||||
],
|
||||
'18': 2}
|
||||
}
|
||||
message_type = {
|
||||
"1": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"2": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"3": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"4": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"5": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"1": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"2": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
},
|
||||
"7": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"14": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
},
|
||||
"8": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"1": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"2": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"3": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"4": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"5": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"6": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"7": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"8": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"100": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"1": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"2": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"3": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"4": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"5": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"1": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"2": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
},
|
||||
"6": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
},
|
||||
"7": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"8": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"14": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
},
|
||||
"9": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"11": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"15": {
|
||||
"type": "message",
|
||||
"message_typedef": {
|
||||
"1": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
},
|
||||
"2": {
|
||||
"type": "bytes",
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
},
|
||||
"18": {
|
||||
"type": "int",
|
||||
"name": ""
|
||||
}
|
||||
},
|
||||
"name": ""
|
||||
}
|
||||
}
|
||||
return value, message_type
|
||||
|
||||
|
||||
# 获取token
|
||||
def get_user_code(pigeon_sign: str, token: str, receiver_id: str, shop_id: str, session_did: str, p_id: int):
|
||||
value = {'1': 10109, '2': int(time.time() * 1000), '3': 10001, '4': 1,
|
||||
'5': [{'1': b'pigeon_source', '2': b'web'}, {'1': b'PIGEON_BIZ_TYPE', '2': b'2'}, {'1': b'pigeon_sign',
|
||||
'2': pigeon_sign.encode()}],
|
||||
'7': {'14': 98}, '8': {'1': 610, '2': 10109, '3': b'1.0.4-beta.2',
|
||||
'4': token.encode(), '5': 3, '6': 3,
|
||||
'7': b'2d97ea6:feat/add_init_callback', '8': {
|
||||
'610': {'1': {'1': f"{receiver_id}:{shop_id}::2:1:pigeon".encode(), '2': p_id, '3': 10}}},
|
||||
'9': session_did.encode(), '11': b'web',
|
||||
'15': [{'1': b'pigeon_source', '2': b'web'}, {'1': b'PIGEON_BIZ_TYPE', '2': b'2'},
|
||||
{'1': b'pigeon_sign',
|
||||
'2': pigeon_sign.encode()},
|
||||
{'1': b'session_aid', '2': b'1383'},
|
||||
{'1': b'session_did', '2': session_did.encode()},
|
||||
{'1': b'app_name', '2': b'im'}, {'1': b'priority_region', '2': b'cn'},
|
||||
{'1': b'user_agent',
|
||||
'2': b'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'cookie_enabled', '2': b'true'},
|
||||
{'1': b'browser_language', '2': b'zh-CN'},
|
||||
{'1': b'browser_platform', '2': b'Win32'},
|
||||
{'1': b'browser_name', '2': b'Mozilla'}, {'1': b'browser_version',
|
||||
'2': b'5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'browser_online', '2': b'true'}, {'1': b'screen_width', '2': b'1707'},
|
||||
{'1': b'screen_height', '2': b'1067'}, {'1': b'referer', '2': b''},
|
||||
{'1': b'timezone_name', '2': b'Asia/Shanghai'}], '18': 2}}
|
||||
message_type = {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''},
|
||||
'3': {'type': 'int', 'name': ''}, '4': {'type': 'int', 'name': ''}, '5': {'type': 'message',
|
||||
'message_typedef': {
|
||||
'1': {'type': 'bytes',
|
||||
'name': ''},
|
||||
'2': {'type': 'bytes',
|
||||
'name': ''}},
|
||||
'name': ''},
|
||||
'7': {'type': 'message', 'message_typedef': {'14': {'type': 'int', 'name': ''}}, 'name': ''},
|
||||
'8': {'type': 'message',
|
||||
'message_typedef': {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''},
|
||||
'3': {'type': 'bytes', 'name': ''}, '4': {'type': 'bytes', 'name': ''},
|
||||
'5': {'type': 'int', 'name': ''}, '6': {'type': 'int', 'name': ''},
|
||||
'7': {'type': 'bytes', 'name': ''}, '8': {'type': 'message',
|
||||
'message_typedef': {
|
||||
'610': {'type': 'message',
|
||||
'message_typedef': {
|
||||
'1': {
|
||||
'type': 'message',
|
||||
'message_typedef': {
|
||||
'1': {
|
||||
'type': 'bytes',
|
||||
'name': ''},
|
||||
'2': {
|
||||
'type': 'int',
|
||||
'name': ''},
|
||||
'3': {
|
||||
'type': 'int',
|
||||
'name': ''}},
|
||||
'name': ''}},
|
||||
'name': ''}},
|
||||
'name': ''},
|
||||
'9': {'type': 'bytes', 'name': ''}, '11': {'type': 'bytes', 'name': ''},
|
||||
'15': {'type': 'message',
|
||||
'message_typedef': {'1': {'type': 'bytes', 'name': ''},
|
||||
'2': {'type': 'bytes', 'name': ''}},
|
||||
'name': ''}, '18': {'type': 'int', 'name': ''}}, 'name': ''}}
|
||||
return value, message_type
|
||||
|
||||
|
||||
# 心跳包
|
||||
def heartbeat_message(pigeon_sign: str, token: str, session_did: str):
|
||||
value = {
|
||||
'1': 11028,
|
||||
'2': int(time.time() * 1000),
|
||||
'3': 10001,
|
||||
'4': 1,
|
||||
'5': [
|
||||
{'1': b'pigeon_source', '2': b'web'},
|
||||
{'1': b'PIGEON_BIZ_TYPE', '2': b'2'},
|
||||
{'1': b'pigeon_sign','2': pigeon_sign.encode()}
|
||||
],
|
||||
'7': {'14': 98},
|
||||
'8': {
|
||||
'1': 200,
|
||||
'2': 11028,
|
||||
'3': b'1.0.4-beta.2',
|
||||
'4': token.encode(),
|
||||
'5': 3,
|
||||
'6': 3,
|
||||
'7': b'2d97ea6:feat/add_init_callback',
|
||||
'8': {'200': {'1': int(time.time() * 1000), '2': 50}},
|
||||
'9': session_did.encode(),
|
||||
'11': b'web',
|
||||
'15': [
|
||||
{'1': b'pigeon_source', '2': b'web'},
|
||||
{'1': b'PIGEON_BIZ_TYPE', '2': b'2'},
|
||||
{'1': b'pigeon_sign', '2': pigeon_sign.encode()},
|
||||
{'1': b'session_aid', '2': b'1383'},
|
||||
{'1': b'session_did', '2': session_did.encode()},
|
||||
{'1': b'app_name', '2': b'im'},
|
||||
{'1': b'priority_region', '2': b'cn'},
|
||||
{'1': b'user_agent', '2': b'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'cookie_enabled', '2': b'true'},
|
||||
{'1': b'browser_language', '2': b'zh-CN'},
|
||||
{'1': b'browser_platform', '2': b'Win32'}, {'1': b'browser_name', '2': b'Mozilla'},
|
||||
{'1': b'browser_version', '2': b'5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36'},
|
||||
{'1': b'browser_online', '2': b'true'}, {'1': b'screen_width', '2': b'1707'},
|
||||
{'1': b'screen_height', '2': b'1067'}, {'1': b'referer', '2': b''},
|
||||
{'1': b'timezone_name', '2': b'Asia/Shanghai'}
|
||||
],
|
||||
'18': 2
|
||||
}
|
||||
}
|
||||
message_type = {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''}, '3': {'type': 'int', 'name': ''}, '4': {'type': 'int', 'name': ''}, '5': {'type': 'message', 'message_typedef': {'1': {'type': 'bytes', 'name': ''}, '2': {'type': 'bytes', 'name': ''}}, 'name': ''}, '7': {'type': 'message', 'message_typedef': {'14': {'type': 'int', 'name': ''}}, 'name': ''}, '8': {'type': 'message', 'message_typedef': {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''}, '3': {'type': 'bytes', 'name': ''}, '4': {'type': 'bytes', 'name': ''}, '5': {'type': 'int', 'name': ''}, '6': {'type': 'int', 'name': ''}, '7': {'type': 'bytes', 'name': ''}, '8': {'type': 'message', 'message_typedef': {'200': {'type': 'message', 'message_typedef': {'1': {'type': 'int', 'name': ''}, '2': {'type': 'int', 'name': ''}}, 'name': ''}}, 'name': ''}, '9': {'type': 'bytes', 'name': ''}, '11': {'type': 'bytes', 'name': ''}, '15': {'type': 'message', 'message_typedef': {'1': {'type': 'bytes', 'name': ''}, '2': {'type': 'bytes', 'name': ''}}, 'name': ''}, '18': {'type': 'int', 'name': ''}}, 'name': ''}}
|
||||
return value, message_type
|
||||
|
||||
981
dist/main/_internal/Utils/JD/JdUtils.py
vendored
Normal file
@@ -0,0 +1,981 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# python let's go
|
||||
# 编辑人:kris思成
|
||||
import asyncio
|
||||
import hashlib
|
||||
import traceback
|
||||
from datetime import datetime
|
||||
import aiohttp
|
||||
import jsonpath
|
||||
import websockets
|
||||
from loguru import logger
|
||||
import requests
|
||||
import json
|
||||
import time
|
||||
import threading
|
||||
|
||||
|
||||
# 定义持久化数据类
|
||||
class WebsocketManager:
|
||||
_instance = None
|
||||
_lock = threading.Lock()
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
with cls._lock:
|
||||
if cls._instance is None:
|
||||
cls._instance = super().__new__(cls)
|
||||
cls._instance._store = {}
|
||||
cls._instance._lock = threading.RLock()
|
||||
return cls._instance
|
||||
|
||||
def on_connect(self, shop_key, ws, **kwargs):
|
||||
"""完全保持原有数据结构"""
|
||||
with self._lock:
|
||||
entry = self._store.setdefault(shop_key, {
|
||||
'platform': None,
|
||||
'customers': [],
|
||||
'user_assignments': {}
|
||||
})
|
||||
entry['platform'] = {
|
||||
'ws': ws, # 注意:这里存储的是强引用
|
||||
'last_heartbeat': datetime.now(),
|
||||
**kwargs
|
||||
}
|
||||
return entry
|
||||
|
||||
def get_connection(self, shop_key):
|
||||
with self._lock:
|
||||
return self._store.get(shop_key)
|
||||
|
||||
def remove_connection(self, shop_key):
|
||||
with self._lock:
|
||||
if shop_key in self._store:
|
||||
del self._store[shop_key]
|
||||
|
||||
|
||||
|
||||
|
||||
class JDBackendService:
|
||||
"""京东后端服务调用类(已废弃:使用单后端连接 BackendClient 代替)"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.current_store_id = ""
|
||||
|
||||
async def connect(self, store_id, *args, **kwargs):
|
||||
try:
|
||||
self.current_store_id = str(store_id or "")
|
||||
except Exception:
|
||||
self.current_store_id = ""
|
||||
return True
|
||||
|
||||
async def send_message_to_backend(self, platform_message):
|
||||
"""改为通过单后端连接发送,需携带store_id"""
|
||||
try:
|
||||
from WebSocket.backend_singleton import get_backend_client
|
||||
backend = get_backend_client()
|
||||
if not backend:
|
||||
return None
|
||||
# 从platform_message中构造统一上行结构,并附加store_id
|
||||
body = platform_message.get('body', {}) if isinstance(platform_message, dict) else {}
|
||||
sender_pin = platform_message.get('from', {}).get('pin', '') if isinstance(platform_message, dict) else ''
|
||||
# 优先取消息内的store_id,其次取body内,再次退回当前会话store_id
|
||||
store_id = (platform_message.get('store_id')
|
||||
or body.get('store_id')
|
||||
or self.current_store_id
|
||||
or '')
|
||||
body_type = body.get('type', 'text')
|
||||
content_for_backend = body.get('content', '')
|
||||
if body_type in ('image', 'video'):
|
||||
# 统一从常见字段取URL
|
||||
content_for_backend = (
|
||||
body.get('url')
|
||||
or body.get('imageUrl')
|
||||
or body.get('videoUrl')
|
||||
or body.get('picUrl')
|
||||
or content_for_backend
|
||||
)
|
||||
# 检测文本中的商品卡片/订单卡片
|
||||
if body_type == 'text' and isinstance(content_for_backend, str):
|
||||
try:
|
||||
import re as _re
|
||||
text = content_for_backend.strip()
|
||||
# 商品卡片:JD商品URL
|
||||
if _re.search(r"https?://item(\.m)?\.jd\.com/\d+\.html(\?.*)?", text):
|
||||
body_type = 'product_card'
|
||||
else:
|
||||
# 订单卡片多样式匹配
|
||||
# 1) 订单在前:咨询/查询/订单号:<order>[,,]? 商品(ID|id|号|编号):<product>
|
||||
m1 = _re.search(
|
||||
r"(?:咨询订单号|查询订单号|订单号)\s*[::]\s*(\d+)[,,]?\s*商品(?:ID|id|号|编号)\s*[::]\s*(\d+)",
|
||||
text)
|
||||
# 2) 商品在前:商品(ID|id|号|编号):<product>[,,]? (咨询/查询)?订单号:<order>
|
||||
m2 = _re.search(
|
||||
r"商品(?:ID|id|号|编号)\s*[::]\s*(\d+)[,,]?\s*(?:咨询订单号|查询订单号|订单号)\s*[::]\s*(\d+)",
|
||||
text)
|
||||
if m1 or m2:
|
||||
body_type = 'order_card'
|
||||
if m1:
|
||||
order_number, product_id = m1.group(1), m1.group(2)
|
||||
else:
|
||||
product_id, order_number = m2.group(1), m2.group(2)
|
||||
# 归一化 content
|
||||
content_for_backend = f"商品id:{product_id} 订单号:{order_number}"
|
||||
except Exception:
|
||||
pass
|
||||
msg = {
|
||||
'type': 'message',
|
||||
'content': content_for_backend,
|
||||
'msg_type': body_type,
|
||||
'sender': {'id': sender_pin},
|
||||
'store_id': store_id
|
||||
}
|
||||
backend.send_message(msg)
|
||||
return None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
class FixJdCookie:
|
||||
|
||||
def __init__(self, log_callback=None):
|
||||
# 定义一些常用参数
|
||||
super().__init__() # 继承一些父类的初始化参数
|
||||
self.ws_manager = WebsocketManager()
|
||||
self.log_callback = log_callback # 存储日志回调
|
||||
|
||||
# 新增后端服务实例
|
||||
self.backend_service = JDBackendService()
|
||||
self.backend_connected = False
|
||||
|
||||
# 新增重连参数
|
||||
self.reconnect_attempts = 0
|
||||
self.max_reconnect_attempts = 10 # 最大重连次数
|
||||
self.base_reconnect_delay = 1.0 # 基础重连延迟
|
||||
self.max_reconnect_delay = 60.0 # 最大重连延迟
|
||||
self.reconnect_backoff = 1.5 # 退避系数
|
||||
|
||||
def _log(self, message, log_type="INFO"):
|
||||
"""内部日志方法"""
|
||||
if self.log_callback:
|
||||
self.log_callback(message, log_type)
|
||||
else:
|
||||
print(f"[{log_type}] {message}")
|
||||
|
||||
def get_config(self, cookies_str):
|
||||
"""获取配置"""
|
||||
headers = {
|
||||
"cookie": cookies_str,
|
||||
"user-agent": "Mozilla/5.0",
|
||||
"referer": "https://dongdong.jd.com/",
|
||||
}
|
||||
response = requests.get("https://dongdong.jd.com/workbench/checkin.json", headers=headers,
|
||||
params={"version": "2.6.3", "client": "openweb"})
|
||||
return response.json()
|
||||
|
||||
async def init_wss(self, ws, aid, pin_zj):
|
||||
"""初始化 socket"""
|
||||
await self.send_heartbeat(ws, aid, pin_zj)
|
||||
print("开始监听初始化")
|
||||
auth = {
|
||||
"id": hashlib.md5(str(int(time.time() * 1000)).encode()).hexdigest(),
|
||||
"aid": aid,
|
||||
"lang": "zh_CN",
|
||||
"timestamp": int(time.time() * 1000),
|
||||
"type": "auth",
|
||||
"body": {"presence": 1, "clientVersion": "2.6.3"},
|
||||
"to": {"app": "im.waiter"},
|
||||
"from": {"app": "im.waiter", "pin": pin_zj, "clientType": "comet", "dvc": "device1234"}
|
||||
}
|
||||
await ws.send(json.dumps(auth))
|
||||
|
||||
|
||||
async def waiter_status_switch(self, ws, aid, pin_zj):
|
||||
"""设置接待状态"""
|
||||
message = {
|
||||
"id": hashlib.md5(str(int(time.time() * 1000)).encode()).hexdigest(),
|
||||
"aid": aid,
|
||||
"lang": "zh_CN",
|
||||
"timestamp": int(time.time() * 1000),
|
||||
"from": {
|
||||
"app": "im.waiter",
|
||||
"pin": pin_zj,
|
||||
"art": "customerGroupMsg",
|
||||
"clientType": "comet"
|
||||
},
|
||||
"type": "waiter_status_switch",
|
||||
"body": {
|
||||
"s": 1
|
||||
}
|
||||
}
|
||||
await ws.send(json.dumps(message))
|
||||
|
||||
async def transfer_customer(self, ws, aid, pin, pin_zj, chat_name):
|
||||
"""异步客服转接 在发送的消息为客服转接的关键词的时候"""
|
||||
message = {
|
||||
"id": hashlib.md5(str(int(time.time() * 1000)).encode()).hexdigest(),
|
||||
"aid": aid,
|
||||
"lang": "zh_CN",
|
||||
"timestamp": int(time.time() * 1000),
|
||||
"from": {
|
||||
"app": "im.waiter", "pin": pin_zj, "art": "customerGroupMsg", "clientType": "comet"
|
||||
},
|
||||
"type": "chat_transfer_partern",
|
||||
"body": {
|
||||
"customer": pin, "cappId": "im.customer", "waiter": chat_name, "reason": "",
|
||||
"ext": {"pid": ""}, "pid": ""
|
||||
}
|
||||
}
|
||||
try:
|
||||
await ws.send(json.dumps(message))
|
||||
return True
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
async def send_message(self, ws, pin, aid, pin_zj, vender_id, content):
|
||||
"""异步发送单条消息"""
|
||||
try:
|
||||
print('本地发送消息')
|
||||
message = {
|
||||
"ver": "4.3",
|
||||
"type": "chat_message",
|
||||
"from": {"pin": pin_zj, "app": "im.waiter", "clientType": "comet"},
|
||||
"to": {"app": "im.customer", "pin": pin},
|
||||
"id": hashlib.md5(str(int(time.time() * 1000)).encode()).hexdigest(),
|
||||
"lang": "zh_CN",
|
||||
"aid": aid,
|
||||
"timestamp": int(time.time() * 1000),
|
||||
"readFlag": 0,
|
||||
"body": {
|
||||
"content": content,
|
||||
"translated": False,
|
||||
"param": {"cusVenderId": vender_id},
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
await ws.send(json.dumps(message))
|
||||
logger.info(f"消息已经发送到客户端[info] {pin}: {content[:20]} ...")
|
||||
except websockets.ConnectionClosed:
|
||||
logger.error('本地发送消息失败 连接关闭')
|
||||
raise
|
||||
except Exception as e:
|
||||
# 同时这里也要及时进行raise抛出 这样比较好让系统可以看出 异常了可以抛出信息不至于后续被认为
|
||||
logger.error(f"消息发送过程中出现特殊异常异常信息为: {e}")
|
||||
raise
|
||||
|
||||
def get_userinfo(self, response_text):
|
||||
"""获取用户 pin 并存入 pins 列表"""
|
||||
pin = jsonpath.jsonpath(json.loads(response_text), "$..from.pin")
|
||||
return pin[0] if pin else None
|
||||
|
||||
def is_merchants(self, store: object, response):
|
||||
"""判断消息是否来自顾客"""
|
||||
send = response['from']['pin']
|
||||
# 补充: 方法lower()是转化为小写 upper()是转化为大写 title()是每个单词首字母大写其余小写
|
||||
if send.lower() == "KLD测试".lower():
|
||||
return False
|
||||
return True
|
||||
|
||||
async def send_heartbeat(self, ws, aid, pin_zj):
|
||||
"""发送心跳包"""
|
||||
msg = {
|
||||
"id": hashlib.md5(str(int(time.time() * 1000)).encode()).hexdigest(),
|
||||
"type": "client_heartbeat",
|
||||
"aid": aid,
|
||||
"ver": "4.1",
|
||||
"lang": "zh_CN",
|
||||
"from": {"pin": pin_zj, "app": "im.waiter", "art": "customerGroupMsg", "clientType": "comet"}
|
||||
}
|
||||
await ws.send(json.dumps(msg, separators=(',', ':'))) # 使用最简心跳包模式 来节约部分性能 减少传输压力
|
||||
|
||||
async def heartbeat_loop(self, websocket, aid, pin_zj):
|
||||
"""独立的心跳循环"""
|
||||
"""
|
||||
优化心跳 循环 新增改进
|
||||
1. 心跳间隔动态调整
|
||||
2. 异常重试机制
|
||||
3. 心跳超时控制
|
||||
4. 状态监控
|
||||
"""
|
||||
retry_count = 0
|
||||
max_retries = 3
|
||||
base_interval = 3.0 # 基础间隔1s
|
||||
backoff_factor = 1.5 # 退避系数
|
||||
timeout = 10.0
|
||||
|
||||
while True:
|
||||
try:
|
||||
start_time = time.monotonic()
|
||||
|
||||
# 使用websocket原生的ping/pong机制
|
||||
pong_waiter = await websocket.ping()
|
||||
await asyncio.wait_for(pong_waiter, timeout=timeout)
|
||||
|
||||
# 如果需要发送自定义心跳包
|
||||
await self.send_heartbeat(websocket, aid, pin_zj)
|
||||
|
||||
# 计算剩余等待时间
|
||||
elapsed = time.monotonic() - start_time
|
||||
sleep_time = max(0.0, base_interval - elapsed)
|
||||
|
||||
if sleep_time > 0:
|
||||
await asyncio.sleep(sleep_time)
|
||||
|
||||
retry_count = 0 # 重置重试计数
|
||||
|
||||
except asyncio.TimeoutError:
|
||||
logger.warning(f'心跳超时,已用时: {time.monotonic() - start_time:.2f}秒')
|
||||
retry_count += 1
|
||||
except websockets.ConnectionClosed:
|
||||
logger.error("连接关闭,心跳已停止")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"心跳异常: {e}", exc_info=True)
|
||||
retry_count += 1
|
||||
|
||||
if retry_count >= max_retries:
|
||||
logger.error(f"心跳连续失败{retry_count}次,终止循环")
|
||||
break
|
||||
|
||||
# 退避策略
|
||||
if retry_count > 0:
|
||||
backoff_time = min(
|
||||
base_interval * (backoff_factor ** (retry_count - 1)),
|
||||
60.0 # 最大等待60秒
|
||||
)
|
||||
logger.debug(f"心跳失败,等待{backoff_time:.2f}秒后重试")
|
||||
await asyncio.sleep(backoff_time)
|
||||
|
||||
''' 整理重连方法 '''
|
||||
async def calculate_reconnect_delay(self):
|
||||
"""计算指数退避的重连延迟时间"""
|
||||
delay = self.base_reconnect_delay * (self.reconnect_backoff ** self.reconnect_attempts)
|
||||
return min(delay, self.max_reconnect_delay)
|
||||
|
||||
async def should_reconnect(self):
|
||||
"""判断是否应该继续重连"""
|
||||
if self.reconnect_attempts >= self.max_reconnect_attempts:
|
||||
self._log(f"已达到最大重连次数({self.max_reconnect_attempts}),停止重连", "ERROR")
|
||||
return False
|
||||
return True
|
||||
|
||||
async def handle_reconnect(self, exception=None):
|
||||
"""处理重连逻辑"""
|
||||
if exception:
|
||||
error_type = type(exception).__name__
|
||||
error_msg = str(exception)
|
||||
self._log(f"连接异常[{error_type}]: {error_msg}", "WARNING")
|
||||
|
||||
if not await self.should_reconnect():
|
||||
return False
|
||||
|
||||
delay = await self.calculate_reconnect_delay()
|
||||
self._log(f"第{self.reconnect_attempts + 1}次重连尝试,等待{delay:.1f}秒...", "WARNING")
|
||||
|
||||
await asyncio.sleep(delay)
|
||||
self.reconnect_attempts += 1
|
||||
return True
|
||||
|
||||
|
||||
''' 后端服务调用方法 '''
|
||||
|
||||
async def connect_backend_service(self, store_id):
|
||||
"""连接后端AI服务"""
|
||||
try:
|
||||
success = await self.backend_service.connect(store_id)
|
||||
if success:
|
||||
self.backend_connected = True
|
||||
self._log("✅ 后端AI服务连接成功", "SUCCESS")
|
||||
return success
|
||||
except Exception as e:
|
||||
self._log(f"❌ 连接后端AI服务失败: {e}", "ERROR")
|
||||
return False
|
||||
|
||||
async def get_ai_reply_from_backend(self, platform_message):
|
||||
"""从后端服务获取AI回复"""
|
||||
# 首先检查后端服务连接状态
|
||||
if not self.backend_connected:
|
||||
# 尝试重新连接
|
||||
store_id = str(platform_message.get('body', {}).get('chatinfo', {}).get('venderId', ''))
|
||||
if store_id:
|
||||
self.backend_connected = await self.connect_backend_service(store_id)
|
||||
|
||||
if not self.backend_connected:
|
||||
self._log("❌ 后端服务未连接,尝试重新连接失败,使用本地AI回复", "WARNING")
|
||||
# 降级到本地AI回复
|
||||
customer_sid = platform_message.get('body', {}).get('chatinfo', {}).get('sid', '')
|
||||
customer_message = platform_message.get('body', {}).get('content', '')
|
||||
return
|
||||
try:
|
||||
# 推送给后端,由后端异步回传AI消息到GUI;此处不进行本地立即回复
|
||||
await self.backend_service.send_message_to_backend(platform_message)
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
self._log(f"❌ 获取AI回复失败: {e},使用本地AI", "ERROR")
|
||||
customer_sid = platform_message.get('body', {}).get('chatinfo', {}).get('sid', '')
|
||||
customer_message = platform_message.get('body', {}).get('content', '')
|
||||
return
|
||||
|
||||
async def process_incoming_message(self, response, ws, aid, pin_zj, vender_id, store):
|
||||
"""处理接收到的消息"""
|
||||
try:
|
||||
# 解析消息
|
||||
json_resp = json.loads(response) if isinstance(response, (str, bytes)) else response
|
||||
|
||||
# 验证消息格式
|
||||
if not all([
|
||||
json_resp,
|
||||
json_resp.get('type') == "chat_message",
|
||||
json_resp.get('ver') == "4.2",
|
||||
isinstance(json_resp.get("body"), dict)
|
||||
]):
|
||||
return
|
||||
|
||||
# 过滤非客户消息
|
||||
pin = self.get_userinfo(response)
|
||||
if not self.is_merchants(store, json_resp):
|
||||
return
|
||||
|
||||
# 提取消息内容
|
||||
message_type = json_resp['body']['type']
|
||||
if message_type == 'text':
|
||||
customer_message = json_resp['body']['content']
|
||||
elif message_type == 'image':
|
||||
customer_message = f"[图片] {json_resp['body'].get('url') or json_resp['body'].get('imageUrl') or json_resp['body'].get('picUrl') or ''}"
|
||||
elif message_type == 'video':
|
||||
customer_message = f"[视频] {json_resp['body'].get('url') or json_resp['body'].get('videoUrl') or ''}"
|
||||
else:
|
||||
return
|
||||
|
||||
self._log(f"📩 收到客户消息: {pin}: {customer_message[:100]}...", "INFO")
|
||||
|
||||
# 从后端服务获取AI回复(单连接模式:仅转交,不本地立即回复)
|
||||
ai_result = await self.get_ai_reply_from_backend(json_resp)
|
||||
|
||||
if isinstance(ai_result, str) and ai_result.strip():
|
||||
# 发送回复消息(仅当本地生成/降级时)
|
||||
await self.send_message(
|
||||
ws=ws, pin=pin, aid=aid,
|
||||
pin_zj=pin_zj, vender_id=vender_id,
|
||||
content=ai_result
|
||||
)
|
||||
self._log(f"📤 已发送回复: {ai_result[:100]}...", "INFO")
|
||||
else:
|
||||
# 正常链路:已转交后端AI,等待后端异步回传并由 GUI 转发到平台
|
||||
self._log("🔄 已转交后端AI处理,等待平台回复下发", "INFO")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
self._log("❌ 消息JSON解析失败", "ERROR")
|
||||
except Exception as e:
|
||||
self._log(f"❌ 消息处理失败: {e}", "ERROR")
|
||||
|
||||
async def message_monitoring(self, cookies_str, aid, pin_zj, vender_id, store, sleep_time=0.5, stop_event=None):
|
||||
print("✅ DEBUG 进入message_monitoring方法")
|
||||
print(f"参数验证: cookies={bool(cookies_str)}, aid={aid}, pin_zj={pin_zj}")
|
||||
|
||||
# 连接后端AI服务 - 使用店铺ID或venderId
|
||||
store_id = str(store.get('id', '')) or str(vender_id)
|
||||
self._log(f"🔗 尝试连接后端服务,店铺ID: {store_id}", "DEBUG")
|
||||
|
||||
backend_connected = await self.connect_backend_service(store_id)
|
||||
if not backend_connected:
|
||||
self._log("⚠️ 后端服务连接失败,将使用本地AI回复", "WARNING")
|
||||
else:
|
||||
self._log("✅ 后端服务连接成功", "SUCCESS")
|
||||
|
||||
stop_event = stop_event or asyncio.Event() # 如果外部没传,自己创建
|
||||
uri = "wss://dongdong.jd.com/workbench/websocket"
|
||||
headers = {"cookie": cookies_str}
|
||||
|
||||
self._log(f"🔵 开始连接WebSocket: {uri}", "INFO")
|
||||
|
||||
# 充值重连计数器
|
||||
self.reconnect_attempts = 0
|
||||
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
self._log(f"🔄 尝试连接WebSocket", "INFO")
|
||||
async with websockets.connect(uri, additional_headers=headers, ping_interval=6, ping_timeout=10, close_timeout=1, max_queue=1024) as ws:
|
||||
# 连接成功,重置重连计数器
|
||||
self.reconnect_attempts = 0
|
||||
self._log("✅ WebSocket-JD连接成功", "SUCCESS")
|
||||
await self.init_wss(ws, aid, pin_zj)
|
||||
# === 验证连接成功的核心指标 ===
|
||||
# print(f"✅ 连接状态: open={ws.open}, closed={ws.closed}")
|
||||
print(f"🖥️ 服务端地址: {ws.remote_address}")
|
||||
|
||||
# --- 注册连接信息到全局管理
|
||||
shop_key = f"京东:{store['id']}"
|
||||
loop = asyncio.get_running_loop()
|
||||
entry = self.ws_manager.on_connect(
|
||||
shop_key=shop_key,
|
||||
ws=ws,
|
||||
vender_id=vender_id,
|
||||
aid=aid,
|
||||
pin_zj=pin_zj,
|
||||
platform="京东",
|
||||
loop=loop
|
||||
)
|
||||
|
||||
await self.waiter_status_switch(ws=ws, aid=aid, pin_zj=pin_zj)
|
||||
|
||||
heartbeat_task = asyncio.create_task(self.heartbeat_loop(ws, aid, pin_zj))
|
||||
message_tasks = set()
|
||||
|
||||
try:
|
||||
while not stop_event.is_set(): # 检查是否收到中止信号
|
||||
try:
|
||||
print(f"等待监听消息-{datetime.now()}")
|
||||
response = await asyncio.wait_for(ws.recv(), timeout=1)
|
||||
print(f"原始消息类型:{type(response)}, 消息体为: {response}")
|
||||
await self.process_incoming_message(response, ws, aid, pin_zj, vender_id, store)
|
||||
|
||||
# 安全解析消息
|
||||
json_resp = json.loads(response) if isinstance(response, (str, bytes)) else response
|
||||
|
||||
print(json_resp)
|
||||
|
||||
ver = json_resp.get("ver")
|
||||
print(f"版本{ver}")
|
||||
except asyncio.TimeoutError:
|
||||
continue
|
||||
except websockets.ConnectionClosed:
|
||||
# 连接关闭 跳出内层循环进行重连
|
||||
break
|
||||
except Exception as e:
|
||||
self._log(f"消息处理异常: {e}", "ERROR")
|
||||
continue
|
||||
await asyncio.sleep(sleep_time)
|
||||
###
|
||||
##{'ver': '4.2', 'mid': 366566937, 'body': {'chatinfo': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10143502227300', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'label': 1, 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': 'ce7f35b51a9c00ac898b0fe08608674a', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd01C5XRGQHGNJBSFYWWA7RF54QXYHF2N34TM32NGLZV6YAAPPNKWLAIQ2MZV25T4QZ2TJE4HRF6UZ2L3THX7I2BLLB37YVAWKR2BYGRRPA01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'param': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10143502227300', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'label': 1, 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': 'ce7f35b51a9c00ac898b0fe08608674a', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd01C5XRGQHGNJBSFYWWA7RF54QXYHF2N34TM32NGLZV6YAAPPNKWLAIQ2MZV25T4QZ2TJE4HRF6UZ2L3THX7I2BLLB37YVAWKR2BYGRRPA01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'type': 'text', 'requestData': {'entry': 'sdk_item', 'venderId': '11961298'}, 'content': '你好', 'sid': 'ce7f35b51a9c00ac898b0fe08608674a'}, 'type': 'chat_message', 'clientTime': 1755076542320, 'datetime': '2025-08-13 17:15:42', 'len': 0, 'from': {'app': 'im.customer', 'art': '', 'clientType': 'android', 'pin': 'jd_thpotntctwys'}, 'subType': 'text', 'id': 'bc3c42a706fa4fa482ff565304c7dfbb', 'to': {'app': 'im.waiter', 'clientType': 'comet', 'pin': 'KLD测试'}, 'lang': 'zh_CN', 'timestamp': 1755076542671}
|
||||
# {'ver': '4.2', 'mid': 366566966, 'body': {'chatinfo': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10052172306055', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': '538fc3761474ea693812ceed4b39639c', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd014TJZZMUXFLXYGJJJ4M3HY3PTU4PBA22SPDIXDWOGZ7XTUTOWTY4LU3VWN6OKDOJPJOVDINMCJXCSPSG5X2K6KWHNQJQOROB57LDG5EY01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'param': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10052172306055', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': '538fc3761474ea693812ceed4b39639c', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd014TJZZMUXFLXYGJJJ4M3HY3PTU4PBA22SPDIXDWOGZ7XTUTOWTY4LU3VWN6OKDOJPJOVDINMCJXCSPSG5X2K6KWHNQJQOROB57LDG5EY01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'type': 'text', 'requestData': {'entry': 'sdk_item', 'venderId': '11961298'}, 'content': '你好啊', 'sid': '538fc3761474ea693812ceed4b39639c'}, 'type': 'chat_message', 'clientTime': 1755592905140, 'datetime': '2025-08-19 16:41:45', 'len': 0, 'from': {'app': 'im.customer', 'art': '', 'clientType': 'android', 'pin': 'jd_thpotntctwys'}, 'subType': 'text', 'id': 'd31d369f17f24b05abbe2b7c334f340e', 'to': {'app': 'im.waiter', 'clientType': 'comet', 'pin': 'KLD测试'}, 'lang': 'zh_CN', 'timestamp': 1755592905232}
|
||||
# {'ver': '4.2', 'mid': 366566984, 'body': {'chatinfo': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10143502227300', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'label': 1, 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': '5b5e044c73ee243b7e67eeca5b11393c', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd01ZC7NRD2EX45UN4Q5IZUQC4VLKXIKR7LWP2HC45VQRBDXEYHACT6U5KFBIAI52JBHYCO5BLMOHXTYUYU35RQPB2XA37HL4MPP7CXET7Q01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'param': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10143502227300', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'label': 1, 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': '5b5e044c73ee243b7e67eeca5b11393c', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd01ZC7NRD2EX45UN4Q5IZUQC4VLKXIKR7LWP2HC45VQRBDXEYHACT6U5KFBIAI52JBHYCO5BLMOHXTYUYU35RQPB2XA37HL4MPP7CXET7Q01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'type': 'text', 'requestData': {'entry': 'sdk_item', 'venderId': '11961298'}, 'content': '您好', 'sid': '5b5e044c73ee243b7e67eeca5b11393c'}, 'type': 'chat_message', 'clientTime': 1755595443735, 'datetime': '2025-08-19 17:24:03', 'len': 0, 'from': {'app': 'im.customer', 'art': '', 'clientType': 'android', 'pin': 'jd_thpotntctwys'}, 'subType': 'text', 'id': '800deaf802f9436b98937bb084ee2a56', 'to': {'app': 'im.waiter', 'clientType': 'comet', 'pin': 'KLD测试'}, 'lang': 'zh_CN', 'timestamp': 1755595443839}
|
||||
# {'ver': '4.2', 'mid': 366566986, 'body': {'chatinfo': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10143502227300', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'label': 1, 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': '5b5e044c73ee243b7e67eeca5b11393c', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd01ZC7NRD2EX45UN4Q5IZUQC4VLKXIKR7LWP2HC45VQRBDXEYHACT6U5KFBIAI52JBHYCO5BLMOHXTYUYU35RQPB2XA37HL4MPP7CXET7Q01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'param': {'venderId': '11961298', 'isJdSuperMarket': '0', 'pid': '10143502227300', 'source': 'jimitwo_service_smart_sdk', 'deviceNo': 'dd_dvc_aes_30EA91E824A2F36365F7B7193C10B76A8842E4E08C0DA687EC9BEB307FCF7195', 'label': 1, 'IMService': False, 'distinguishPersonJimi': 2, 'proVer': 'smart_android_15.2.0', 'sid': '5b5e044c73ee243b7e67eeca5b11393c', 'entry': 'sdk_item', 'leaveMsgTable': 1, 'venderName': 'TYBOY康路达数字科技专卖店', 'disputeId': -1, 'ddSessionType': '1', 'appId': 'im.waiter', 'systemVer': 'android_13_V2239A', 'eidtoken': 'jdd01ZC7NRD2EX45UN4Q5IZUQC4VLKXIKR7LWP2HC45VQRBDXEYHACT6U5KFBIAI52JBHYCO5BLMOHXTYUYU35RQPB2XA37HL4MPP7CXET7Q01234567', 'auctionType': '0', 'region': 'CN', 'verification': 'slide'}, 'type': 'text', 'requestData': {'entry': 'sdk_item', 'venderId': '11961298'}, 'content': '我先自己看看谢谢您', 'sid': '5b5e044c73ee243b7e67eeca5b11393c'}, 'type': 'chat_message', 'clientTime': 1755595460153, 'datetime': '2025-08-19 17:24:20', 'len': 0, 'from': {'app': 'im.customer', 'art': '', 'clientType': 'android', 'pin': 'jd_thpotntctwys'}, 'subType': 'text', 'id': 'a3d4de984f2d4811952f8ba872850bc2', 'to': {'app': 'im.waiter', 'clientType': 'comet', 'pin': 'KLD测试'}, 'lang': 'zh_CN', 'timestamp': 1755595460274}
|
||||
except Exception as e:
|
||||
logger.error(f"接收对应监控消息时候产生特殊错误 , 错误信息为{e}")
|
||||
|
||||
finally:
|
||||
# 清理资源
|
||||
heartbeat_task.cancel()
|
||||
try:
|
||||
await heartbeat_task
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
self._log("🔄 连接断开,准备重连", "INFO")
|
||||
except websockets.ConnectionClosed as e:
|
||||
self._log(f"🔌 连接已关闭: {e.code} {e.reason}", "WARNING")
|
||||
if not await self.handle_reconnect(e):
|
||||
break
|
||||
|
||||
except (websockets.WebSocketException, aiohttp.ClientError, OSError) as e:
|
||||
self._log(f"🌐 网络异常: {type(e).__name__} - {str(e)}", "WARNING")
|
||||
if not await self.handle_reconnect(e):
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
self._log(f"⚠️ 未知异常: {type(e).__name__} - {str(e)}", "ERROR")
|
||||
if not await self.handle_reconnect(e):
|
||||
break
|
||||
|
||||
# 关闭后端服务连接
|
||||
if self.backend_connected:
|
||||
await self.backend_service.close()
|
||||
self.backend_connected = False
|
||||
self._log("🛑 消息监听已停止", "INFO")
|
||||
|
||||
|
||||
# 新增: GUI集成包装器类
|
||||
# class JDListenerForGUI:
|
||||
# """用于GUI集成的JD监听包装器 ()"""
|
||||
#
|
||||
# def __init__(self, log_callback=None):
|
||||
# self.fix_jd_util = FixJdCookie(log_callback)
|
||||
# self.log_callback = log_callback
|
||||
# self.running = False
|
||||
# self.stop_event = None
|
||||
# self.username = None
|
||||
# self.password = None
|
||||
#
|
||||
# def _log(self, message, log_type="INFO"):
|
||||
# """处理日志输出"""
|
||||
# if self.log_callback:
|
||||
# self.log_callback(message, log_type)
|
||||
# else:
|
||||
# print(f"[{log_type}] {message}")
|
||||
#
|
||||
# async def start_listening(self, username, password):
|
||||
# """启动监听的主方法"""
|
||||
# try:
|
||||
# # 存储用户名和密码
|
||||
# self.username = username
|
||||
# self.password = password
|
||||
#
|
||||
# self._log("🔵 开始JD平台连接流程", "INFO")
|
||||
# print("🔵 开始JD平台连接流程 - 调试断点1")
|
||||
#
|
||||
# # 1. 获取店铺信息
|
||||
# self._log("🔵 步骤2: 获取店铺信息...", "INFO")
|
||||
# print("🔵 步骤2: 获取店铺信息... - 调试断点2")
|
||||
# store_today = self.fix_jd_util.get_today_store()
|
||||
# if not store_today:
|
||||
# self._log("❌ 未找到店铺信息", "ERROR")
|
||||
# print("❌ 未找到店铺信息")
|
||||
# return False
|
||||
# self._log(f"✅ 获取到店铺信息: {store_today.get("id", '未知')}", "SUCCESS")
|
||||
# print(f"✅ 获取到店铺信息: {store_today.get("id", '未知')}")
|
||||
#
|
||||
# # 2. 连接后端服务获取cookie
|
||||
# self._log("🔵 步骤3: 连接后端服务获取cookie...", "INFO")
|
||||
# store_id = str(store_today.get('id', ''))
|
||||
#
|
||||
# jd_cookie = await self.fix_jd_util.connect_backend_service(store_id, username, password)
|
||||
#
|
||||
# if not jd_cookie or not jd_cookie.get('status'):
|
||||
# self._log("❌ 从后端服务获取cookie失败", "ERROR")
|
||||
# if jd_cookie and jd_cookie.get('verify_link'):
|
||||
# self._log(f"❌ 需要验证登录,验证链接: {jd_cookie.get('verify_link')}", "ERROR")
|
||||
# return False
|
||||
#
|
||||
# self._log("✅ 从后端服务获取cookie成功", "SUCCESS")
|
||||
# cookies_str = jd_cookie.get('cookie')
|
||||
# self._log(f"📦 获取到cookie: {cookies_str[:50] + '...' if cookies_str else '无'}", "DEBUG")
|
||||
#
|
||||
# # 3. 获取配置信息
|
||||
# self._log("🔵 步骤4: 获取配置信息...", "INFO")
|
||||
# config = None
|
||||
# for i in range(3):
|
||||
# try:
|
||||
# config = self.fix_jd_util.get_config(cookies_str)
|
||||
# if config and config.get('data'):
|
||||
# self._log(f"✅ 第{i + 1}次尝试获取配置成功", "SUCCESS")
|
||||
# break
|
||||
# else:
|
||||
# self._log(f"⚠️ 第{i + 1}次尝试获取配置返回空数据", "WARNING")
|
||||
# except Exception as e:
|
||||
# self._log(f"获取配置异常({i + 1}/3): {str(e)}", "WARNING")
|
||||
# await asyncio.sleep(3)
|
||||
#
|
||||
# if not config or not config.get('data'):
|
||||
# self._log("获取配置失败", "ERROR")
|
||||
# return False
|
||||
#
|
||||
# # 4. 提取必要参数
|
||||
# self._log("🔵 步骤5: 提取配置参数...", "INFO")
|
||||
# aid = config["data"].get("aid")
|
||||
# vender_id = config["data"].get("venderId")
|
||||
# pin_zj = config["data"].get("pin", "").lower()
|
||||
#
|
||||
# if not all([aid, vender_id, pin_zj]):
|
||||
# self._log("❌ 登录信息不完整", "ERROR")
|
||||
# return False
|
||||
#
|
||||
# self._log(f"获取到配置: aid={aid}, vender_id={vender_id}, pin_zj={pin_zj}", "INFO")
|
||||
#
|
||||
# # 5. 启动监听
|
||||
# self._log("🔵 步骤6: 启动消息监听...", "INFO")
|
||||
# self.stop_event = asyncio.Event()
|
||||
# self.running = True
|
||||
#
|
||||
# self._log("🎉开始监听JD平台消息...", "SUCCESS")
|
||||
#
|
||||
# # 调用实际的监听方法
|
||||
# await self.fix_jd_util.message_monitoring(
|
||||
# cookies_str=cookies_str,
|
||||
# aid=aid,
|
||||
# pin_zj=pin_zj,
|
||||
# vender_id=vender_id,
|
||||
# store=store_today,
|
||||
# stop_event=self.stop_event,
|
||||
# username=username,
|
||||
# password=password
|
||||
# )
|
||||
#
|
||||
# return True
|
||||
#
|
||||
# except Exception as e:
|
||||
# self._log(f"监听过程中出现严重错误: {str(e)}", "ERROR")
|
||||
# import traceback
|
||||
# self._log(f"错误详情: {traceback.format_exc()}", "DEBUG")
|
||||
# return False
|
||||
#
|
||||
# def stop_listening(self):
|
||||
# """停止监听"""
|
||||
# if self.stop_event:
|
||||
# self.stop_event.set()
|
||||
# self.running = False
|
||||
# self._log("JD监听已停止", "INFO")
|
||||
|
||||
# 新增: GUI集成包装器类
|
||||
class JDListenerForGUI:
|
||||
"""用于GUI集成的JD监听包装器 ()"""
|
||||
|
||||
def __init__(self, log_callback=None):
|
||||
self.fix_jd_util = FixJdCookie(log_callback)
|
||||
self.log_callback = log_callback
|
||||
self.running = False
|
||||
self.stop_event = None
|
||||
|
||||
def _log(self, message, log_type="INFO"):
|
||||
"""处理日志输出"""
|
||||
if self.log_callback:
|
||||
self.log_callback(message, log_type)
|
||||
else:
|
||||
print(f"[{log_type}] {message}")
|
||||
|
||||
async def start_listening(self, username, password):
|
||||
"""启动监听的主方法"""
|
||||
try:
|
||||
self._log("🔵 开始JD平台连接流程", "INFO")
|
||||
print("🔵 开始JD平台连接流程 - 调试断点1")
|
||||
|
||||
# 1. 获取店铺信息
|
||||
self._log("🔵 步骤2: 获取店铺信息...", "INFO")
|
||||
print("🔵 步骤2: 获取店铺信息... - 调试断点2")
|
||||
store_today = self.fix_jd_util.get_today_store()
|
||||
if not store_today:
|
||||
self._log("❌ 未找到店铺信息", "ERROR")
|
||||
print("❌ 未找到店铺信息")
|
||||
return False
|
||||
self._log(f"✅ 获取到店铺信息: {store_today.get("id", '未知')}", "SUCCESS")
|
||||
print(f"✅ 获取到店铺信息: {store_today.get("id", '未知')}")
|
||||
|
||||
cookie_str = store_today.get('platform_cookie')
|
||||
self._log(f"📦 当前存储的cookie: {cookie_str[:50] + '...' if cookie_str else '无'}", "DEBUG")
|
||||
|
||||
# 2. 获取或更新cookie - 在这里设置断点②
|
||||
self._log("🔵 步骤3: 获取或更新JD cookie...", "INFO")
|
||||
# 2. 获取或更新cookie
|
||||
jd_login_cookie = self.fix_jd_util.get_cookies(
|
||||
username=username,
|
||||
password=password,
|
||||
cookies_str=cookie_str
|
||||
)
|
||||
|
||||
if not jd_login_cookie['status']:
|
||||
fail_status = jd_login_cookie.get('verify_link', None)
|
||||
if fail_status:
|
||||
self._log(f"❌ JD登录失败: , 失败类型为二次验证(手机验证码) 对应url:{fail_status}", "ERROR")
|
||||
else:
|
||||
# 表示没有返回verify_url 未知错误
|
||||
self._log(f"❌ JD登录失败: , 失败类型为:{fail_status} 未知错误 请单独测试login方法")
|
||||
return False
|
||||
|
||||
self._log("✅ JD登录成功", "SUCCESS")
|
||||
self._log(f"📦 获取到cookie: {jd_login_cookie['cookie'][:50] + '...'}", "DEBUG")
|
||||
|
||||
self._log("🔵 步骤4: 获取配置信息...", "INFO")
|
||||
# 3. 获取配置信息
|
||||
config = None
|
||||
for i in range(3):
|
||||
try:
|
||||
config = self.fix_jd_util.get_config(jd_login_cookie['cookie'])
|
||||
if config and config.get('data'):
|
||||
self._log(f"✅ 第{i + 1}次尝试获取配置成功", "SUCCESS")
|
||||
break
|
||||
else:
|
||||
self._log(f"⚠️ 第{i + 1}次尝试获取配置返回空数据", "WARNING")
|
||||
except Exception as e:
|
||||
self._log(f"获取配置异常({i + 1}/3): {str(e)}", "WARNING")
|
||||
await asyncio.sleep(3)
|
||||
|
||||
if not config or not config.get('data'):
|
||||
self._log("获取配置失败", "ERROR")
|
||||
return False
|
||||
|
||||
# 4. 提取必要参数
|
||||
self._log("🔵 步骤5: 提取配置参数...", "INFO")
|
||||
aid = config["data"].get("aid")
|
||||
vender_id = config["data"].get("venderId")
|
||||
pin_zj = config["data"].get("pin", "").lower()
|
||||
|
||||
if not all([aid, vender_id, pin_zj]):
|
||||
self._log("❌ 登录信息不完整", "ERROR")
|
||||
return False
|
||||
|
||||
self._log(f"获取到配置: aid={aid}, vender_id={vender_id}, pin_zj={pin_zj}", "INFO")
|
||||
|
||||
# 5. 启动监听
|
||||
self._log("🔵 步骤6: 启动消息监听...", "INFO")
|
||||
self.stop_event = asyncio.Event()
|
||||
self.running = True
|
||||
|
||||
self._log("🎉开始监听JD平台消息...", "SUCCESS")
|
||||
|
||||
# 调用实际的监听方法
|
||||
await self.fix_jd_util.message_monitoring(
|
||||
cookies_str=jd_login_cookie['cookie'],
|
||||
aid=aid,
|
||||
pin_zj=pin_zj,
|
||||
vender_id=vender_id,
|
||||
store=store_today,
|
||||
stop_event=self.stop_event
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
self._log(f"监听过程中出现严重错误: {str(e)}", "ERROR")
|
||||
import traceback
|
||||
self._log(f"错误详情: {traceback.format_exc()}", "DEBUG")
|
||||
return False
|
||||
|
||||
async def start_with_cookies(self, store_id: str, cookies: str):
|
||||
"""使用下发的cookies与store_id直接建立JD平台WS并开始监听"""
|
||||
try:
|
||||
self._log("🔵 [JD] 收到后端登录指令,开始使用cookies连接平台", "INFO")
|
||||
|
||||
# 获取平台配置
|
||||
config = None
|
||||
for i in range(3):
|
||||
try:
|
||||
config = self.fix_jd_util.get_config(cookies)
|
||||
if config and config.get('data'):
|
||||
self._log(f"✅ 第{i + 1}次尝试获取配置成功", "SUCCESS")
|
||||
break
|
||||
else:
|
||||
self._log(f"⚠️ 第{i + 1}次尝试获取配置返回空数据", "WARNING")
|
||||
except Exception as e:
|
||||
self._log(f"获取配置异常({i + 1}/3): {str(e)}", "WARNING")
|
||||
await asyncio.sleep(3)
|
||||
|
||||
if not config or not config.get('data'):
|
||||
self._log("获取配置失败", "ERROR")
|
||||
return False
|
||||
|
||||
aid = config["data"].get("aid")
|
||||
vender_id = config["data"].get("venderId")
|
||||
pin_zj = config["data"].get("pin", "").lower()
|
||||
|
||||
if not all([aid, vender_id, pin_zj]):
|
||||
self._log("❌ 登录信息不完整", "ERROR")
|
||||
return False
|
||||
|
||||
# 建立与后端的AI通道(确保使用GUI的store_id)
|
||||
await self.fix_jd_util.connect_backend_service(store_id)
|
||||
|
||||
# 启动监听
|
||||
self.stop_event = asyncio.Event()
|
||||
self.running = True
|
||||
store = {'id': store_id}
|
||||
self._log("🎉 [JD] 开始监听平台消息", "SUCCESS")
|
||||
|
||||
await self.fix_jd_util.message_monitoring(
|
||||
cookies_str=cookies,
|
||||
aid=aid,
|
||||
pin_zj=pin_zj,
|
||||
vender_id=vender_id,
|
||||
store=store,
|
||||
stop_event=self.stop_event
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
self._log(f"[JD] 监听过程中出现错误: {str(e)}", "ERROR")
|
||||
import traceback
|
||||
self._log(f"错误详情: {traceback.format_exc()}", "DEBUG")
|
||||
return False
|
||||
|
||||
def stop_listening(self):
|
||||
"""停止监听"""
|
||||
if self.stop_event:
|
||||
self.stop_event.set()
|
||||
self.running = False
|
||||
self._log("JD监听已停止", "INFO")
|
||||
|
||||
|
||||
async def main():
|
||||
username = "KLD测试"
|
||||
password = "kld168168"
|
||||
fix_jd_util = FixJdCookie()
|
||||
store_today = fix_jd_util.get_today_store()
|
||||
|
||||
# 检查店铺信息
|
||||
if not store_today:
|
||||
logger.error("❌ 未找到店铺信息")
|
||||
return
|
||||
|
||||
store_id = str(store_today.get('id', ''))
|
||||
logger.info(f"✅ 获取到店铺信息: {store_id}")
|
||||
|
||||
try:
|
||||
# 1. 直接连接后端服务获取 cookie
|
||||
logger.info("🔵 步骤1: 连接后端服务获取 cookie...")
|
||||
jd_cookie = await fix_jd_util.connect_backend_service(store_id, username, password)
|
||||
print(f"完整的cookie数据: {jd_cookie}")
|
||||
|
||||
if not jd_cookie or not jd_cookie.get('status'):
|
||||
logger.error("❌ 从后端服务获取 cookie 失败")
|
||||
if jd_cookie and jd_cookie.get('verify_link'):
|
||||
logger.error(f"❌ 需要验证登录,验证链接: {jd_cookie.get('verify_link')}")
|
||||
return
|
||||
|
||||
cookies_str = jd_cookie.get('cookie')
|
||||
logger.info("✅ 从后端服务获取 cookie 成功")
|
||||
logger.debug(f"📦 获取到 cookie: {cookies_str[:50] + '...' if cookies_str else '无'}")
|
||||
|
||||
# 测试cookie后端生成的有效性
|
||||
# cookies_str = "shshshfpa=112082d7-6f59-f35d-093a-e4c035938ab8-1754961318; shshshfpx=112082d7-6f59-f35d-093a-e4c035938ab8-1754961318; __jdu=17549613198151684402245; user-key=13d41f1d-5d8a-447e-a3d1-19c964e2fa13; __jdv=76161171|direct|-|none|-|1756259208627; areaId=18; ipLoc-djd=18-1482-48942-49052; pinId=EifU7rHmf-gwaaxnNveDFw; _tp=%2Bw%2Fs5xFMS9g0SkUd93EGxqh4USt1M5LwIyzTR4TbgCM%3D; _pst=KLD%E6%B5%8B%E8%AF%95; pin=KLD%E6%B5%8B%E8%AF%95; unick=u40d47u5ckctnz; PCSYCityID=CN_430000_430100_0; ceshi3.com=000; sdtoken=AAbEsBpEIOVjqTAKCQtvQu17tqE2au0-pftQOStCUKRw9JX4gfXHESNiN_EgrTvDv8qS5IZHipleuQxIX9JXWojJS8sKju6Vh1Qqt5LjakfSeWqqAOL-HhXeBn9m; shshshfpb=BApXS1gvPG_xA1izHnR4d6bvzjbeOVTtiBhbXFDdg9xJ1Mh6uh462; 3AB9D23F7A4B3CSS=jdd03OFWZGTHWHQYLKSX5BEWHXMTLYAHXEEXC7HBOIZDBIPLMQZT5LTHKICALRZU5ZDL6X6T3NMHRNSJJDX6BTEI6AVJS5IAAAAMZDDKTS5YAAAAACJZVYQP7FYJA3UX; _gia_d=1; wlfstk_smdl=0whbpvk7ixj27lbykeeb8rh6iulon3fo; __jda=95931165.17549613198151684402245.1754961320.1757039732.1757053789.21; __jdb=95931165.30.17549613198151684402245|21.1757053789; __jdc=95931165; 3AB9D23F7A4B3C9B=OFWZGTHWHQYLKSX5BEWHXMTLYAHXEEXC7HBOIZDBIPLMQZT5LTHKICALRZU5ZDL6X6T3NMHRNSJJDX6BTEI6AVJS5I; TrackID=1C24wlDX-QPSyJRaB_1YHqCLhBW6qIo2stht_nwl5g9fGI-lJpP-CZT3TaCr9QVppcvhilhcCe1VhgXMKGWao6Fd3wJ5bQhJ9w9VwWcYOySsXfbCTQbteFWevVN1ZQYp9; thor=4E136F9D9458703D01BE17544D30601F9649F79B89E5FC150CA91054C788CAA1C82670080466F219573AE7FD6EB9ABDF9F52D520671373DAD721CC3B78613FABC99ADA1FAC8E92CDC42F5131682B1F008727F1BA49783B055AFED9349D0B79E53A51F059A1DDE3FC181DD38D1B388D829CE8ADD775D0D30C38A8CAD0519DCD0C; flash=3_KFKaImBVn2spH8stTd9wjKlZQTxgYcZCPXXP_axvJMphR3w29aJNU2c2qPReKxWHRX1lzJ7MfD9iQmHQI-2cKp0dYzs6YsH9eDyB3lQxuu6MtkM8jCiBynVSdRBnr21oDrLKGMeYG6yYlcEsAsbe8OC-yKO69758MJYyMZd_4soV; light_key=AASBKE7rOxgWQziEhC_QY6yakCROyWTrRIF9K9uCpw_IcR8gGNaL7IM6AQuVa-3pJoC9wTze; logining=1; rita=A1EA9FF92ADE7FC61C825E83F126B9E97EF9243BEED9B77E4F7110D6081254A8EEAA66B26BFA00E08CBD8B0C88DD3D292CAD14839A50184501755B761A11F679F63D9DAA76E6785799D2F78AE378F76F32E05C1914C1132995B15CC5F79AFB9314A9D6FE7911DAFE1D958906C016E724"
|
||||
|
||||
# 2. 获取配置信息
|
||||
logger.info("🔵 步骤2: 获取配置信息...")
|
||||
config = None
|
||||
for i in range(3):
|
||||
try:
|
||||
config = fix_jd_util.get_config(cookies_str)
|
||||
if config and config.get('data'):
|
||||
logger.info(f"✅ 第{i + 1}次尝试获取配置成功")
|
||||
break
|
||||
else:
|
||||
logger.warning(f"⚠️ 第{i + 1}次尝试获取配置返回空数据")
|
||||
except Exception as e:
|
||||
logger.error(f"获取配置异常({i + 1}/3): {e}")
|
||||
if i == 2:
|
||||
return
|
||||
await asyncio.sleep(3) # 使用异步等待
|
||||
|
||||
if not config or not config.get('data'):
|
||||
logger.error("❌ 获取配置失败")
|
||||
return
|
||||
|
||||
# 3. 提取必要参数
|
||||
logger.info("🔵 步骤3: 提取配置参数...")
|
||||
aid = config["data"].get("aid")
|
||||
vender_id = config["data"].get("venderId")
|
||||
pin_zj = config["data"].get("pin", "").lower()
|
||||
|
||||
if not all([aid, vender_id, pin_zj]):
|
||||
logger.error("❌ 登录信息不完整,需要重新登录")
|
||||
return
|
||||
|
||||
logger.info(f"✅ 获取到配置: aid={aid}, vender_id={vender_id}, pin_zj={pin_zj}")
|
||||
|
||||
# 4. 启动监听
|
||||
logger.info("🔵 步骤4: 启动消息监听...")
|
||||
stop_event = asyncio.Event()
|
||||
|
||||
try:
|
||||
await fix_jd_util.message_monitoring(
|
||||
cookies_str=cookies_str,
|
||||
aid=aid,
|
||||
pin_zj=pin_zj,
|
||||
vender_id=vender_id,
|
||||
store=store_today,
|
||||
stop_event=stop_event,
|
||||
username=username,
|
||||
password=password
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 监听过程中出现错误: {e}")
|
||||
import traceback
|
||||
logger.error(f"错误详情: {traceback.format_exc()}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ 主程序执行过程中出现错误: {e}")
|
||||
import traceback
|
||||
logger.error(f"错误详情: {traceback.format_exc()}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
# asyncio.run(new_test_login())
|
||||
0
dist/main/_internal/Utils/JD/__init__.py
vendored
Normal file
BIN
dist/main/_internal/Utils/JD/__pycache__/JdUtils.cpython-313.pyc
vendored
Normal file
BIN
dist/main/_internal/Utils/JD/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
3158
dist/main/_internal/Utils/Pdd/PddUtils.py
vendored
Normal file
0
dist/main/_internal/Utils/Pdd/__init__.py
vendored
Normal file
BIN
dist/main/_internal/Utils/Pdd/__pycache__/PddUtils.cpython-313.pyc
vendored
Normal file
BIN
dist/main/_internal/Utils/Pdd/__pycache__/__init__.cpython-313.pyc
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_asyncio.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_bz2.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_ctypes.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_ctypes_test.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_decimal.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_elementtree.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_hashlib.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_lzma.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_multiprocessing.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_overlapped.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_queue.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_socket.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_sqlite3.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_ssl.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testbuffer.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testcapi.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testclinic.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testclinic_limited.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testconsole.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testimportmultiple.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testinternalcapi.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testlimitedcapi.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testmultiphase.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_testsinglephase.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_tkinter.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_uuid.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_wmi.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/_zoneinfo.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/libcrypto-3.dll
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/libffi-8.dll
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/libssl-3.dll
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/py.ico
vendored
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/pyc.ico
vendored
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/pyd.ico
vendored
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/pyexpat.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/python_lib.cat
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/select.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/sqlite3.dll
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/tcl86t.dll
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/tk86t.dll
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/unicodedata.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/winsound.pyd
vendored
Normal file
BIN
dist/main/_internal/Utils/PythonNew32/DLLs/zlib1.dll
vendored
Normal file
173
dist/main/_internal/Utils/PythonNew32/DOEM.py
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
import ctypes
|
||||
import asyncio
|
||||
import websockets
|
||||
import hashlib
|
||||
import time
|
||||
import json
|
||||
|
||||
# 加载DLL文件
|
||||
sainiu_api = ctypes.CDLL('SaiNiuApi.dll')
|
||||
|
||||
# 定义函数参数类型和返回值类型
|
||||
sainiu_api.Access_ServerStart.argtypes = [
|
||||
ctypes.c_int,
|
||||
ctypes.c_bool,
|
||||
ctypes.c_bool,
|
||||
ctypes.c_bool,
|
||||
ctypes.c_bool,
|
||||
ctypes.c_int,
|
||||
ctypes.c_char_p,
|
||||
ctypes.c_bool,
|
||||
ctypes.c_bool
|
||||
]
|
||||
sainiu_api.Access_ServerStart.restype = ctypes.c_char_p # 返回值类型为文本型(字符串)
|
||||
|
||||
# 调用函数时传入的参数
|
||||
port = 3030 # WS以及HTTP的请求端口,默认3030
|
||||
web_socket = True # 是否开启WebSocket
|
||||
http_server = True # 是否开启HTTP请求
|
||||
remote = False # 是否开启远程请求
|
||||
log = True # 是否开启日志功能
|
||||
ws_max = 0 # 设置WS客户端最大连接数,0 = 不限制
|
||||
sign_key = b'111111' # 签名key,留空表示无需签名请求 调试时建议修改为空
|
||||
sha256 = True # sign签名方式,假 = md5,真 = hmac - sha256
|
||||
version_tip = True # 是否开启SDK版本与DLL不一致时的刷新提示
|
||||
|
||||
# 启动服务器
|
||||
result = sainiu_api.Access_ServerStart(
|
||||
port,
|
||||
web_socket,
|
||||
http_server,
|
||||
remote,
|
||||
log,
|
||||
ws_max,
|
||||
sign_key,
|
||||
sha256,
|
||||
version_tip
|
||||
)
|
||||
|
||||
print(f"Access_ServerStart 服务器启动: {result.decode('gbk')}")
|
||||
|
||||
# 计算sign值
|
||||
def sign_GetSign(signKey, post, time, sha256=False):
|
||||
# 拼接字符串
|
||||
data = post + str(time) + signKey
|
||||
|
||||
# 将字符串转换为字节集
|
||||
byte_data = data.encode('utf-8')
|
||||
|
||||
# 根据sha256参数选择哈希算法
|
||||
if sha256:
|
||||
hash_object = hashlib.sha256(byte_data)
|
||||
else:
|
||||
hash_object = hashlib.md5(byte_data)
|
||||
|
||||
# 获取十六进制表示并转换为小写
|
||||
sign = hash_object.hexdigest().lower()
|
||||
|
||||
return sign
|
||||
|
||||
async def connect_to_websocket():
|
||||
while True:
|
||||
try:
|
||||
# 获取当前的13位时间戳(毫秒级)
|
||||
current_time_ws = int(time.time() * 1000)
|
||||
|
||||
# 计算签名,参数post参数为"ws"不可修改,signKey为自定义密匙,sha256参数为True选择sha256算法,为False则选择md5算法,需要与Access_StartServer的参数一致
|
||||
ws_sign = sign_GetSign(sign_key.decode('utf-8'), "ws", current_time_ws, sha256)
|
||||
|
||||
# 构建URI
|
||||
uri = f"ws://127.0.0.1:{port}?time={current_time_ws}&sign={ws_sign}"
|
||||
|
||||
async with websockets.connect(uri) as websocket:
|
||||
print("已连接到ws服务器")
|
||||
|
||||
# 再次获取当前的13位时间戳(毫秒级)以避免签名超时
|
||||
current_time_json = int(time.time() * 1000)
|
||||
|
||||
# 计算JSON数据的签名,参数post参数为"init"
|
||||
json_sign = sign_GetSign(sign_key.decode('utf-8'), "Init", current_time_json, sha256)
|
||||
|
||||
# 发送JSON数据
|
||||
message = {
|
||||
"type": "Invoke_SaiNiu",
|
||||
"traceId": "Access_Init",
|
||||
"codeType": "Access",
|
||||
"post": "Init",
|
||||
"data": {
|
||||
"AccessType": 0,
|
||||
"AccessId": "AccessId", #替换成授权的AccessId,
|
||||
"AccessKey": "AccessKey", #替换成授权的AccessKey
|
||||
"ForceLogin": True
|
||||
},
|
||||
"time": current_time_json,
|
||||
"sign": json_sign
|
||||
}
|
||||
|
||||
await websocket.send(json.dumps(message))
|
||||
print(f"Sent message: {message}")
|
||||
|
||||
try:
|
||||
while True:
|
||||
# 接收来自服务器的消息
|
||||
response = await websocket.recv()
|
||||
print(f"接收来自服务器的消息: {response}")
|
||||
|
||||
# 解析响应消息
|
||||
response_data = json.loads(response)
|
||||
|
||||
# 判断traceId是否匹配
|
||||
if response_data.get("traceId") == "Access_Init":
|
||||
# 再次获取当前的13位时间戳(毫秒级)以避免签名超时
|
||||
current_time_sys_init = int(time.time() * 1000)
|
||||
|
||||
# 计算新的JSON数据的签名,参数post参数为"SysInit"
|
||||
sys_init_sign = sign_GetSign(sign_key.decode('utf-8'), "SysInit", current_time_sys_init, sha256)
|
||||
|
||||
# 发送新的JSON数据
|
||||
new_message = {
|
||||
"type": "Invoke_SaiNiu",
|
||||
"traceId": "0470bf9489729b2e8a2126a04ab3e272",#自定义返回的traceId
|
||||
"codeType": "Access",
|
||||
"post": "SysInit",
|
||||
"data": {
|
||||
"number": 20,
|
||||
"port": 3030,
|
||||
"token": True,
|
||||
"connect": True,
|
||||
"disconnect": True,
|
||||
"newMessage": True,
|
||||
"groupMessage": True,
|
||||
"notice": True,
|
||||
"event": True,
|
||||
"assistant": True
|
||||
},
|
||||
"time": current_time_sys_init,
|
||||
"sign": sys_init_sign
|
||||
}
|
||||
|
||||
await websocket.send(json.dumps(new_message))
|
||||
print(f"Sent message: {new_message}")
|
||||
except websockets.ConnectionClosed:
|
||||
print("服务器关闭连接")
|
||||
except Exception as e:
|
||||
print(f"出现错误:{e}")
|
||||
except websockets.InvalidURI as e:
|
||||
print(f"ws地址无效: {e} 请检查WebSocket地址")
|
||||
break
|
||||
except ConnectionRefusedError as e:
|
||||
print(f"连接被拒绝: {e} 服务器可能未运行或URI不正确。5秒后重试..")
|
||||
await asyncio.sleep(5)
|
||||
except OSError as e:
|
||||
print(f"操作系统错误: {e} 服务器可能无法访问。5秒后重试..")
|
||||
await asyncio.sleep(5)
|
||||
except Exception as e:
|
||||
print(f"发生意外错误:{e} Sign验证错误。5秒后重试..")
|
||||
await asyncio.sleep(5)
|
||||
|
||||
# 运行异步主函数
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(connect_to_websocket())
|
||||
|
||||
|
||||
|
||||
4
dist/main/_internal/Utils/PythonNew32/Doc/html/.buildinfo
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# Sphinx build info version 1
|
||||
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 06974a5ccb59221159504cb0c9d0222b
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
241
dist/main/_internal/Utils/PythonNew32/Doc/html/404.html
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" data-content_root="./">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Page not found — Python 3.13.5 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/en/latest/_static/pygments.css?v=b86133f3" />
|
||||
<link rel="stylesheet" type="text/css" href="/en/latest/_static/classic.css?v=234b1a7c" />
|
||||
<link rel="stylesheet" type="text/css" href="/en/latest/_static/pydoctheme.css?v=5ff89526" />
|
||||
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="/en/latest/_static/pygments_dark.css?v=5349f25f" />
|
||||
|
||||
<script src="/en/latest/_static/documentation_options.js?v=32a6def9"></script>
|
||||
<script src="/en/latest/_static/doctools.js?v=9bcbadda"></script>
|
||||
<script src="/en/latest/_static/sphinx_highlight.js?v=dc90522c"></script>
|
||||
|
||||
<script src="/en/latest/_static/sidebar.js"></script>
|
||||
|
||||
<link rel="search" type="application/opensearchdescription+xml"
|
||||
title="Search within Python 3.13.5 documentation"
|
||||
href="/en/latest/_static/opensearch.xml"/>
|
||||
<link rel="author" title="About these documents" href="/en/latest/about.html" />
|
||||
<link rel="index" title="Index" href="/en/latest/genindex.html" />
|
||||
<link rel="search" title="Search" href="/en/latest/search.html" />
|
||||
<link rel="copyright" title="Copyright" href="/en/latest/copyright.html" />
|
||||
|
||||
|
||||
<link rel="canonical" href="https://docs.python.org/3/404.html">
|
||||
|
||||
|
||||
|
||||
|
||||
<style>
|
||||
@media only screen {
|
||||
table.full-width-table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/en/latest/_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
|
||||
<link rel="shortcut icon" type="image/png" href="/en/latest/_static/py.svg">
|
||||
<script type="text/javascript" src="/en/latest/_static/copybutton.js"></script>
|
||||
<script type="text/javascript" src="/en/latest/_static/menu.js"></script>
|
||||
<script type="text/javascript" src="/en/latest/_static/search-focus.js"></script>
|
||||
<script type="text/javascript" src="/en/latest/_static/themetoggle.js"></script>
|
||||
<script type="text/javascript" src="/en/latest/_static/rtd_switcher.js"></script>
|
||||
<meta name="readthedocs-addons-api-version" content="1">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="mobile-nav">
|
||||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu">
|
||||
<nav class="nav-content" role="navigation">
|
||||
<label for="menuToggler" class="toggler__label">
|
||||
<span></span>
|
||||
</label>
|
||||
<span class="nav-items-wrapper">
|
||||
<a href="https://www.python.org/" class="nav-logo">
|
||||
<img src="/en/latest/_static/py.svg" alt="Python logo">
|
||||
</a>
|
||||
<span class="version_switcher_placeholder"></span>
|
||||
<form role="search" class="search" action="/en/latest/search.html" method="get">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||||
<path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
|
||||
</svg>
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q">
|
||||
<input type="submit" value="Go">
|
||||
</form>
|
||||
</span>
|
||||
</nav>
|
||||
<div class="menu-wrapper">
|
||||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||||
<div class="language_switcher_placeholder"></div>
|
||||
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="related" role="navigation" aria-label="Related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="/en/latest/genindex.html" title="General Index"
|
||||
accesskey="I">index</a></li>
|
||||
<li class="right" >
|
||||
<a href="/en/latest/py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
|
||||
<li><img src="/en/latest/_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
|
||||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||||
<li class="switchers">
|
||||
<div class="language_switcher_placeholder"></div>
|
||||
<div class="version_switcher_placeholder"></div>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
</li>
|
||||
<li id="cpython-language-and-version">
|
||||
<a href="/en/latest/index.html">3.13.5 Documentation</a> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-this"><a href="">Page not found</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="/en/latest/search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
|
||||
<input type="submit" value="Go">
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Page not found</h1>
|
||||
|
||||
Unfortunately we couldn't find the content you were looking for.
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
</div>
|
||||
<div id="sidebarbutton" title="Collapse sidebar">
|
||||
<span>«</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="related" role="navigation" aria-label="Related">
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="right" style="margin-right: 10px">
|
||||
<a href="/en/latest/genindex.html" title="General Index"
|
||||
>index</a></li>
|
||||
<li class="right" >
|
||||
<a href="/en/latest/py-modindex.html" title="Python Module Index"
|
||||
>modules</a> |</li>
|
||||
|
||||
<li><img src="/en/latest/_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
|
||||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||||
<li class="switchers">
|
||||
<div class="language_switcher_placeholder"></div>
|
||||
<div class="version_switcher_placeholder"></div>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
</li>
|
||||
<li id="cpython-language-and-version">
|
||||
<a href="/en/latest/index.html">3.13.5 Documentation</a> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-this"><a href="">Page not found</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="/en/latest/search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
|
||||
<input type="submit" value="Go">
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
©
|
||||
<a href="/en/latest/copyright.html">
|
||||
|
||||
Copyright
|
||||
|
||||
</a>
|
||||
2001-2025, Python Software Foundation.
|
||||
<br>
|
||||
This page is licensed under the Python Software Foundation License Version 2.
|
||||
<br>
|
||||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||||
<br>
|
||||
|
||||
See <a href="/license.html">History and License</a> for more information.<br>
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
The Python Software Foundation is a non-profit corporation.
|
||||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||||
<br>
|
||||
<br>
|
||||
Last updated on Jun 11, 2025 (15:56 UTC).
|
||||
|
||||
<a href="/bugs.html">Found a bug</a>?
|
||||
|
||||
<br>
|
||||
|
||||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,175 @@
|
||||
from datetime import tzinfo, timedelta, datetime
|
||||
|
||||
ZERO = timedelta(0)
|
||||
HOUR = timedelta(hours=1)
|
||||
SECOND = timedelta(seconds=1)
|
||||
|
||||
# A class capturing the platform's idea of local time.
|
||||
# (May result in wrong values on historical times in
|
||||
# timezones where UTC offset and/or the DST rules had
|
||||
# changed in the past.)
|
||||
import time as _time
|
||||
|
||||
STDOFFSET = timedelta(seconds = -_time.timezone)
|
||||
if _time.daylight:
|
||||
DSTOFFSET = timedelta(seconds = -_time.altzone)
|
||||
else:
|
||||
DSTOFFSET = STDOFFSET
|
||||
|
||||
DSTDIFF = DSTOFFSET - STDOFFSET
|
||||
|
||||
class LocalTimezone(tzinfo):
|
||||
|
||||
def fromutc(self, dt):
|
||||
assert dt.tzinfo is self
|
||||
stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND
|
||||
args = _time.localtime(stamp)[:6]
|
||||
dst_diff = DSTDIFF // SECOND
|
||||
# Detect fold
|
||||
fold = (args == _time.localtime(stamp - dst_diff))
|
||||
return datetime(*args, microsecond=dt.microsecond,
|
||||
tzinfo=self, fold=fold)
|
||||
|
||||
def utcoffset(self, dt):
|
||||
if self._isdst(dt):
|
||||
return DSTOFFSET
|
||||
else:
|
||||
return STDOFFSET
|
||||
|
||||
def dst(self, dt):
|
||||
if self._isdst(dt):
|
||||
return DSTDIFF
|
||||
else:
|
||||
return ZERO
|
||||
|
||||
def tzname(self, dt):
|
||||
return _time.tzname[self._isdst(dt)]
|
||||
|
||||
def _isdst(self, dt):
|
||||
tt = (dt.year, dt.month, dt.day,
|
||||
dt.hour, dt.minute, dt.second,
|
||||
dt.weekday(), 0, 0)
|
||||
stamp = _time.mktime(tt)
|
||||
tt = _time.localtime(stamp)
|
||||
return tt.tm_isdst > 0
|
||||
|
||||
Local = LocalTimezone()
|
||||
|
||||
|
||||
# A complete implementation of current DST rules for major US time zones.
|
||||
|
||||
def first_sunday_on_or_after(dt):
|
||||
days_to_go = 6 - dt.weekday()
|
||||
if days_to_go:
|
||||
dt += timedelta(days_to_go)
|
||||
return dt
|
||||
|
||||
|
||||
# US DST Rules
|
||||
#
|
||||
# This is a simplified (i.e., wrong for a few cases) set of rules for US
|
||||
# DST start and end times. For a complete and up-to-date set of DST rules
|
||||
# and timezone definitions, visit the Olson Database (or try pytz):
|
||||
# http://www.twinsun.com/tz/tz-link.htm
|
||||
# https://sourceforge.net/projects/pytz/ (might not be up-to-date)
|
||||
#
|
||||
# In the US, since 2007, DST starts at 2am (standard time) on the second
|
||||
# Sunday in March, which is the first Sunday on or after Mar 8.
|
||||
DSTSTART_2007 = datetime(1, 3, 8, 2)
|
||||
# and ends at 2am (DST time) on the first Sunday of Nov.
|
||||
DSTEND_2007 = datetime(1, 11, 1, 2)
|
||||
# From 1987 to 2006, DST used to start at 2am (standard time) on the first
|
||||
# Sunday in April and to end at 2am (DST time) on the last
|
||||
# Sunday of October, which is the first Sunday on or after Oct 25.
|
||||
DSTSTART_1987_2006 = datetime(1, 4, 1, 2)
|
||||
DSTEND_1987_2006 = datetime(1, 10, 25, 2)
|
||||
# From 1967 to 1986, DST used to start at 2am (standard time) on the last
|
||||
# Sunday in April (the one on or after April 24) and to end at 2am (DST time)
|
||||
# on the last Sunday of October, which is the first Sunday
|
||||
# on or after Oct 25.
|
||||
DSTSTART_1967_1986 = datetime(1, 4, 24, 2)
|
||||
DSTEND_1967_1986 = DSTEND_1987_2006
|
||||
|
||||
def us_dst_range(year):
|
||||
# Find start and end times for US DST. For years before 1967, return
|
||||
# start = end for no DST.
|
||||
if 2006 < year:
|
||||
dststart, dstend = DSTSTART_2007, DSTEND_2007
|
||||
elif 1986 < year < 2007:
|
||||
dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
|
||||
elif 1966 < year < 1987:
|
||||
dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
|
||||
else:
|
||||
return (datetime(year, 1, 1), ) * 2
|
||||
|
||||
start = first_sunday_on_or_after(dststart.replace(year=year))
|
||||
end = first_sunday_on_or_after(dstend.replace(year=year))
|
||||
return start, end
|
||||
|
||||
|
||||
class USTimeZone(tzinfo):
|
||||
|
||||
def __init__(self, hours, reprname, stdname, dstname):
|
||||
self.stdoffset = timedelta(hours=hours)
|
||||
self.reprname = reprname
|
||||
self.stdname = stdname
|
||||
self.dstname = dstname
|
||||
|
||||
def __repr__(self):
|
||||
return self.reprname
|
||||
|
||||
def tzname(self, dt):
|
||||
if self.dst(dt):
|
||||
return self.dstname
|
||||
else:
|
||||
return self.stdname
|
||||
|
||||
def utcoffset(self, dt):
|
||||
return self.stdoffset + self.dst(dt)
|
||||
|
||||
def dst(self, dt):
|
||||
if dt is None or dt.tzinfo is None:
|
||||
# An exception may be sensible here, in one or both cases.
|
||||
# It depends on how you want to treat them. The default
|
||||
# fromutc() implementation (called by the default astimezone()
|
||||
# implementation) passes a datetime with dt.tzinfo is self.
|
||||
return ZERO
|
||||
assert dt.tzinfo is self
|
||||
start, end = us_dst_range(dt.year)
|
||||
# Can't compare naive to aware objects, so strip the timezone from
|
||||
# dt first.
|
||||
dt = dt.replace(tzinfo=None)
|
||||
if start + HOUR <= dt < end - HOUR:
|
||||
# DST is in effect.
|
||||
return HOUR
|
||||
if end - HOUR <= dt < end:
|
||||
# Fold (an ambiguous hour): use dt.fold to disambiguate.
|
||||
return ZERO if dt.fold else HOUR
|
||||
if start <= dt < start + HOUR:
|
||||
# Gap (a non-existent hour): reverse the fold rule.
|
||||
return HOUR if dt.fold else ZERO
|
||||
# DST is off.
|
||||
return ZERO
|
||||
|
||||
def fromutc(self, dt):
|
||||
assert dt.tzinfo is self
|
||||
start, end = us_dst_range(dt.year)
|
||||
start = start.replace(tzinfo=self)
|
||||
end = end.replace(tzinfo=self)
|
||||
std_time = dt + self.stdoffset
|
||||
dst_time = std_time + HOUR
|
||||
if end <= dst_time < end + HOUR:
|
||||
# Repeated hour
|
||||
return std_time.replace(fold=1)
|
||||
if std_time < start or dst_time >= end:
|
||||
# Standard time
|
||||
return std_time
|
||||
if start <= std_time < end - HOUR:
|
||||
# Daylight saving time
|
||||
return dst_time
|
||||
|
||||
|
||||
Eastern = USTimeZone(-5, "Eastern", "EST", "EDT")
|
||||
Central = USTimeZone(-6, "Central", "CST", "CDT")
|
||||
Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
|
||||
Pacific = USTimeZone(-8, "Pacific", "PST", "PDT")
|
||||
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/hashlib-blake2-tree.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/kde_example.png
vendored
Normal file
|
After Width: | Height: | Size: 308 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_01_introduction.png
vendored
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_02_readme.png
vendored
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_03_license.png
vendored
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_04_installation_type.png
vendored
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_05_custom_install.png
vendored
Normal file
|
After Width: | Height: | Size: 165 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_06_summary.png
vendored
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_07_applications.png
vendored
Normal file
|
After Width: | Height: | Size: 145 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/mac_installer_08_install_certificates.png
vendored
Normal file
|
After Width: | Height: | Size: 170 KiB |
|
After Width: | Height: | Size: 188 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/pathlib-inheritance.png
vendored
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/tk_msg.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/turtle-star.png
vendored
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/win_install_freethreaded.png
vendored
Normal file
|
After Width: | Height: | Size: 231 KiB |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_images/win_installer.png
vendored
Normal file
|
After Width: | Height: | Size: 82 KiB |
906
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/basic.css
vendored
Normal file
@@ -0,0 +1,906 @@
|
||||
/*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.section::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap : break-word;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox form.search {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
float: left;
|
||||
width: 80%;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
float: left;
|
||||
width: 20%;
|
||||
border-left: none;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li p.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
table.indextable > tbody > tr > td > ul {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- domain module index --------------------------------------------------- */
|
||||
|
||||
table.modindextable td {
|
||||
padding: 2px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
div.body {
|
||||
min-width: 360px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #551A8B;
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink,
|
||||
caption:hover > a.headerlink,
|
||||
p.caption:hover > a.headerlink,
|
||||
div.code-block-caption:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
img.align-default, figure.align-default, .figure.align-default {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar,
|
||||
aside.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
clear: right;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.admonition, div.topic, blockquote {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||
|
||||
div.sidebar > :last-child,
|
||||
aside.sidebar > :last-child,
|
||||
nav.contents > :last-child,
|
||||
aside.topic > :last-child,
|
||||
div.topic > :last-child,
|
||||
div.admonition > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sidebar::after,
|
||||
aside.sidebar::after,
|
||||
nav.contents::after,
|
||||
aside.topic::after,
|
||||
div.topic::after,
|
||||
div.admonition::after,
|
||||
blockquote::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-default {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table caption span.caption-text {
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th > :first-child,
|
||||
td > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
th > :last-child,
|
||||
td > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* -- figures --------------------------------------------------------------- */
|
||||
|
||||
div.figure, figure {
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.figure p.caption, figcaption {
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-number,
|
||||
figcaption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-text,
|
||||
figcaption span.caption-text {
|
||||
}
|
||||
|
||||
/* -- field list styles ----------------------------------------------------- */
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
/* -- hlist styles ---------------------------------------------------------- */
|
||||
|
||||
table.hlist {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
table.hlist td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -- object description styles --------------------------------------------- */
|
||||
|
||||
.sig {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
}
|
||||
|
||||
.sig-name, code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sig-name {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.sig-prename, code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.sig-param.n {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* C++ specific styling */
|
||||
|
||||
.sig-inline.c-texpr,
|
||||
.sig-inline.cpp-texpr {
|
||||
font-family: unset;
|
||||
}
|
||||
|
||||
.sig.c .k, .sig.c .kt,
|
||||
.sig.cpp .k, .sig.cpp .kt {
|
||||
color: #0033B3;
|
||||
}
|
||||
|
||||
.sig.c .m,
|
||||
.sig.cpp .m {
|
||||
color: #1750EB;
|
||||
}
|
||||
|
||||
.sig.c .s, .sig.c .sc,
|
||||
.sig.cpp .s, .sig.cpp .sc {
|
||||
color: #067D17;
|
||||
}
|
||||
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:first-child > :first-child,
|
||||
:not(li) > ul > li:first-child > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:last-child > :last-child,
|
||||
:not(li) > ul > li:last-child > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ol.simple ol p,
|
||||
ol.simple ul p,
|
||||
ul.simple ol p,
|
||||
ul.simple ul p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple > li:not(:first-child) > p,
|
||||
ul.simple > li:not(:first-child) > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple p,
|
||||
ul.simple p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
aside.footnote > span,
|
||||
div.citation > span {
|
||||
float: left;
|
||||
}
|
||||
aside.footnote > span:last-of-type,
|
||||
div.citation > span:last-of-type {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
aside.footnote > p {
|
||||
margin-left: 2em;
|
||||
}
|
||||
div.citation > p {
|
||||
margin-left: 4em;
|
||||
}
|
||||
aside.footnote > p:last-of-type,
|
||||
div.citation > p:last-of-type {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
aside.footnote > p:last-of-type:after,
|
||||
div.citation > p:last-of-type:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(30%) auto;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
dl.field-list > dd {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 0em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.sig dd {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.sig dl {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
dl > dd:last-child,
|
||||
dl > dd:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt:target, span.highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
rect.highlighted {
|
||||
fill: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
.classifier:before {
|
||||
font-style: normal;
|
||||
margin: 0 0.5em;
|
||||
content: ":";
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
pre, div[class*="highlight-"] {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div[class*="highlight-"] {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tr {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td.code {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.highlight pre,
|
||||
table.highlighttable pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption + div {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
margin-top: 1em;
|
||||
padding: 2px 5px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div.code-block-caption code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos,
|
||||
span.linenos,
|
||||
div.highlight span.gp { /* gp: Generic.Prompt */
|
||||
user-select: none;
|
||||
-webkit-user-select: text; /* Safari fallback only */
|
||||
-webkit-user-select: none; /* Chrome/Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-number {
|
||||
padding: 0.1em 0.3em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-text {
|
||||
}
|
||||
|
||||
div.literal-block-wrapper {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
span.eqno a.headerlink {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.math:hover a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
59
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/changelog_search.js
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// add the search form and bind the events
|
||||
document
|
||||
.querySelector("h1")
|
||||
.insertAdjacentHTML(
|
||||
"afterend",
|
||||
[
|
||||
"<p>Filter entries by content:",
|
||||
'<input type="text" value="" id="searchbox" style="width: 50%">',
|
||||
'<input type="submit" id="searchbox-submit" value="Filter"></p>',
|
||||
].join("\n"),
|
||||
);
|
||||
|
||||
function doFilter() {
|
||||
let query;
|
||||
try {
|
||||
query = new RegExp(document.querySelector("#searchbox").value, "i");
|
||||
} catch (e) {
|
||||
return; // not a valid regex (yet)
|
||||
}
|
||||
// find headers for the versions (What's new in Python X.Y.Z?)
|
||||
const h2s = document.querySelectorAll("#changelog h2");
|
||||
for (const h2 of h2s) {
|
||||
let sections_found = 0;
|
||||
// find headers for the sections (Core, Library, etc.)
|
||||
const h3s = h2.parentNode.querySelectorAll("h3");
|
||||
for (const h3 of h3s) {
|
||||
let entries_found = 0;
|
||||
// find all the entries
|
||||
const lis = h3.parentNode.querySelectorAll("li");
|
||||
for (let li of lis) {
|
||||
// check if the query matches the entry
|
||||
if (query.test(li.textContent)) {
|
||||
li.style.display = "block";
|
||||
entries_found++;
|
||||
} else {
|
||||
li.style.display = "none";
|
||||
}
|
||||
}
|
||||
// if there are entries, show the section, otherwise hide it
|
||||
if (entries_found > 0) {
|
||||
h3.parentNode.style.display = "block";
|
||||
sections_found++;
|
||||
} else {
|
||||
h3.parentNode.style.display = "none";
|
||||
}
|
||||
}
|
||||
if (sections_found > 0) {
|
||||
h2.parentNode.style.display = "block";
|
||||
} else {
|
||||
h2.parentNode.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
document.querySelector("#searchbox").addEventListener("keyup", doFilter);
|
||||
document
|
||||
.querySelector("#searchbox-submit")
|
||||
.addEventListener("click", doFilter);
|
||||
});
|
||||
294
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/classic.css
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Sphinx stylesheet -- classic theme.
|
||||
*/
|
||||
|
||||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
html {
|
||||
/* CSS hack for macOS's scrollbar (see #1125) */
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: white;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.document {
|
||||
display: flex;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 230px;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: white;
|
||||
color: #222222;
|
||||
padding: 0 20px 30px 20px;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
color: #555555;
|
||||
width: 100%;
|
||||
padding: 9px 0 9px 0;
|
||||
text-align: center;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #555555;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.related {
|
||||
background-color: white;
|
||||
line-height: 30px;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
color: #444444;
|
||||
font-size: 1.4em;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
color: #444444;
|
||||
font-size: 1.3em;
|
||||
font-weight: normal;
|
||||
margin: 5px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.topless {
|
||||
margin: 5px 10px 10px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #444444;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* for collapsible sidebar */
|
||||
#sidebarbutton {
|
||||
height: 100%;
|
||||
background-color: #cccccc;
|
||||
margin-left: 0;
|
||||
color: #FFFFFF;
|
||||
border-left: 1px solid white;
|
||||
font-size: 1.2em;
|
||||
cursor: pointer;
|
||||
padding-top: 1px;
|
||||
float: right;
|
||||
display: table; /* for vertically centering the <span> */
|
||||
}
|
||||
|
||||
#sidebarbutton:hover {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
#sidebarbutton span {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
float: left;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
|
||||
/* -- hyperlink styles ------------------------------------------------------ */
|
||||
|
||||
a {
|
||||
color: #0090c0;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #00608f;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
background-color: white;
|
||||
font-weight: normal;
|
||||
color: #1a1a1a;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 20px -20px 10px -20px;
|
||||
padding: 3px 0 3px 10px;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; font-size: 200%; }
|
||||
div.body h2 { font-size: 160%; }
|
||||
div.body h3 { font-size: 140%; }
|
||||
div.body h4 { font-size: 120%; }
|
||||
div.body h5 { font-size: 110%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #aaaaaa;
|
||||
font-size: 0.8em;
|
||||
padding: 0 4px 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #aaaaaa;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
text-align: justify;
|
||||
line-height: 130%;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title + p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.admonition p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition pre {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.admonition ul, div.admonition ol {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #eee;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #ffc;
|
||||
border: 1px solid #ff6;
|
||||
}
|
||||
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.topic {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #ffe4e4;
|
||||
border: 1px solid #f66;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 5px;
|
||||
background-color: #eeffcc;
|
||||
color: #333333;
|
||||
line-height: 120%;
|
||||
border: 1px solid #ac9;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #ecf0f3;
|
||||
padding: 0 1px 0 1px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
th, dl.field-list > dt {
|
||||
background-color: #ede;
|
||||
}
|
||||
|
||||
.warning code {
|
||||
background: #efc2c2;
|
||||
}
|
||||
|
||||
.note code {
|
||||
background: #d6d6d6;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background-color: #f4debf;
|
||||
border-top: 1px solid #ac9;
|
||||
border-bottom: 1px solid #ac9;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
color: #efefef;
|
||||
background-color: #1c4e63;
|
||||
}
|
||||
84
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/copybutton.js
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
// Extract copyable text from the code block ignoring the
|
||||
// prompts and output.
|
||||
function getCopyableText(rootElement) {
|
||||
rootElement = rootElement.cloneNode(true)
|
||||
// tracebacks (.gt) contain bare text elements that
|
||||
// need to be removed
|
||||
const tracebacks = rootElement.querySelectorAll(".gt")
|
||||
for (const el of tracebacks) {
|
||||
while (
|
||||
el.nextSibling &&
|
||||
(el.nextSibling.nodeType !== Node.ELEMENT_NODE ||
|
||||
!el.nextSibling.matches(".gp, .go"))
|
||||
) {
|
||||
el.nextSibling.remove()
|
||||
}
|
||||
}
|
||||
// Remove all elements with the "go" (Generic.Output),
|
||||
// "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
|
||||
const elements = rootElement.querySelectorAll(".gp, .go, .gt")
|
||||
for (const el of elements) {
|
||||
el.remove()
|
||||
}
|
||||
return rootElement.innerText.trim()
|
||||
}
|
||||
|
||||
const loadCopyButton = () => {
|
||||
const button = document.createElement("button")
|
||||
button.classList.add("copybutton")
|
||||
button.type = "button"
|
||||
button.innerText = _("Copy")
|
||||
button.title = _("Copy to clipboard")
|
||||
|
||||
const makeOnButtonClick = () => {
|
||||
let timeout = null
|
||||
// define the behavior of the button when it's clicked
|
||||
return async event => {
|
||||
// check if the clipboard is available
|
||||
if (!navigator.clipboard || !navigator.clipboard.writeText) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(timeout)
|
||||
const buttonEl = event.currentTarget
|
||||
const codeEl = buttonEl.nextElementSibling
|
||||
|
||||
try {
|
||||
await navigator.clipboard.writeText(getCopyableText(codeEl))
|
||||
} catch (e) {
|
||||
console.error(e.message)
|
||||
return
|
||||
}
|
||||
|
||||
buttonEl.innerText = _("Copied!")
|
||||
timeout = setTimeout(() => {
|
||||
buttonEl.innerText = _("Copy")
|
||||
}, 1500)
|
||||
}
|
||||
}
|
||||
|
||||
const highlightedElements = document.querySelectorAll(
|
||||
".highlight-python .highlight,"
|
||||
+ ".highlight-python3 .highlight,"
|
||||
+ ".highlight-pycon .highlight,"
|
||||
+ ".highlight-pycon3 .highlight,"
|
||||
+ ".highlight-default .highlight"
|
||||
)
|
||||
|
||||
// create and add the button to all the code blocks that contain >>>
|
||||
highlightedElements.forEach(el => {
|
||||
el.style.position = "relative"
|
||||
|
||||
// if we find a console prompt (.gp), prepend the (deeply cloned) button
|
||||
const clonedButton = button.cloneNode(true)
|
||||
// the onclick attribute is not cloned, set it on the new element
|
||||
clonedButton.onclick = makeOnButtonClick()
|
||||
el.prepend(clonedButton)
|
||||
})
|
||||
}
|
||||
|
||||
if (document.readyState !== "loading") {
|
||||
loadCopyButton()
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", loadCopyButton)
|
||||
}
|
||||
1
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/default.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
@import url("classic.css");
|
||||
149
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/doctools.js
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Base JavaScript utilities for all Sphinx HTML documentation.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
|
||||
"TEXTAREA",
|
||||
"INPUT",
|
||||
"SELECT",
|
||||
"BUTTON",
|
||||
]);
|
||||
|
||||
const _ready = (callback) => {
|
||||
if (document.readyState !== "loading") {
|
||||
callback();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", callback);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
const Documentation = {
|
||||
init: () => {
|
||||
Documentation.initDomainIndexTable();
|
||||
Documentation.initOnKeyListeners();
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS: {},
|
||||
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
|
||||
LOCALE: "unknown",
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can safely bound to a different name (_ = Documentation.gettext)
|
||||
gettext: (string) => {
|
||||
const translated = Documentation.TRANSLATIONS[string];
|
||||
switch (typeof translated) {
|
||||
case "undefined":
|
||||
return string; // no translation
|
||||
case "string":
|
||||
return translated; // translation exists
|
||||
default:
|
||||
return translated[0]; // (singular, plural) translation tuple exists
|
||||
}
|
||||
},
|
||||
|
||||
ngettext: (singular, plural, n) => {
|
||||
const translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated !== "undefined")
|
||||
return translated[Documentation.PLURAL_EXPR(n)];
|
||||
return n === 1 ? singular : plural;
|
||||
},
|
||||
|
||||
addTranslations: (catalog) => {
|
||||
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
|
||||
Documentation.PLURAL_EXPR = new Function(
|
||||
"n",
|
||||
`return (${catalog.plural_expr})`
|
||||
);
|
||||
Documentation.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to focus on search bar
|
||||
*/
|
||||
focusSearchBar: () => {
|
||||
document.querySelectorAll("input[name=q]")[0]?.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialise the domain index toggle buttons
|
||||
*/
|
||||
initDomainIndexTable: () => {
|
||||
const toggler = (el) => {
|
||||
const idNumber = el.id.substr(7);
|
||||
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
|
||||
if (el.src.substr(-9) === "minus.png") {
|
||||
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
|
||||
toggledRows.forEach((el) => (el.style.display = "none"));
|
||||
} else {
|
||||
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
|
||||
toggledRows.forEach((el) => (el.style.display = ""));
|
||||
}
|
||||
};
|
||||
|
||||
const togglerElements = document.querySelectorAll("img.toggler");
|
||||
togglerElements.forEach((el) =>
|
||||
el.addEventListener("click", (event) => toggler(event.currentTarget))
|
||||
);
|
||||
togglerElements.forEach((el) => (el.style.display = ""));
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
|
||||
},
|
||||
|
||||
initOnKeyListeners: () => {
|
||||
// only install a listener if it is really needed
|
||||
if (
|
||||
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
|
||||
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
|
||||
)
|
||||
return;
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
// bail for input elements
|
||||
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
|
||||
// bail with special keys
|
||||
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
||||
|
||||
if (!event.shiftKey) {
|
||||
switch (event.key) {
|
||||
case "ArrowLeft":
|
||||
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||
|
||||
const prevLink = document.querySelector('link[rel="prev"]');
|
||||
if (prevLink && prevLink.href) {
|
||||
window.location.href = prevLink.href;
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
case "ArrowRight":
|
||||
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||
|
||||
const nextLink = document.querySelector('link[rel="next"]');
|
||||
if (nextLink && nextLink.href) {
|
||||
window.location.href = nextLink.href;
|
||||
event.preventDefault();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// some keyboard layouts may need Shift to get /
|
||||
switch (event.key) {
|
||||
case "/":
|
||||
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
|
||||
Documentation.focusSearchBar();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
const _ = Documentation.gettext;
|
||||
|
||||
_ready(Documentation.init);
|
||||
13
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/documentation_options.js
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
const DOCUMENTATION_OPTIONS = {
|
||||
VERSION: '3.13.5',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
FILE_SUFFIX: '.html',
|
||||
LINK_SUFFIX: '.html',
|
||||
HAS_SOURCE: true,
|
||||
SOURCELINK_SUFFIX: '.txt',
|
||||
NAVIGATION_WITH_KEYS: false,
|
||||
SHOW_SEARCH_SUMMARY: true,
|
||||
ENABLE_SEARCH_SHORTCUTS: true,
|
||||
};
|
||||
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/file.png
vendored
Normal file
|
After Width: | Height: | Size: 286 B |
1
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/glossary.json
vendored
Normal file
47
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/glossary_search.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
|
||||
const GLOSSARY_PAGE = "glossary.html";
|
||||
|
||||
const glossary_search = async () => {
|
||||
const response = await fetch("_static/glossary.json");
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch glossary.json");
|
||||
}
|
||||
const glossary = await response.json();
|
||||
|
||||
const params = new URLSearchParams(document.location.search).get("q");
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
const searchParam = params.toLowerCase();
|
||||
const glossaryItem = glossary[searchParam];
|
||||
if (!glossaryItem) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set up the title text with a link to the glossary page
|
||||
const glossaryTitle = document.getElementById("glossary-title");
|
||||
glossaryTitle.textContent = "Glossary: " + glossaryItem.title;
|
||||
const linkTarget = searchParam.replace(/ /g, "-");
|
||||
glossaryTitle.href = GLOSSARY_PAGE + "#term-" + linkTarget;
|
||||
|
||||
// rewrite any anchor links (to other glossary terms)
|
||||
// to have a full reference to the glossary page
|
||||
const glossaryBody = document.getElementById("glossary-body");
|
||||
glossaryBody.innerHTML = glossaryItem.body;
|
||||
const anchorLinks = glossaryBody.querySelectorAll('a[href^="#"]');
|
||||
anchorLinks.forEach(function (link) {
|
||||
const currentUrl = link.getAttribute("href");
|
||||
link.href = GLOSSARY_PAGE + currentUrl;
|
||||
});
|
||||
|
||||
const glossaryResult = document.getElementById("glossary-result");
|
||||
glossaryResult.style.display = "";
|
||||
};
|
||||
|
||||
if (document.readyState !== "loading") {
|
||||
glossary_search().catch(console.error);
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", glossary_search);
|
||||
}
|
||||
192
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/language_data.js
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This script contains the language-specific data used by searchtools.js,
|
||||
* namely the list of stopwords, stemmer, scorer and splitter.
|
||||
*/
|
||||
|
||||
var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
|
||||
|
||||
|
||||
/* Non-minified version is copied as a separate JS file, if available */
|
||||
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
var Stemmer = function() {
|
||||
|
||||
var step2list = {
|
||||
ational: 'ate',
|
||||
tional: 'tion',
|
||||
enci: 'ence',
|
||||
anci: 'ance',
|
||||
izer: 'ize',
|
||||
bli: 'ble',
|
||||
alli: 'al',
|
||||
entli: 'ent',
|
||||
eli: 'e',
|
||||
ousli: 'ous',
|
||||
ization: 'ize',
|
||||
ation: 'ate',
|
||||
ator: 'ate',
|
||||
alism: 'al',
|
||||
iveness: 'ive',
|
||||
fulness: 'ful',
|
||||
ousness: 'ous',
|
||||
aliti: 'al',
|
||||
iviti: 'ive',
|
||||
biliti: 'ble',
|
||||
logi: 'log'
|
||||
};
|
||||
|
||||
var step3list = {
|
||||
icate: 'ic',
|
||||
ative: '',
|
||||
alize: 'al',
|
||||
iciti: 'ic',
|
||||
ical: 'ic',
|
||||
ful: '',
|
||||
ness: ''
|
||||
};
|
||||
|
||||
var c = "[^aeiou]"; // consonant
|
||||
var v = "[aeiouy]"; // vowel
|
||||
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||
var V = v + "[aeiou]*"; // vowel sequence
|
||||
|
||||
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||
|
||||
this.stemWord = function (w) {
|
||||
var stem;
|
||||
var suffix;
|
||||
var firstch;
|
||||
var origword = w;
|
||||
|
||||
if (w.length < 3)
|
||||
return w;
|
||||
|
||||
var re;
|
||||
var re2;
|
||||
var re3;
|
||||
var re4;
|
||||
|
||||
firstch = w.substr(0,1);
|
||||
if (firstch == "y")
|
||||
w = firstch.toUpperCase() + w.substr(1);
|
||||
|
||||
// Step 1a
|
||||
re = /^(.+?)(ss|i)es$/;
|
||||
re2 = /^(.+?)([^s])s$/;
|
||||
|
||||
if (re.test(w))
|
||||
w = w.replace(re,"$1$2");
|
||||
else if (re2.test(w))
|
||||
w = w.replace(re2,"$1$2");
|
||||
|
||||
// Step 1b
|
||||
re = /^(.+?)eed$/;
|
||||
re2 = /^(.+?)(ed|ing)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(fp[1])) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1];
|
||||
re2 = new RegExp(s_v);
|
||||
if (re2.test(stem)) {
|
||||
w = stem;
|
||||
re2 = /(at|bl|iz)$/;
|
||||
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re2.test(w))
|
||||
w = w + "e";
|
||||
else if (re3.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
else if (re4.test(w))
|
||||
w = w + "e";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1c
|
||||
re = /^(.+?)y$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(s_v);
|
||||
if (re.test(stem))
|
||||
w = stem + "i";
|
||||
}
|
||||
|
||||
// Step 2
|
||||
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step2list[suffix];
|
||||
}
|
||||
|
||||
// Step 3
|
||||
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step3list[suffix];
|
||||
}
|
||||
|
||||
// Step 4
|
||||
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||
re2 = /^(.+?)(s|t)(ion)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
if (re.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1] + fp[2];
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re2.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
re = /^(.+?)e$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
re2 = new RegExp(meq1);
|
||||
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||
w = stem;
|
||||
}
|
||||
re = /ll$/;
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re.test(w) && re2.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
|
||||
// and turn initial Y back to y
|
||||
if (firstch == "y")
|
||||
w = firstch.toLowerCase() + w.substr(1);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
57
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/menu.js
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
// Make tables responsive by wrapping them in a div and making them scrollable
|
||||
const tables = document.querySelectorAll("table.docutils")
|
||||
tables.forEach(function(table){
|
||||
table.outerHTML = '<div class="responsive-table__container">' + table.outerHTML + "</div>"
|
||||
})
|
||||
|
||||
const togglerInput = document.querySelector(".toggler__input")
|
||||
const togglerLabel = document.querySelector(".toggler__label")
|
||||
const sideMenu = document.querySelector(".menu-wrapper")
|
||||
const menuItems = document.querySelectorAll(".menu")
|
||||
const doc = document.querySelector(".document")
|
||||
const body = document.querySelector("body")
|
||||
|
||||
function closeMenu() {
|
||||
togglerInput.checked = false
|
||||
sideMenu.setAttribute("aria-expanded", "false")
|
||||
sideMenu.setAttribute("aria-hidden", "true")
|
||||
togglerLabel.setAttribute("aria-pressed", "false")
|
||||
body.style.overflow = "visible"
|
||||
}
|
||||
function openMenu() {
|
||||
togglerInput.checked = true
|
||||
sideMenu.setAttribute("aria-expanded", "true")
|
||||
sideMenu.setAttribute("aria-hidden", "false")
|
||||
togglerLabel.setAttribute("aria-pressed", "true")
|
||||
body.style.overflow = "hidden"
|
||||
}
|
||||
|
||||
// Close menu when link on the sideMenu is clicked
|
||||
sideMenu.addEventListener("click", function (event) {
|
||||
let target = event.target
|
||||
if (target.tagName.toLowerCase() !== "a") {
|
||||
return
|
||||
}
|
||||
closeMenu()
|
||||
})
|
||||
// Add accessibility data when sideMenu is opened/closed
|
||||
togglerInput.addEventListener("change", function (_event) {
|
||||
togglerInput.checked ? openMenu() : closeMenu()
|
||||
})
|
||||
// Make sideMenu links tabbable only when visible
|
||||
for(let menuItem of menuItems) {
|
||||
if(togglerInput.checked) {
|
||||
menuItem.setAttribute("tabindex", "0")
|
||||
} else {
|
||||
menuItem.setAttribute("tabindex", "-1")
|
||||
}
|
||||
}
|
||||
// Close sideMenu when document body is clicked
|
||||
doc.addEventListener("click", function () {
|
||||
if (togglerInput.checked) {
|
||||
closeMenu()
|
||||
}
|
||||
})
|
||||
})
|
||||
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/minus.png
vendored
Normal file
|
After Width: | Height: | Size: 90 B |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/og-image.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
10
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/opensearch.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||
<ShortName>Python</ShortName>
|
||||
<Description>Search Python 3.13.5 documentation</Description>
|
||||
<InputEncoding>utf-8</InputEncoding>
|
||||
<Url type="text/html" method="get"
|
||||
template="https://docs.python.org/3.13/search.html?q={searchTerms}"/>
|
||||
<LongName>Python 3.13.5 documentation</LongName>
|
||||
<Image height="16" width="16" type="image/x-icon">https://www.python.org/images/favicon16x16.ico</Image>
|
||||
</OpenSearchDescription>
|
||||
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/plus.png
vendored
Normal file
|
After Width: | Height: | Size: 90 B |
BIN
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/py.png
vendored
Normal file
|
After Width: | Height: | Size: 695 B |
14
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/py.svg
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.90472 0.00013087C7.24498 0.00316295 6.61493 0.0588153 6.06056 0.15584C4.42744 0.441207 4.13093 1.0385 4.13093 2.14002V3.59479H7.99018V4.07971H4.13093H2.68259C1.56098 4.07971 0.578874 4.7465 0.271682 6.01495C-0.0826595 7.4689 -0.0983765 8.37618 0.271682 9.89434C0.546011 11.0244 1.20115 11.8296 2.32275 11.8296H3.64965V10.0856C3.64965 8.82574 4.75178 7.71441 6.06056 7.71441H9.91531C10.9883 7.71441 11.8449 6.84056 11.8449 5.77472V2.14002C11.8449 1.10556 10.9626 0.328486 9.91531 0.15584C9.25235 0.046687 8.56447 -0.00290121 7.90472 0.00013087ZM5.81767 1.17017C6.2163 1.17017 6.54184 1.49742 6.54184 1.89978C6.54184 2.30072 6.2163 2.62494 5.81767 2.62494C5.41761 2.62494 5.0935 2.30072 5.0935 1.89978C5.0935 1.49742 5.41761 1.17017 5.81767 1.17017Z" fill="url(#paint0_linear)"/>
|
||||
<path d="M12.3262 4.07971V5.77472C12.3262 7.08883 11.1998 8.19488 9.9153 8.19488H6.06055C5.00466 8.19488 4.13092 9.0887 4.13092 10.1346V13.7693C4.13092 14.8037 5.04038 15.4122 6.06055 15.709C7.28217 16.0642 8.45364 16.1285 9.9153 15.709C10.8869 15.4307 11.8449 14.8708 11.8449 13.7693V12.3145H7.99017V11.8296H11.8449H13.7746C14.8962 11.8296 15.3141 11.0558 15.7042 9.89434C16.1071 8.69865 16.09 7.5488 15.7042 6.01495C15.427 4.91058 14.8976 4.07971 13.7746 4.07971H12.3262ZM10.1582 13.2843C10.5583 13.2843 10.8824 13.6086 10.8824 14.0095C10.8824 14.4119 10.5583 14.7391 10.1582 14.7391C9.75955 14.7391 9.43402 14.4119 9.43402 14.0095C9.43402 13.6086 9.75955 13.2843 10.1582 13.2843Z" fill="url(#paint1_linear)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear" x1="1.25961e-08" y1="1.08223e-08" x2="8.81664" y2="7.59597" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#5A9FD4"/>
|
||||
<stop offset="1" stop-color="#306998"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear" x1="10.0654" y1="13.8872" x2="6.91912" y2="9.42957" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#FFD43B"/>
|
||||
<stop offset="1" stop-color="#FFE873"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
773
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/pydoctheme.css
vendored
Normal file
@@ -0,0 +1,773 @@
|
||||
/* Common colours */
|
||||
:root {
|
||||
--good-color: rgb(41 100 51);
|
||||
--good-border: rgb(79 196 100);
|
||||
--middle-color: rgb(133 72 38);
|
||||
--middle-border: rgb(244, 227, 76);
|
||||
--bad-color: rgb(159 49 51);
|
||||
--bad-border: rgb(244, 76, 78);
|
||||
}
|
||||
|
||||
/* unset some styles from the classic stylesheet */
|
||||
div.document,
|
||||
div.body,
|
||||
div.related,
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6,
|
||||
div.sphinxsidebar a,
|
||||
div.sphinxsidebar p,
|
||||
div.sphinxsidebar ul,
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h3 a,
|
||||
div.sphinxsidebar h4,
|
||||
.menu a,
|
||||
.menu p,
|
||||
.menu ul,
|
||||
.menu h3,
|
||||
.menu h3 a,
|
||||
.menu h4,
|
||||
table.docutils td,
|
||||
table.indextable tr.cap,
|
||||
pre {
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* Add underlines to links */
|
||||
a[href] {
|
||||
text-decoration: underline 1px;
|
||||
}
|
||||
|
||||
/* Increase the underline offset for code to avoid obscuring underscores */
|
||||
a[href]:has(> code) {
|
||||
text-underline-offset: 0.25em;
|
||||
}
|
||||
|
||||
/* No underline for navigation */
|
||||
a.headerlink,
|
||||
div.genindex-jumpbox a,
|
||||
div.modindex-jumpbox a,
|
||||
div#search-results a,
|
||||
div.sphinxsidebar a,
|
||||
div.toctree-wrapper a,
|
||||
div[role=navigation] a,
|
||||
table.contentstable a,
|
||||
table.indextable a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Except when hovered */
|
||||
div.genindex-jumpbox a:hover,
|
||||
div.modindex-jumpbox a:hover,
|
||||
div#search-results a:hover,
|
||||
div.sphinxsidebar a:hover,
|
||||
div.toctree-wrapper a:hover,
|
||||
div[role=navigation] a:hover,
|
||||
table.contentstable a:hover,
|
||||
table.indextable a:hover {
|
||||
text-decoration: underline;
|
||||
text-underline-offset: auto;
|
||||
}
|
||||
|
||||
body {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.mobile-nav,
|
||||
.menu-wrapper {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 1.2em;
|
||||
padding: 0.5em 0;
|
||||
border-width: 1px;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
.mobile-nav + div.related {
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
.document + div.related {
|
||||
border-top-style: solid;
|
||||
}
|
||||
|
||||
div.related a:hover {
|
||||
color: #0095c4;
|
||||
}
|
||||
|
||||
.related .switchers {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.switchers > div {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
div.related ul::after {
|
||||
content: '';
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.inline-search,
|
||||
form.inline-search input {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
form.inline-search input[type='submit'] {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
div.document {
|
||||
display: flex;
|
||||
/* Don't let long code literals extend beyond the right side of the screen */
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Don't let long code literals extend beyond the right side of the screen */
|
||||
span.pre {
|
||||
white-space: unset;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: flex;
|
||||
width: min(25vw, 350px);
|
||||
float: none;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
max-height: 100vh;
|
||||
color: #444;
|
||||
background-color: #eee;
|
||||
border-radius: 5px;
|
||||
line-height: 130%;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin-left: min(25vw, 350px);
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
float: none;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper > h3:first-child {
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper > ul > li > ul > li {
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
color: #0095c4;
|
||||
}
|
||||
|
||||
form.inline-search input,
|
||||
div.sphinxsidebar input,
|
||||
div.related input {
|
||||
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
||||
border: 1px solid #999999;
|
||||
font-size: smaller;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input[type='text'] {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
#sidebarbutton {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 12px;
|
||||
min-width: 12px;
|
||||
border-radius: 0 5px 5px 0;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
#sidebarbutton:hover {
|
||||
background-color: #AAAAAA;
|
||||
}
|
||||
|
||||
div.body {
|
||||
padding: 0 0 0 1.2em;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
text-align: left;
|
||||
line-height: 1.6;
|
||||
}
|
||||
div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0.3em 0;
|
||||
}
|
||||
|
||||
div.body hr {
|
||||
border: 0;
|
||||
background-color: #ccc;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
div.body pre {
|
||||
border-radius: 3px;
|
||||
border: 1px solid #ac9;
|
||||
}
|
||||
|
||||
/* Admonitions */
|
||||
:root {
|
||||
--admonition-background: #eee;
|
||||
--admonition-border: #ccc;
|
||||
--admonition-color: black;
|
||||
--attention-background: #bbddff5c;
|
||||
--attention-border: #0000ff36;
|
||||
--caution-background: #ffc;
|
||||
--caution-border: #dd6;
|
||||
--danger-background: #ffe4e4;
|
||||
--danger-border: red;
|
||||
--error-background: #ffe4e4;
|
||||
--error-border: red;
|
||||
--hint-background: #dfd;
|
||||
--hint-border: green;
|
||||
--seealso-background: #ffc;
|
||||
--seealso-border: #dd6;
|
||||
--tip-background: #dfd;
|
||||
--tip-border: green;
|
||||
--warning-background: #ffe4e4;
|
||||
--warning-border: red;
|
||||
}
|
||||
|
||||
div.body div.admonition {
|
||||
background-color: var(--admonition-background);
|
||||
border: 1px solid var(--admonition-border);
|
||||
border-radius: 3px;
|
||||
color: var(--admonition-color);
|
||||
}
|
||||
|
||||
div.body div.admonition.attention {
|
||||
background-color: var(--attention-background);
|
||||
border-color: var(--attention-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.caution {
|
||||
background-color: var(--caution-background);
|
||||
border-color: var(--caution-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.danger {
|
||||
background-color: var(--danger-background);
|
||||
border-color: var(--danger-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.error {
|
||||
background-color: var(--error-background);
|
||||
border-color: var(--error-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.hint {
|
||||
background-color: var(--hint-background);
|
||||
border-color: var(--hint-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.seealso {
|
||||
background-color: var(--seealso-background);
|
||||
border-color: var(--seealso-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.tip {
|
||||
background-color: var(--tip-background);
|
||||
border-color: var(--tip-border);
|
||||
}
|
||||
|
||||
div.body div.admonition.warning {
|
||||
background-color: var(--warning-background);
|
||||
border-color: var(--warning-border);
|
||||
}
|
||||
|
||||
div.body div.impl-detail {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
div.body div.impl-detail > p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.body a {
|
||||
color: #0072aa;
|
||||
}
|
||||
|
||||
div.body a:visited {
|
||||
color: #6363bb;
|
||||
}
|
||||
|
||||
div.body a:hover {
|
||||
color: #00b0e4;
|
||||
}
|
||||
|
||||
tt, code, pre {
|
||||
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||
font-size: 96.5%;
|
||||
}
|
||||
|
||||
div.body pre {
|
||||
line-height: 120%;
|
||||
}
|
||||
|
||||
div.body tt,
|
||||
div.body code {
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
div.body tt.descname,
|
||||
div.body code.descname {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
div.body tt.xref,
|
||||
div.body a tt,
|
||||
div.body code.xref,
|
||||
div.body a code {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
table.docutils {
|
||||
border: 1px solid #ddd;
|
||||
min-width: 20%;
|
||||
border-radius: 3px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
table.docutils td,
|
||||
table.docutils th {
|
||||
border: 1px solid #ddd !important;
|
||||
border-radius: 3px;
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
table p,
|
||||
table li {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
table.docutils th {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
table.footnote,
|
||||
table.footnote td {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
line-height: 150%;
|
||||
text-align: right;
|
||||
width: auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
text-underline-offset: auto;
|
||||
}
|
||||
|
||||
div.footer a:hover {
|
||||
color: #0095c4;
|
||||
}
|
||||
|
||||
/* C API return value annotations */
|
||||
:root {
|
||||
--refcount: var(--good-color);
|
||||
--refcount-return-borrowed-ref: var(--middle-color);
|
||||
}
|
||||
|
||||
.refcount {
|
||||
color: var(--refcount);
|
||||
}
|
||||
|
||||
.refcount.return_borrowed_ref {
|
||||
color: var(--refcount-return-borrowed-ref)
|
||||
}
|
||||
|
||||
.stableabi {
|
||||
color: #229;
|
||||
}
|
||||
|
||||
dl > dt span ~ em,
|
||||
.sig {
|
||||
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||
}
|
||||
|
||||
.toctree-wrapper ul {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.theme-selector {
|
||||
margin-left: .5em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox,
|
||||
div.genindex-jumpbox > p {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox a {
|
||||
margin: 0 5px;
|
||||
min-width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.copybutton {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
||||
font-size: 80%;
|
||||
padding-left: .5em;
|
||||
padding-right: .5em;
|
||||
height: 100%;
|
||||
max-height: min(100%, 2.4em);
|
||||
border-radius: 0 3px 0 0;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ac9; /* follows div.body pre */
|
||||
display: none;
|
||||
}
|
||||
|
||||
.copybutton:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.copybutton:active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
.highlight:active .copybutton {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.highlight:hover .copybutton {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
/* Body layout */
|
||||
div.body {
|
||||
min-width: 100%;
|
||||
padding: 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
div.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
/* Typography */
|
||||
div.body h1 {
|
||||
font-size: 1.625rem;
|
||||
}
|
||||
div.body h2 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
div.body h3, div.body h4, div.body h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
/* Override default styles to make more readable */
|
||||
div.body ul {
|
||||
padding-inline-start: 1rem;
|
||||
}
|
||||
div.body blockquote {
|
||||
margin-inline-start: 1rem;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
/* Remove sidebar and top related bar */
|
||||
div.related, div.sphinxsidebar {
|
||||
display: none;
|
||||
}
|
||||
/* Anchorlinks are not hidden by fixed-positioned navbar when scrolled to */
|
||||
html {
|
||||
scroll-padding-top: 40px;
|
||||
}
|
||||
body {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
/* Top navigation bar */
|
||||
.mobile-nav {
|
||||
display: block;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
box-shadow: rgba(0, 0, 0, 0.25) 0 0 2px 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.mobile-nav * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.nav-content {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
height: 40px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
background-color: white;
|
||||
}
|
||||
.nav-items-wrapper {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
padding: .25rem;
|
||||
align-items: stretch;
|
||||
}
|
||||
.nav-logo {
|
||||
margin-right: 1rem;
|
||||
flex-shrink: 0;
|
||||
align-self: center;
|
||||
}
|
||||
.nav-content img {
|
||||
display: block;
|
||||
width: 20px;
|
||||
}
|
||||
.version_switcher_placeholder {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.version_switcher_placeholder > select {
|
||||
height: 100%;
|
||||
}
|
||||
.nav-content .search {
|
||||
display: flex;
|
||||
flex: auto;
|
||||
border: 1px solid #a9a9a9;
|
||||
align-items: stretch;
|
||||
}
|
||||
.nav-content .search input[type=search] {
|
||||
border: 0;
|
||||
padding-left: 24px;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
}
|
||||
.nav-content .search input[type=submit] {
|
||||
height: 100%;
|
||||
box-shadow: none;
|
||||
border: 0;
|
||||
border-left: 1px solid #a9a9a9;
|
||||
cursor: pointer;
|
||||
margin-right: 0;
|
||||
}
|
||||
.nav-content .search svg {
|
||||
position: absolute;
|
||||
align-self: center;
|
||||
padding-left: 4px;
|
||||
}
|
||||
.toggler__input {
|
||||
display: none;
|
||||
}
|
||||
.toggler__label {
|
||||
width: 40px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.toggler__label:hover, .toggler__label:focus {
|
||||
background-color: rgba(127 127 127 / 50%);
|
||||
}
|
||||
.toggler__label > span {
|
||||
position: relative;
|
||||
flex: none;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
background: currentColor;
|
||||
transition: all 400ms ease;
|
||||
}
|
||||
.toggler__label > span::before,
|
||||
.toggler__label > span::after {
|
||||
content: '';
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
background: inherit;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -8px;
|
||||
}
|
||||
.toggler__label > span::after {
|
||||
top: 8px;
|
||||
}
|
||||
.toggler__input:checked ~ nav > .toggler__label span {
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
.toggler__input:checked ~ nav > .toggler__label span::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.toggler__input:checked ~ nav > .toggler__label span::before,
|
||||
.toggler__input:checked ~ nav > .toggler__label span::after {
|
||||
top: 0;
|
||||
}
|
||||
.toggler__input:checked:hover ~ nav > .toggler__label span {
|
||||
transform: rotate(315deg);
|
||||
}
|
||||
.toggler__input:checked ~ .menu-wrapper {
|
||||
visibility: visible;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Sliding side menu */
|
||||
.menu-wrapper {
|
||||
display: block;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
transition: left 400ms ease;
|
||||
left: -310px;
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
background-color: #eee;
|
||||
color: #444444;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.menu-wrapper.open {
|
||||
visibility: visible;
|
||||
left: 0;
|
||||
}
|
||||
.menu {
|
||||
padding: 40px 10px 30px 20px;
|
||||
}
|
||||
.menu-wrapper h3,
|
||||
.menu-wrapper h4 {
|
||||
margin-bottom: 0;
|
||||
font-weight: normal;
|
||||
}
|
||||
.menu-wrapper h4 {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
.menu-wrapper h3 {
|
||||
font-size: 1.4em;
|
||||
}
|
||||
.menu-wrapper h3 + p,
|
||||
.menu-wrapper h4 + p {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.menu a {
|
||||
font-size: smaller;
|
||||
text-decoration: none;
|
||||
}
|
||||
.menu ul {
|
||||
list-style: none;
|
||||
line-height: 1.4;
|
||||
overflow-wrap: break-word;
|
||||
padding-left: 0;
|
||||
}
|
||||
.menu ul ul {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
.menu ul li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.language_switcher_placeholder {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.language_switcher_placeholder select {
|
||||
width: 100%;
|
||||
}
|
||||
.document {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
/*Responsive tables*/
|
||||
.responsive-table__container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.menu .theme-selector-label {
|
||||
margin-top: .5em;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.menu .theme-selector {
|
||||
flex: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
div.footer {
|
||||
margin-top: -2em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Version change directives */
|
||||
:root {
|
||||
--versionadded: var(--good-color);
|
||||
--versionchanged: var(--middle-color);
|
||||
--deprecated: var(--bad-color);
|
||||
|
||||
--versionadded-border: var(--good-border);
|
||||
--versionchanged-border: var(--middle-border);
|
||||
--deprecated-border: var(--bad-border);
|
||||
}
|
||||
|
||||
div.versionadded,
|
||||
div.versionchanged,
|
||||
div.deprecated,
|
||||
div.deprecated-removed {
|
||||
border-left: 3px solid;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
div.versionadded {
|
||||
border-left-color: var(--versionadded-border);
|
||||
}
|
||||
|
||||
div.versionchanged {
|
||||
border-left-color: var(--versionchanged-border);
|
||||
}
|
||||
|
||||
div.deprecated,
|
||||
div.deprecated-removed,
|
||||
div.versionremoved {
|
||||
border-left-color: var(--deprecated-border);
|
||||
}
|
||||
|
||||
div.versionadded .versionmodified {
|
||||
color: var(--versionadded);
|
||||
}
|
||||
|
||||
div.versionchanged .versionmodified {
|
||||
color: var(--versionchanged);
|
||||
}
|
||||
|
||||
div.deprecated .versionmodified,
|
||||
div.deprecated-removed .versionmodified,
|
||||
div.versionremoved .versionmodified {
|
||||
color: var(--deprecated);
|
||||
}
|
||||
|
||||
/* Hide header when printing */
|
||||
@media print {
|
||||
div.mobile-nav {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
191
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/pydoctheme_dark.css
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/* Common colours */
|
||||
:root {
|
||||
--good-color: rgb(79 196 100);
|
||||
--good-border: var(--good-color);
|
||||
--middle-color: rgb(244, 227, 76);
|
||||
--middle-border: var(--middle-color);
|
||||
--bad-color: rgb(244, 76, 78);
|
||||
--bad-border: var(--bad-color);
|
||||
}
|
||||
|
||||
|
||||
/* Browser elements */
|
||||
:root {
|
||||
scrollbar-color: #616161 transparent;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
background-color: #222;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
}
|
||||
|
||||
div.related {
|
||||
color: rgba(255, 255, 255, 0.7); /* classic overwrite */
|
||||
border-color: #424242;
|
||||
}
|
||||
|
||||
/* SIDEBAR */
|
||||
div.sphinxsidebar, .menu-wrapper {
|
||||
background-color: #333;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#sidebarbutton {
|
||||
/* important to overwrite style attribute */
|
||||
background-color: #555 !important;
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
div.sidebar, aside.sidebar {
|
||||
background-color: #424242;
|
||||
border-color: #616161;
|
||||
}
|
||||
|
||||
/* ANCHORS AND HIGHLIGHTS */
|
||||
div.body a {
|
||||
color: #7af;
|
||||
}
|
||||
|
||||
div.body a:visited {
|
||||
color: #09e;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
div.related a {
|
||||
color: currentColor;
|
||||
}
|
||||
|
||||
div.footer,
|
||||
div.footer a {
|
||||
color: currentColor; /* classic overwrites */
|
||||
}
|
||||
|
||||
dt:target,
|
||||
span.highlighted {
|
||||
background-color: #616161;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #2c3e50;
|
||||
}
|
||||
|
||||
/* Below for most things in text */
|
||||
|
||||
dl.field-list > dt {
|
||||
background-color: #434;
|
||||
}
|
||||
|
||||
table.docutils td,
|
||||
table.docutils th {
|
||||
border-color: #616161 !important;
|
||||
}
|
||||
|
||||
table.docutils th {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
.stableabi {
|
||||
color: #bbf;
|
||||
}
|
||||
|
||||
div.body pre {
|
||||
border-color: #616161;
|
||||
}
|
||||
|
||||
code {
|
||||
background-color: #424242;
|
||||
}
|
||||
|
||||
div.body div.seealso {
|
||||
background-color: rgba(255, 255, 0, 0.1);
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: rgba(255, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.warning code {
|
||||
background-color: rgba(255, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
/* Admonitions */
|
||||
:root {
|
||||
--admonition-background: #ffffff1a;
|
||||
--admonition-border: currentColor;
|
||||
--admonition-color: #ffffffde;
|
||||
--attention-background: #ffffff1a;
|
||||
--attention-border: currentColor;
|
||||
--caution-background: #ffff001a;
|
||||
--caution-border: #dd6;
|
||||
--danger-background: #f003;
|
||||
--danger-border: #f66;
|
||||
--error-background: #f003;
|
||||
--error-border: #f66;
|
||||
--hint-background: #0044117a;
|
||||
--hint-border: green;
|
||||
--seealso-background: #ffff001a;
|
||||
--seealso-border: #dd6;
|
||||
--tip-background: #0044117a;
|
||||
--tip-border: green;
|
||||
--warning-background: #ff000033;
|
||||
--warning-border: #ff6666;
|
||||
}
|
||||
|
||||
aside.topic,
|
||||
div.topic,
|
||||
div.note,
|
||||
nav.contents {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
border-color: currentColor;
|
||||
}
|
||||
|
||||
.note code {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.mobile-nav {
|
||||
box-shadow: rgba(255, 255, 255, 0.25) 0 0 2px 0;
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
img.invert-in-dark-mode {
|
||||
filter: invert(1) hue-rotate(.5turn);
|
||||
}
|
||||
|
||||
/* -- object description styles --------------------------------------------- */
|
||||
|
||||
/* C++ specific styling */
|
||||
|
||||
/* Override Sphinx's basic.css to fix colour contrast */
|
||||
.sig.c .k, .sig.c .kt,
|
||||
.sig.cpp .k, .sig.cpp .kt {
|
||||
color: #5283ff;
|
||||
}
|
||||
|
||||
/* Version change directives */
|
||||
:root {
|
||||
--versionadded: var(--good-color);
|
||||
--versionchanged: var(--middle-color);
|
||||
--deprecated: var(--bad-color);
|
||||
}
|
||||
|
||||
.copybutton {
|
||||
color: #ac9; /* follows div.body pre */
|
||||
background-color: #222222; /* follows body */
|
||||
}
|
||||
|
||||
.copybutton:hover {
|
||||
background-color: #434343;
|
||||
}
|
||||
|
||||
.copybutton:active {
|
||||
background-color: #656565;
|
||||
}
|
||||
75
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/pygments.css
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
pre { line-height: 125%; }
|
||||
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #f8f8f8; }
|
||||
.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #F00 } /* Error */
|
||||
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666 } /* Operator */
|
||||
.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #9C6500 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
|
||||
.highlight .gr { color: #E40000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #008400 } /* Generic.Inserted */
|
||||
.highlight .go { color: #717171 } /* Generic.Output */
|
||||
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #04D } /* Generic.Traceback */
|
||||
.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #008000 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #B00040 } /* Keyword.Type */
|
||||
.highlight .m { color: #666 } /* Literal.Number */
|
||||
.highlight .s { color: #BA2121 } /* Literal.String */
|
||||
.highlight .na { color: #687822 } /* Name.Attribute */
|
||||
.highlight .nb { color: #008000 } /* Name.Builtin */
|
||||
.highlight .nc { color: #00F; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #800 } /* Name.Constant */
|
||||
.highlight .nd { color: #A2F } /* Name.Decorator */
|
||||
.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #00F } /* Name.Function */
|
||||
.highlight .nl { color: #767600 } /* Name.Label */
|
||||
.highlight .nn { color: #00F; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #19177C } /* Name.Variable */
|
||||
.highlight .ow { color: #A2F; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #BBB } /* Text.Whitespace */
|
||||
.highlight .mb { color: #666 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #666 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #666 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #666 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #666 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #BA2121 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #BA2121 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #008000 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #A45A77 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #00F } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #19177C } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #19177C } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #19177C } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #666 } /* Literal.Number.Integer.Long */
|
||||
85
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/pygments_dark.css
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
pre { line-height: 125%; }
|
||||
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.highlight .hll { background-color: #49483e }
|
||||
.highlight { background: #272822; color: #F8F8F2 }
|
||||
.highlight .c { color: #959077 } /* Comment */
|
||||
.highlight .err { color: #ED007E; background-color: #1E0010 } /* Error */
|
||||
.highlight .esc { color: #F8F8F2 } /* Escape */
|
||||
.highlight .g { color: #F8F8F2 } /* Generic */
|
||||
.highlight .k { color: #66D9EF } /* Keyword */
|
||||
.highlight .l { color: #AE81FF } /* Literal */
|
||||
.highlight .n { color: #F8F8F2 } /* Name */
|
||||
.highlight .o { color: #FF4689 } /* Operator */
|
||||
.highlight .x { color: #F8F8F2 } /* Other */
|
||||
.highlight .p { color: #F8F8F2 } /* Punctuation */
|
||||
.highlight .ch { color: #959077 } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #959077 } /* Comment.Multiline */
|
||||
.highlight .cp { color: #959077 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #959077 } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #959077 } /* Comment.Single */
|
||||
.highlight .cs { color: #959077 } /* Comment.Special */
|
||||
.highlight .gd { color: #FF4689 } /* Generic.Deleted */
|
||||
.highlight .ge { color: #F8F8F2; font-style: italic } /* Generic.Emph */
|
||||
.highlight .ges { color: #F8F8F2; font-weight: bold; font-style: italic } /* Generic.EmphStrong */
|
||||
.highlight .gr { color: #F8F8F2 } /* Generic.Error */
|
||||
.highlight .gh { color: #F8F8F2 } /* Generic.Heading */
|
||||
.highlight .gi { color: #A6E22E } /* Generic.Inserted */
|
||||
.highlight .go { color: #66D9EF } /* Generic.Output */
|
||||
.highlight .gp { color: #FF4689; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { color: #F8F8F2; font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #959077 } /* Generic.Subheading */
|
||||
.highlight .gt { color: #F8F8F2 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #66D9EF } /* Keyword.Constant */
|
||||
.highlight .kd { color: #66D9EF } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #FF4689 } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #66D9EF } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #66D9EF } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #66D9EF } /* Keyword.Type */
|
||||
.highlight .ld { color: #E6DB74 } /* Literal.Date */
|
||||
.highlight .m { color: #AE81FF } /* Literal.Number */
|
||||
.highlight .s { color: #E6DB74 } /* Literal.String */
|
||||
.highlight .na { color: #A6E22E } /* Name.Attribute */
|
||||
.highlight .nb { color: #F8F8F2 } /* Name.Builtin */
|
||||
.highlight .nc { color: #A6E22E } /* Name.Class */
|
||||
.highlight .no { color: #66D9EF } /* Name.Constant */
|
||||
.highlight .nd { color: #A6E22E } /* Name.Decorator */
|
||||
.highlight .ni { color: #F8F8F2 } /* Name.Entity */
|
||||
.highlight .ne { color: #A6E22E } /* Name.Exception */
|
||||
.highlight .nf { color: #A6E22E } /* Name.Function */
|
||||
.highlight .nl { color: #F8F8F2 } /* Name.Label */
|
||||
.highlight .nn { color: #F8F8F2 } /* Name.Namespace */
|
||||
.highlight .nx { color: #A6E22E } /* Name.Other */
|
||||
.highlight .py { color: #F8F8F2 } /* Name.Property */
|
||||
.highlight .nt { color: #FF4689 } /* Name.Tag */
|
||||
.highlight .nv { color: #F8F8F2 } /* Name.Variable */
|
||||
.highlight .ow { color: #FF4689 } /* Operator.Word */
|
||||
.highlight .pm { color: #F8F8F2 } /* Punctuation.Marker */
|
||||
.highlight .w { color: #F8F8F2 } /* Text.Whitespace */
|
||||
.highlight .mb { color: #AE81FF } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #AE81FF } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #AE81FF } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #AE81FF } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #AE81FF } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #E6DB74 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #E6DB74 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #E6DB74 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #E6DB74 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #E6DB74 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #E6DB74 } /* Literal.String.Double */
|
||||
.highlight .se { color: #AE81FF } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #E6DB74 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #E6DB74 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #E6DB74 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #E6DB74 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #E6DB74 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #E6DB74 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #F8F8F2 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #A6E22E } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #F8F8F2 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #F8F8F2 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #F8F8F2 } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #F8F8F2 } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #AE81FF } /* Literal.Number.Integer.Long */
|
||||
55
dist/main/_internal/Utils/PythonNew32/Doc/html/_static/rtd_switcher.js
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
function onSwitch(event) {
|
||||
const option = event.target.selectedIndex;
|
||||
const item = event.target.options[option];
|
||||
window.location.href = item.dataset.url;
|
||||
}
|
||||
|
||||
document.addEventListener("readthedocs-addons-data-ready", function(event) {
|
||||
const config = event.detail.data()
|
||||
const versionSelect = `
|
||||
<select id="version_select" aria-label="Python version">
|
||||
${ config.versions.active.map(
|
||||
(version) => `
|
||||
<option
|
||||
value="${ version.slug }"
|
||||
${ config.versions.current.slug === version.slug ? 'selected="selected"' : '' }
|
||||
data-url="${ version.urls.documentation }">
|
||||
${ version.slug }
|
||||
</option>`
|
||||
).join("\n") }
|
||||
</select>
|
||||
`;
|
||||
|
||||
// Prepend the current language to the options on the selector
|
||||
let languages = config.projects.translations.concat(config.projects.current);
|
||||
languages = languages.sort((a, b) => a.language.name.localeCompare(b.language.name));
|
||||
|
||||
const languageSelect = `
|
||||
<select id="language_select" aria-label="Language">
|
||||
${ languages.map(
|
||||
(translation) => `
|
||||
<option
|
||||
value="${ translation.slug }"
|
||||
${ config.projects.current.slug === translation.slug ? 'selected="selected"' : '' }
|
||||
data-url="${ translation.urls.documentation }">
|
||||
${ translation.language.name }
|
||||
</option>`
|
||||
).join("\n") }
|
||||
</select>
|
||||
`;
|
||||
|
||||
// Query all the placeholders because there are different ones for Desktop/Mobile
|
||||
const versionPlaceholders = document.querySelectorAll(".version_switcher_placeholder");
|
||||
for (placeholder of versionPlaceholders) {
|
||||
placeholder.innerHTML = versionSelect;
|
||||
let selectElement = placeholder.querySelector("select");
|
||||
selectElement.addEventListener("change", onSwitch);
|
||||
}
|
||||
|
||||
const languagePlaceholders = document.querySelectorAll(".language_switcher_placeholder");
|
||||
for (placeholder of languagePlaceholders) {
|
||||
placeholder.innerHTML = languageSelect;
|
||||
let selectElement = placeholder.querySelector("select");
|
||||
selectElement.addEventListener("change", onSwitch);
|
||||
}
|
||||
});
|
||||