1.修改部分代码风格,实现风格统一 2.添加数据刷新时间到config中 3.将html单独放到文件中并且添加一些相关说明

This commit is contained in:
2025-08-14 15:04:11 +08:00
parent 04bdb5f52b
commit 10959132b7
179 changed files with 1499 additions and 44780 deletions

View File

@ -5,6 +5,7 @@
"ip": "192.168.0.1",
"rack": 0,
"slot": 1,
"refresh_interval": 0.5,
"areas": [
{
"name": "DB100_Read",

View File

@ -5,6 +5,7 @@
"ip": "192.168.0.1",
"rack": 0,
"slot": 1,
"refresh_interval": 1,
"areas": [
{
"name": "DB100_Read",
@ -35,7 +36,7 @@
"name": "DB100_Write",
"type": "write",
"db_number": 100,
"offset": 4000,
"offset": 0,
"size": 5000
},
{

446
gateway/api_server_html.py Normal file
View File

@ -0,0 +1,446 @@
from flask import Flask, jsonify, request, render_template_string, Response, render_template
import threading
import time
import json
from functools import wraps
from config_manager import ConfigManager
import logging
class APIServer:
"""REST API服务器提供PLC数据访问和配置管理功能"""
def __init__(self, cache_manager, config_path="config/config.json"):
"""
初始化API服务器
Args:
cache_manager: 缓存管理器实例
config_path: 配置文件路径
"""
self.cache_manager = cache_manager
self.config_manager = ConfigManager(config_path)
self.app = Flask(__name__)
self.logger = logging.getLogger("APIServer")
self.auth_enabled = True # 可通过配置关闭认证
self.username = "admin"
self.password = "admin123" # 实际应用中应从安全存储获取
self.start_time = time.strftime("%Y-%m-%d %H:%M:%S")
# 在初始化方法中调用 setup_routes
self.setup_routes()
def check_auth(self, username, password):
"""验证用户名和密码"""
return username == self.username and password == self.password
def authenticate(self):
"""发送401响应要求认证"""
return Response(
"Unauthorized",
401,
{"WWW-Authenticate": 'Basic realm="PLC Gateway Configuration"'}
)
def requires_auth(self, f):
"""装饰器:需要认证的路由,保留函数元数据"""
@wraps(f)
def decorated(*args, **kwargs):
if not self.auth_enabled:
return f(*args, **kwargs)
auth = request.authorization
if not auth or not self.check_auth(auth.username, auth.password):
return self.authenticate()
return f(*args, **kwargs)
return decorated
def get_summary(self):
"""获取缓存摘要信息"""
summary = {}
for plc_name, areas in self.cache_manager.cache.items():
summary[plc_name] = {}
for area_name, area in areas.items():
last_update = self.cache_manager.last_update[plc_name][area_name]
plc_status = self.cache_manager.plc_connection_status.get(plc_name, "unknown")
summary[plc_name][area_name] = {
"status": area["status"],
"plc_connection_status": plc_status,
"last_update": time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(last_update)) if last_update > 0 else "Never",
"size": area["size"],
"type": area["type"]
}
return summary
def setup_routes(self):
"""设置所有API路由"""
# ===========================
# 主页面 - 状态摘要
# ===========================
@self.app.route("/", endpoint="index")
def index():
summary = self.get_summary()
return render_template(
"status.html", # 模板文件名
start_time=self.start_time,
summary=summary,
plc_statuses=self.cache_manager.plc_connection_status
)
# ===========================
# 系统状态API
# ===========================
@self.app.route("/api/status", endpoint="system_status")
def system_status():
"""获取系统状态信息"""
plc_statuses = {}
for plc_name in self.cache_manager.plc_connection_status:
plc_statuses[plc_name] = {
"status": self.cache_manager.plc_connection_status[plc_name],
"last_connected": time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(self.cache_manager.plc_last_connected[plc_name]))
if self.cache_manager.plc_last_connected[plc_name] > 0 else "Never"
}
return jsonify({
"status": "running",
"start_time": self.start_time,
"plc_count": len(self.config_manager.get_config().get("plcs", [])),
"cache_size": sum(
len(area["data"]) for plc in self.cache_manager.cache.values() for area in plc.values()),
"plc_statuses": plc_statuses
})
# ===========================
# 配置管理相关路由
# ===========================
@self.app.route("/config", endpoint="config_page")
@self.requires_auth
def config_page():
"""配置编辑页面"""
config = self.config_manager.get_config()
config_json = json.dumps(config, indent=2)
return render_template(
'config.html',
config_json=config_json,
username=self.username,
password=self.password
)
# 配置验证API
@self.app.route("/api/config/validate", methods=["POST"], endpoint="validate_config")
@self.requires_auth
def validate_config():
"""验证配置是否有效"""
try:
config = request.json
is_valid, error = self.config_manager.validate_config(config)
if is_valid:
return jsonify({"valid": True})
else:
return jsonify({"valid": False, "message": error}), 400
except Exception as e:
return jsonify({"valid": False, "message": str(e)}), 400
# 配置获取API
@self.app.route("/api/config", methods=["GET"], endpoint="get_config")
@self.requires_auth
def get_config():
"""获取当前配置"""
return jsonify(self.config_manager.get_config())
# 配置保存API
@self.app.route("/api/config", methods=["POST"], endpoint="save_config")
@self.requires_auth
def save_config():
"""保存配置"""
try:
config = request.json
reload = request.args.get('reload', 'false').lower() == 'true'
success, message = self.config_manager.save_config(config)
if success:
if reload:
# 通知主应用程序重载配置
if hasattr(self.cache_manager, 'app') and self.cache_manager.app:
self.cache_manager.app.request_reload()
return jsonify({
"success": True,
"message": "Configuration saved and reload requested"
})
else:
return jsonify({
"success": True,
"message": "Configuration saved successfully (restart to apply changes)"
})
else:
return jsonify({
"success": False,
"message": message
}), 400
except Exception as e:
return jsonify({
"success": False,
"message": f"Error saving config: {str(e)}"
}), 500
# ===========================
# 新增 API 文档接口
# ===========================
@self.app.route("/api/doc", endpoint="api_doc")
def api_doc():
"""API文档页面"""
return render_template('api_doc.html')
# ===========================
# 数据访问API
# ===========================
# 单个读取接口
@self.app.route("/api/read/<plc_name>/<area_name>/<int:offset>/<int:length>", methods=["GET"],
endpoint="single_read")
def single_read(plc_name, area_name, offset, length):
"""从指定区域读取数据"""
data, error, plc_status, update_time = self.cache_manager.read_area(plc_name, area_name, offset, length)
if error:
return jsonify({
"status": "error",
"plc_name": plc_name,
"area_name": area_name,
"message": error,
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(update_time)) if update_time > 0 else "Never"
}), 400
return jsonify({
"status": "success",
"plc_name": plc_name,
"area_name": area_name,
"offset": offset,
"length": length,
"data": list(data),
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_time))
})
# 单个读取BOOL类型接口
@self.app.route("/api/read_bool/<plc_name>/<area_name>/<int:offset>/<int:length>", methods=["GET"],
endpoint="single_read_bool")
def single_read_bool(plc_name, area_name, offset, length):
"""从指定区域读取数据"""
data, error, plc_status, update_time = self.cache_manager.read_area_bool(plc_name, area_name, offset,
length)
if error:
return jsonify({
"status": "error",
"plc_name": plc_name,
"area_name": area_name,
"message": error,
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(update_time)) if update_time > 0 else "Never"
}), 400
return jsonify({
"status": "success",
"plc_name": plc_name,
"area_name": area_name,
"offset": offset,
"length": length,
"data": [data], # list(data)
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_time))
})
# 单个写入接口
@self.app.route("/api/write/<plc_name>/<area_name>/<int:offset>", methods=["POST"], endpoint="single_write")
def single_write(plc_name, area_name, offset):
"""向指定区域写入数据"""
data = request.data
if not data:
# 如果没有提供数据,返回错误
return jsonify({
"status": "error",
"message": "No data provided",
"plc_connection_status": self.cache_manager.plc_connection_status.get(plc_name, "unknown"),
"last_update": 0,
"last_update_formatted": "N/A"
}), 400
success, error, plc_status, update_time = self.cache_manager.write_area(plc_name, area_name, offset, data)
if error:
return jsonify({
"status": "error",
"plc_name": plc_name,
"area_name": area_name,
"message": error,
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(update_time)) if update_time > 0 else "Never"
}), 400
return jsonify({
"status": "success",
"plc_name": plc_name,
"area_name": area_name,
"offset": offset,
"length": len(data),
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_time))
})
# 单个写入BOOL类型接口
@self.app.route("/api/write_bool/<plc_name>/<area_name>/<int:offset>", methods=["POST"],
endpoint="single_write_bool")
def single_write_bool(plc_name, area_name, offset):
"""向指定区域写入数据"""
data = request.data
if not data:
# 如果没有提供数据,返回错误
return jsonify({
"status": "error",
"message": "No data provided",
"plc_connection_status": self.cache_manager.plc_connection_status.get(plc_name, "unknown"),
"last_update": 0,
"last_update_formatted": "N/A"
}), 400
success, error, plc_status, update_time = self.cache_manager.write_area_bool(plc_name, area_name, offset,
data)
if error:
return jsonify({
"status": "error",
"plc_name": plc_name,
"area_name": area_name,
"message": error,
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(update_time)) if update_time > 0 else "Never"
}), 400
return jsonify({
"status": "success",
"plc_name": plc_name,
"area_name": area_name,
"offset": offset,
"length": 1,
"plc_connection_status": plc_status,
"last_update": update_time,
"last_update_formatted": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_time))
})
# 批量读取接口
@self.app.route("/api/batch_read", methods=["POST"], endpoint="batch_read")
def batch_read():
"""批量读取多个区域的数据"""
try:
# 确保是JSON请求
if not request.is_json:
return jsonify({
"status": "error",
"message": "Request must be JSON (Content-Type: application/json)",
"plc_connection_status": "unknown",
"last_update": 0,
"last_update_formatted": "N/A"
}), 400
requests = request.json
if not isinstance(requests, list):
return jsonify({
"status": "error",
"message": "Request must be a JSON array",
"plc_connection_status": "unknown",
"last_update": 0,
"last_update_formatted": "N/A"
}), 400
# 添加详细日志
self.logger.info(f"Received batch read request: {json.dumps(requests)}")
results = self.cache_manager.batch_read(requests)
return jsonify(results)
except Exception as e:
self.logger.error(f"Batch read error: {str(e)}", exc_info=True)
return jsonify({
"status": "error",
"message": f"Internal server error: {str(e)}",
"plc_connection_status": "unknown",
"last_update": 0,
"last_update_formatted": "N/A"
}), 500
# 批量写入接口
@self.app.route("/api/batch_write", methods=["POST"], endpoint="batch_write")
def batch_write():
"""批量写入多个区域的数据"""
try:
if not request.is_json:
return jsonify({
"status": "error",
"message": "Request must be JSON (Content-Type: application/json)",
"plc_connection_status": "unknown",
"last_update": 0,
"last_update_formatted": "N/A"
}), 400
requests = request.json
if not isinstance(requests, list):
return jsonify({
"status": "error",
"message": "Request must be a JSON array",
"plc_connection_status": "unknown",
"last_update": 0,
"last_update_formatted": "N/A"
}), 400
self.logger.info(f"Received batch write request: {json.dumps(requests)}")
results = self.cache_manager.batch_write(requests)
return jsonify(results)
except Exception as e:
self.logger.error(f"Batch write error: {str(e)}", exc_info=True)
return jsonify({
"status": "error",
"message": f"Internal server error: {str(e)}",
"plc_connection_status": "unknown",
"last_update": 0,
"last_update_formatted": "N/A"
}), 500
# 区域状态检查
@self.app.route("/api/status/<plc_name>/<area_name>", methods=["GET"], endpoint="area_status")
def area_status(plc_name, area_name):
"""获取区域状态"""
status = self.cache_manager.get_area_status(plc_name, area_name)
return jsonify(status)
# 获取解析后的数据
@self.app.route("/api/data/<plc_name>/<area_name>", methods=["GET"], endpoint="get_parsed_data")
def get_parsed_data(plc_name, area_name):
"""获取解析后的数据"""
return jsonify(self.cache_manager.get_parsed_data(plc_name, area_name))
def start(self):
"""启动API服务器"""
self.server_thread = threading.Thread(
target=self.app.run,
kwargs={
"host": "0.0.0.0",
"port": 5000,
"threaded": True,
"use_reloader": False # 避免在生产环境中使用重载器
},
daemon=True,
name="APIServerThread"
)
self.server_thread.start()
self.logger.info("API server started at http://0.0.0.0:5000")

File diff suppressed because it is too large Load Diff

View File

@ -1,467 +0,0 @@
([('main.exe',
'D:\\Projects\\gateway\\gateway\\build\\main\\main.exe',
'EXECUTABLE'),
('python313.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\python313.dll',
'BINARY'),
('select.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\select.pyd',
'EXTENSION'),
('_socket.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_socket.pyd',
'EXTENSION'),
('_lzma.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_lzma.pyd',
'EXTENSION'),
('_bz2.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_bz2.pyd',
'EXTENSION'),
('_decimal.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_decimal.pyd',
'EXTENSION'),
('_hashlib.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_hashlib.pyd',
'EXTENSION'),
('unicodedata.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\unicodedata.pyd',
'EXTENSION'),
('_ctypes.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_ctypes.pyd',
'EXTENSION'),
('_queue.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_queue.pyd',
'EXTENSION'),
('_overlapped.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_overlapped.pyd',
'EXTENSION'),
('_ssl.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_ssl.pyd',
'EXTENSION'),
('_asyncio.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_asyncio.pyd',
'EXTENSION'),
('_multiprocessing.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_multiprocessing.pyd',
'EXTENSION'),
('pyexpat.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\pyexpat.pyd',
'EXTENSION'),
('_wmi.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_wmi.pyd',
'EXTENSION'),
('rpds\\rpds.cp313-win_amd64.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\rpds\\rpds.cp313-win_amd64.pyd',
'EXTENSION'),
('charset_normalizer\\md__mypyc.cp313-win_amd64.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\charset_normalizer\\md__mypyc.cp313-win_amd64.pyd',
'EXTENSION'),
('charset_normalizer\\md.cp313-win_amd64.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\charset_normalizer\\md.cp313-win_amd64.pyd',
'EXTENSION'),
('_uuid.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\DLLs\\_uuid.pyd',
'EXTENSION'),
('markupsafe\\_speedups.cp313-win_amd64.pyd',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\markupsafe\\_speedups.cp313-win_amd64.pyd',
'EXTENSION'),
('api-ms-win-crt-conio-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-conio-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-runtime-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-runtime-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-string-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-string-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-heap-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-heap-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-filesystem-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-filesystem-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-time-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-time-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-stdio-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-stdio-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-locale-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-locale-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-process-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-process-l1-1-0.dll',
'BINARY'),
('zlib.dll', 'D:\\ProgramFiles\\Anaconda\\envs\\ota\\zlib.dll', 'BINARY'),
('api-ms-win-crt-math-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-math-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-convert-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-convert-l1-1-0.dll',
'BINARY'),
('api-ms-win-crt-environment-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-crt-environment-l1-1-0.dll',
'BINARY'),
('VCRUNTIME140.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\VCRUNTIME140.dll',
'BINARY'),
('liblzma.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\liblzma.dll',
'BINARY'),
('LIBBZ2.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\LIBBZ2.dll',
'BINARY'),
('libmpdec-4.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\libmpdec-4.dll',
'BINARY'),
('libcrypto-3-x64.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\libcrypto-3-x64.dll',
'BINARY'),
('ffi.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\ffi.dll',
'BINARY'),
('libssl-3-x64.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\libssl-3-x64.dll',
'BINARY'),
('libexpat.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\libexpat.dll',
'BINARY'),
('api-ms-win-core-synch-l1-2-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-synch-l1-2-0.dll',
'BINARY'),
('ucrtbase.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\ucrtbase.dll',
'BINARY'),
('api-ms-win-crt-utility-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Library\\bin\\api-ms-win-crt-utility-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-handle-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-handle-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-file-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-file-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-file-l1-2-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-file-l1-2-0.dll',
'BINARY'),
('api-ms-win-core-processenvironment-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-processenvironment-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-heap-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-heap-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-sysinfo-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-sysinfo-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-datetime-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-datetime-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-interlocked-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-interlocked-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-processthreads-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-processthreads-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-fibers-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-fibers-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-profile-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-profile-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-processthreads-l1-1-1.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-processthreads-l1-1-1.dll',
'BINARY'),
('api-ms-win-core-util-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-util-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-debug-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-debug-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-timezone-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-timezone-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-synch-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-synch-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-console-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-console-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-errorhandling-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-errorhandling-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-string-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-string-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-rtlsupport-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-rtlsupport-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-libraryloader-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-libraryloader-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-localization-l1-2-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-localization-l1-2-0.dll',
'BINARY'),
('api-ms-win-core-file-l2-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-file-l2-1-0.dll',
'BINARY'),
('api-ms-win-core-memory-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-memory-l1-1-0.dll',
'BINARY'),
('api-ms-win-core-namedpipe-l1-1-0.dll',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\api-ms-win-core-namedpipe-l1-1-0.dll',
'BINARY'),
('jsonschema-4.25.0.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\METADATA',
'DATA'),
('jsonschema-4.25.0.dist-info\\REQUESTED',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\REQUESTED',
'DATA'),
('jsonschema-4.25.0.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\RECORD',
'DATA'),
('jsonschema-4.25.0.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\INSTALLER',
'DATA'),
('jsonschema-4.25.0.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\WHEEL',
'DATA'),
('jsonschema-4.25.0.dist-info\\licenses\\COPYING',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\licenses\\COPYING',
'DATA'),
('jsonschema\\benchmarks\\issue232\\issue.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema\\benchmarks\\issue232\\issue.json',
'DATA'),
('jsonschema-4.25.0.dist-info\\entry_points.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema-4.25.0.dist-info\\entry_points.txt',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\METADATA',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\top_level.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\top_level.txt',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\INSTALLER',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\REQUESTED',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\REQUESTED',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\LICENSE',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\LICENSE',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\RECORD',
'DATA'),
('setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\importlib_metadata-8.0.0.dist-info\\WHEEL',
'DATA'),
('setuptools\\_vendor\\jaraco\\text\\Lorem ipsum.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\setuptools\\_vendor\\jaraco\\text\\Lorem '
'ipsum.txt',
'DATA'),
('certifi\\cacert.pem',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\certifi\\cacert.pem',
'DATA'),
('certifi\\py.typed',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\certifi\\py.typed',
'DATA'),
('jsonschema_specifications\\schemas\\draft201909\\vocabularies\\meta-data',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft201909\\vocabularies\\meta-data',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\metaschema.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\metaschema.json',
'DATA'),
('jsonschema_specifications\\schemas\\draft7\\metaschema.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft7\\metaschema.json',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\validation',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\validation',
'DATA'),
('jsonschema_specifications\\schemas\\draft201909\\metaschema.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft201909\\metaschema.json',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\content',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\content',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\format',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\format',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\format-assertion',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\format-assertion',
'DATA'),
('jsonschema_specifications\\schemas\\draft201909\\vocabularies\\core',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft201909\\vocabularies\\core',
'DATA'),
('jsonschema_specifications\\schemas\\draft4\\metaschema.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft4\\metaschema.json',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\format-annotation',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\format-annotation',
'DATA'),
('jsonschema_specifications\\schemas\\draft201909\\vocabularies\\validation',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft201909\\vocabularies\\validation',
'DATA'),
('jsonschema_specifications\\schemas\\draft6\\metaschema.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft6\\metaschema.json',
'DATA'),
('jsonschema_specifications\\schemas\\draft201909\\vocabularies\\applicator',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft201909\\vocabularies\\applicator',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\meta-data',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\meta-data',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\core',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\core',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\unevaluated',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\unevaluated',
'DATA'),
('jsonschema_specifications\\schemas\\draft201909\\vocabularies\\content',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft201909\\vocabularies\\content',
'DATA'),
('jsonschema_specifications\\schemas\\draft202012\\vocabularies\\applicator',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft202012\\vocabularies\\applicator',
'DATA'),
('jsonschema_specifications\\schemas\\draft3\\metaschema.json',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\jsonschema_specifications\\schemas\\draft3\\metaschema.json',
'DATA'),
('click-8.2.1.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\click-8.2.1.dist-info\\RECORD',
'DATA'),
('click-8.2.1.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\click-8.2.1.dist-info\\INSTALLER',
'DATA'),
('flask-3.1.1.dist-info\\entry_points.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\entry_points.txt',
'DATA'),
('flask-3.1.1.dist-info\\licenses\\LICENSE.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\licenses\\LICENSE.txt',
'DATA'),
('attrs-25.3.0.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\attrs-25.3.0.dist-info\\INSTALLER',
'DATA'),
('attrs-25.3.0.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\attrs-25.3.0.dist-info\\RECORD',
'DATA'),
('click-8.2.1.dist-info\\licenses\\LICENSE.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\click-8.2.1.dist-info\\licenses\\LICENSE.txt',
'DATA'),
('attrs-25.3.0.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\attrs-25.3.0.dist-info\\WHEEL',
'DATA'),
('python_snap7-2.0.2.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\INSTALLER',
'DATA'),
('werkzeug-3.1.3.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\werkzeug-3.1.3.dist-info\\WHEEL',
'DATA'),
('attrs-25.3.0.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\attrs-25.3.0.dist-info\\METADATA',
'DATA'),
('itsdangerous-2.2.0.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\itsdangerous-2.2.0.dist-info\\WHEEL',
'DATA'),
('wheel-0.45.1.dist-info\\LICENSE.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\wheel-0.45.1.dist-info\\LICENSE.txt',
'DATA'),
('wheel-0.45.1.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\wheel-0.45.1.dist-info\\RECORD',
'DATA'),
('werkzeug-3.1.3.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\werkzeug-3.1.3.dist-info\\INSTALLER',
'DATA'),
('MarkupSafe-3.0.2.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\MarkupSafe-3.0.2.dist-info\\INSTALLER',
'DATA'),
('python_snap7-2.0.2.dist-info\\entry_points.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\entry_points.txt',
'DATA'),
('flask-3.1.1.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\RECORD',
'DATA'),
('python_snap7-2.0.2.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\METADATA',
'DATA'),
('click-8.2.1.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\click-8.2.1.dist-info\\METADATA',
'DATA'),
('werkzeug-3.1.3.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\werkzeug-3.1.3.dist-info\\METADATA',
'DATA'),
('flask-3.1.1.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\INSTALLER',
'DATA'),
('python_snap7-2.0.2.dist-info\\top_level.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\top_level.txt',
'DATA'),
('MarkupSafe-3.0.2.dist-info\\top_level.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\MarkupSafe-3.0.2.dist-info\\top_level.txt',
'DATA'),
('MarkupSafe-3.0.2.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\MarkupSafe-3.0.2.dist-info\\RECORD',
'DATA'),
('werkzeug-3.1.3.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\werkzeug-3.1.3.dist-info\\RECORD',
'DATA'),
('python_snap7-2.0.2.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\RECORD',
'DATA'),
('flask-3.1.1.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\WHEEL',
'DATA'),
('click-8.2.1.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\click-8.2.1.dist-info\\WHEEL',
'DATA'),
('wheel-0.45.1.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\wheel-0.45.1.dist-info\\METADATA',
'DATA'),
('itsdangerous-2.2.0.dist-info\\INSTALLER',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\itsdangerous-2.2.0.dist-info\\INSTALLER',
'DATA'),
('python_snap7-2.0.2.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\WHEEL',
'DATA'),
('itsdangerous-2.2.0.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\itsdangerous-2.2.0.dist-info\\METADATA',
'DATA'),
('wheel-0.45.1.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\wheel-0.45.1.dist-info\\WHEEL',
'DATA'),
('attrs-25.3.0.dist-info\\licenses\\LICENSE',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\attrs-25.3.0.dist-info\\licenses\\LICENSE',
'DATA'),
('flask-3.1.1.dist-info\\REQUESTED',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\REQUESTED',
'DATA'),
('python_snap7-2.0.2.dist-info\\LICENSE',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\LICENSE',
'DATA'),
('python_snap7-2.0.2.dist-info\\REQUESTED',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\python_snap7-2.0.2.dist-info\\REQUESTED',
'DATA'),
('MarkupSafe-3.0.2.dist-info\\WHEEL',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\MarkupSafe-3.0.2.dist-info\\WHEEL',
'DATA'),
('flask-3.1.1.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\flask-3.1.1.dist-info\\METADATA',
'DATA'),
('wheel-0.45.1.dist-info\\entry_points.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\wheel-0.45.1.dist-info\\entry_points.txt',
'DATA'),
('MarkupSafe-3.0.2.dist-info\\LICENSE.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\MarkupSafe-3.0.2.dist-info\\LICENSE.txt',
'DATA'),
('MarkupSafe-3.0.2.dist-info\\METADATA',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\MarkupSafe-3.0.2.dist-info\\METADATA',
'DATA'),
('itsdangerous-2.2.0.dist-info\\RECORD',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\itsdangerous-2.2.0.dist-info\\RECORD',
'DATA'),
('werkzeug-3.1.3.dist-info\\LICENSE.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\werkzeug-3.1.3.dist-info\\LICENSE.txt',
'DATA'),
('itsdangerous-2.2.0.dist-info\\LICENSE.txt',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\itsdangerous-2.2.0.dist-info\\LICENSE.txt',
'DATA'),
('base_library.zip',
'D:\\Projects\\gateway\\gateway\\build\\main\\base_library.zip',
'DATA')],)

View File

@ -1,78 +0,0 @@
('D:\\Projects\\gateway\\gateway\\build\\main\\main.exe',
True,
False,
True,
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-console.ico',
None,
False,
False,
b'<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n<assembly xmlns='
b'"urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">\n <trustInfo x'
b'mlns="urn:schemas-microsoft-com:asm.v3">\n <security>\n <requested'
b'Privileges>\n <requestedExecutionLevel level="asInvoker" uiAccess='
b'"false"/>\n </requestedPrivileges>\n </security>\n </trustInfo>\n '
b'<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">\n <'
b'application>\n <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f'
b'0}"/>\n <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>\n '
b' <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>\n <s'
b'upportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>\n <supporte'
b'dOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>\n </application>\n <'
b'/compatibility>\n <application xmlns="urn:schemas-microsoft-com:asm.v3">'
b'\n <windowsSettings>\n <longPathAware xmlns="http://schemas.micros'
b'oft.com/SMI/2016/WindowsSettings">true</longPathAware>\n </windowsSett'
b'ings>\n </application>\n <dependency>\n <dependentAssembly>\n <ass'
b'emblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version='
b'"6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" langua'
b'ge="*"/>\n </dependentAssembly>\n </dependency>\n</assembly>',
True,
False,
None,
None,
None,
'D:\\Projects\\gateway\\gateway\\build\\main\\main.pkg',
[('pyi-contents-directory _internal', '', 'OPTION'),
('PYZ-00.pyz',
'D:\\Projects\\gateway\\gateway\\build\\main\\PYZ-00.pyz',
'PYZ'),
('struct',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\struct.pyc',
'PYMODULE'),
('pyimod01_archive',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod01_archive.pyc',
'PYMODULE'),
('pyimod02_importers',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod02_importers.pyc',
'PYMODULE'),
('pyimod03_ctypes',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod03_ctypes.pyc',
'PYMODULE'),
('pyimod04_pywin32',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod04_pywin32.pyc',
'PYMODULE'),
('pyiboot01_bootstrap',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
'PYSOURCE'),
('pyi_rth_inspect',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
'PYSOURCE'),
('pyi_rth_setuptools',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_setuptools.py',
'PYSOURCE'),
('pyi_rth_pkgutil',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
'PYSOURCE'),
('pyi_rth_multiprocessing',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
'PYSOURCE'),
('pyi_rth_pkgres',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgres.py',
'PYSOURCE'),
('main', 'D:\\Projects\\gateway\\gateway\\main.py', 'PYSOURCE')],
[],
False,
False,
1753498013,
[('run.exe',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\bootloader\\Windows-64bit-intel\\run.exe',
'EXECUTABLE')],
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\python313.dll')

View File

@ -1,56 +0,0 @@
('D:\\Projects\\gateway\\gateway\\build\\main\\main.pkg',
{'BINARY': True,
'DATA': True,
'EXECUTABLE': True,
'EXTENSION': True,
'PYMODULE': True,
'PYSOURCE': True,
'PYZ': False,
'SPLASH': True,
'SYMLINK': False},
[('pyi-contents-directory _internal', '', 'OPTION'),
('PYZ-00.pyz',
'D:\\Projects\\gateway\\gateway\\build\\main\\PYZ-00.pyz',
'PYZ'),
('struct',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\struct.pyc',
'PYMODULE'),
('pyimod01_archive',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod01_archive.pyc',
'PYMODULE'),
('pyimod02_importers',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod02_importers.pyc',
'PYMODULE'),
('pyimod03_ctypes',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod03_ctypes.pyc',
'PYMODULE'),
('pyimod04_pywin32',
'D:\\Projects\\gateway\\gateway\\build\\main\\localpycs\\pyimod04_pywin32.pyc',
'PYMODULE'),
('pyiboot01_bootstrap',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\loader\\pyiboot01_bootstrap.py',
'PYSOURCE'),
('pyi_rth_inspect',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_inspect.py',
'PYSOURCE'),
('pyi_rth_setuptools',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_setuptools.py',
'PYSOURCE'),
('pyi_rth_pkgutil',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgutil.py',
'PYSOURCE'),
('pyi_rth_multiprocessing',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py',
'PYSOURCE'),
('pyi_rth_pkgres',
'D:\\ProgramFiles\\Anaconda\\envs\\ota\\Lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_pkgres.py',
'PYSOURCE'),
('main', 'D:\\Projects\\gateway\\gateway\\main.py', 'PYSOURCE')],
'python313.dll',
True,
False,
False,
[],
None,
None,
None)

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,96 +0,0 @@
This file lists modules PyInstaller was not able to find. This does not
necessarily mean this module is required for running your program. Python and
Python 3rd-party packages include a lot of conditional or optional modules. For
example the module 'ntpath' only exists on Windows, whereas the module
'posixpath' only exists on Posix systems.
Types if import:
* top-level: imported at the top-level - look at these first
* conditional: imported within an if-statement
* delayed: imported within a function
* optional: imported within a try-except-statement
IMPORTANT: Do NOT post this list to the issue-tracker. Use it as a basis for
tracking down the missing module yourself. Thanks!
missing module named pyimod02_importers - imported by D:\ProgramFiles\Anaconda\envs\ota\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgutil.py (delayed), D:\ProgramFiles\Anaconda\envs\ota\Lib\site-packages\PyInstaller\hooks\rthooks\pyi_rth_pkgres.py (delayed)
missing module named pwd - imported by posixpath (delayed, conditional, optional), shutil (delayed, optional), tarfile (optional), pathlib._local (optional), subprocess (delayed, conditional, optional), http.server (delayed, optional), setuptools._distutils.util (delayed, conditional, optional), netrc (delayed, conditional), getpass (delayed, optional), setuptools._vendor.backports.tarfile (optional), setuptools._distutils.archive_util (optional)
missing module named grp - imported by shutil (delayed, optional), tarfile (optional), pathlib._local (optional), subprocess (delayed, conditional, optional), setuptools._vendor.backports.tarfile (optional), setuptools._distutils.archive_util (optional)
missing module named _posixsubprocess - imported by subprocess (conditional), multiprocessing.util (delayed)
missing module named fcntl - imported by subprocess (optional), _pyrepl.unix_console (top-level)
missing module named posix - imported by posixpath (optional), shutil (conditional), importlib._bootstrap_external (conditional), os (conditional, optional), _pyrepl.unix_console (delayed, optional)
missing module named resource - imported by posix (top-level)
missing module named _manylinux - imported by packaging._manylinux (delayed, optional), setuptools._vendor.packaging._manylinux (delayed, optional), wheel.vendored.packaging._manylinux (delayed, optional)
missing module named _frozen_importlib_external - imported by importlib._bootstrap (delayed), importlib (optional), importlib.abc (optional), zipimport (top-level)
missing module named typing_extensions.TypeAlias - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.compilers.C.base (conditional), setuptools._reqs (conditional), setuptools.warnings (conditional), setuptools._path (conditional), setuptools._distutils.dist (conditional), setuptools.config.setupcfg (conditional), setuptools.config._apply_pyprojecttoml (conditional), setuptools.dist (conditional), pkg_resources (conditional), setuptools.command.bdist_egg (conditional), setuptools.compat.py311 (conditional)
missing module named typing_extensions.Self - imported by setuptools._vendor.typing_extensions (top-level), setuptools.config.expand (conditional), setuptools.config.pyprojecttoml (conditional), setuptools.config._validate_pyproject.error_reporting (conditional), pkg_resources (conditional)
missing module named asyncio.DefaultEventLoopPolicy - imported by asyncio (delayed, conditional), asyncio.events (delayed, conditional)
missing module named _posixshmem - imported by multiprocessing.resource_tracker (conditional), multiprocessing.shared_memory (conditional)
missing module named multiprocessing.set_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_start_method - imported by multiprocessing (top-level), multiprocessing.spawn (top-level)
missing module named multiprocessing.get_context - imported by multiprocessing (top-level), multiprocessing.pool (top-level), multiprocessing.managers (top-level), multiprocessing.sharedctypes (top-level)
missing module named multiprocessing.TimeoutError - imported by multiprocessing (top-level), multiprocessing.pool (top-level)
missing module named _scproxy - imported by urllib.request (conditional)
missing module named termios - imported by getpass (optional), tty (top-level), _pyrepl.pager (delayed, optional), werkzeug._reloader (delayed, optional), click._termui_impl (conditional), _pyrepl.unix_console (top-level), _pyrepl.fancy_termios (top-level), _pyrepl.unix_eventqueue (top-level)
missing module named multiprocessing.BufferTooShort - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.AuthenticationError - imported by multiprocessing (top-level), multiprocessing.connection (top-level)
missing module named multiprocessing.Value - imported by multiprocessing (top-level), werkzeug.debug (top-level)
missing module named usercustomize - imported by site (delayed, optional)
missing module named sitecustomize - imported by site (delayed, optional)
missing module named _curses - imported by curses (top-level), curses.has_key (top-level), _pyrepl.curses (optional)
missing module named readline - imported by code (delayed, conditional, optional), flask.cli (delayed, conditional, optional), rlcompleter (optional), site (delayed, optional)
missing module named trove_classifiers - imported by setuptools.config._validate_pyproject.formats (optional)
missing module named typing_extensions.Buffer - imported by setuptools._vendor.typing_extensions (top-level), wheel.wheelfile (conditional)
missing module named typing_extensions.Literal - imported by setuptools._vendor.typing_extensions (top-level), setuptools.config._validate_pyproject.formats (conditional)
missing module named typing_extensions.deprecated - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.sysconfig (conditional), setuptools._distutils.command.bdist (conditional)
missing module named typing_extensions.Unpack - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.util (conditional), setuptools._distutils.compilers.C.base (conditional), setuptools._distutils.cmd (conditional)
missing module named typing_extensions.TypeVarTuple - imported by setuptools._vendor.typing_extensions (top-level), setuptools._distutils.util (conditional), setuptools._distutils.compilers.C.base (conditional), setuptools._distutils.cmd (conditional)
missing module named '_typeshed.importlib' - imported by pkg_resources (conditional)
missing module named _typeshed - imported by werkzeug._internal (conditional), setuptools._distutils.dist (conditional), pkg_resources (conditional), setuptools.glob (conditional), setuptools.compat.py311 (conditional), click.testing (conditional)
missing module named jnius - imported by setuptools._vendor.platformdirs.android (delayed, conditional, optional)
missing module named android - imported by setuptools._vendor.platformdirs.android (delayed, conditional, optional)
missing module named importlib_resources - imported by setuptools._vendor.jaraco.text (optional), jsonschema_specifications._core (optional)
missing module named 'collections.abc' - imported by traceback (top-level), typing (top-level), inspect (top-level), logging (top-level), importlib.resources.readers (top-level), selectors (top-level), tracemalloc (top-level), http.client (top-level), werkzeug.wrappers.request (top-level), werkzeug.datastructures.accept (top-level), werkzeug.datastructures.structures (top-level), markupsafe (top-level), setuptools (top-level), setuptools._distutils.filelist (top-level), setuptools._distutils.util (top-level), setuptools._vendor.jaraco.functools (top-level), setuptools._vendor.more_itertools.more (top-level), setuptools._vendor.more_itertools.recipes (top-level), setuptools._distutils._modified (top-level), setuptools._distutils.compat (top-level), setuptools._distutils.spawn (top-level), setuptools._distutils.compilers.C.base (top-level), setuptools._distutils.fancy_getopt (top-level), setuptools._reqs (top-level), setuptools.discovery (top-level), setuptools.dist (top-level), setuptools._distutils.command.bdist (top-level), setuptools._distutils.core (top-level), setuptools._distutils.cmd (top-level), setuptools._distutils.dist (top-level), configparser (top-level), setuptools._distutils.extension (top-level), setuptools.config.setupcfg (top-level), setuptools.config.expand (top-level), setuptools.config.pyprojecttoml (top-level), setuptools.config._apply_pyprojecttoml (top-level), tomllib._parser (top-level), setuptools._vendor.tomli._parser (top-level), pkg_resources (top-level), setuptools._vendor.platformdirs.windows (conditional), setuptools.command.egg_info (top-level), setuptools._distutils.command.build (top-level), setuptools._distutils.command.sdist (top-level), setuptools.glob (top-level), setuptools.command._requirestxt (top-level), setuptools.command.bdist_wheel (top-level), wheel.cli.convert (top-level), wheel.cli.tags (top-level), setuptools._vendor.typing_extensions (top-level), werkzeug.datastructures.cache_control (top-level), werkzeug.datastructures.mixins (top-level), werkzeug.datastructures.auth (top-level), werkzeug.datastructures.csp (top-level), werkzeug.datastructures.etag (top-level), werkzeug.datastructures.file_storage (top-level), werkzeug.datastructures.headers (top-level), werkzeug.datastructures.range (top-level), werkzeug.middleware.shared_data (top-level), flask.app (top-level), click.core (top-level), click.types (top-level), click._compat (top-level), click._winconsole (top-level), click.exceptions (top-level), click.utils (top-level), click.shell_completion (top-level), click.formatting (top-level), click.parser (top-level), click._textwrap (top-level), click.termui (top-level), click._termui_impl (top-level), flask.cli (top-level), blinker.base (top-level), blinker._utilities (top-level), asyncio.base_events (top-level), asyncio.coroutines (top-level), flask.typing (top-level), flask.sessions (top-level), itsdangerous.serializer (top-level), itsdangerous.signer (top-level), itsdangerous.timed (top-level), click.testing (top-level), attr._compat (top-level), attr._make (top-level), referencing._core (top-level), referencing.typing (top-level), referencing.jsonschema (top-level), jsonschema._utils (top-level), jsonschema.exceptions (conditional), jsonschema._types (conditional), jsonschema.validators (top-level), jsonschema._typing (top-level), jsonschema.protocols (conditional), requests.compat (top-level), setuptools._distutils.command.build_ext (top-level), _pyrepl.types (top-level), _pyrepl.readline (top-level), setuptools._distutils.compilers.C.msvc (top-level)
excluded module named _frozen_importlib - imported by importlib (optional), importlib.abc (optional), zipimport (top-level)
missing module named vms_lib - imported by platform (delayed, optional)
missing module named 'java.lang' - imported by platform (delayed, optional)
missing module named java - imported by platform (delayed)
missing module named rpds.List - imported by rpds (top-level), referencing._core (top-level)
missing module named rpds.HashTrieSet - imported by rpds (top-level), referencing._core (top-level)
missing module named rpds.HashTrieMap - imported by rpds (top-level), referencing._core (top-level), jsonschema._types (top-level), jsonschema.validators (top-level)
missing module named annotationlib - imported by attr._compat (conditional)
missing module named simplejson - imported by requests.compat (conditional, optional)
missing module named dummy_threading - imported by requests.cookies (optional)
missing module named zstandard - imported by urllib3.util.request (optional), urllib3.response (optional)
missing module named compression - imported by urllib3.util.request (optional), urllib3.response (optional)
missing module named 'h2.events' - imported by urllib3.http2.connection (top-level)
missing module named 'h2.connection' - imported by urllib3.http2.connection (top-level)
missing module named h2 - imported by urllib3.http2.connection (top-level)
missing module named brotli - imported by urllib3.util.request (optional), urllib3.response (optional)
missing module named brotlicffi - imported by urllib3.util.request (optional), urllib3.response (optional)
missing module named socks - imported by urllib3.contrib.socks (optional)
missing module named cryptography - imported by werkzeug.serving (delayed, conditional, optional), flask.cli (delayed, conditional, optional), urllib3.contrib.pyopenssl (top-level), requests (conditional, optional)
missing module named 'OpenSSL.crypto' - imported by urllib3.contrib.pyopenssl (delayed, conditional)
missing module named 'cryptography.x509' - imported by werkzeug.serving (delayed, conditional, optional), urllib3.contrib.pyopenssl (delayed, optional)
missing module named OpenSSL - imported by urllib3.contrib.pyopenssl (top-level)
missing module named chardet - imported by requests (optional)
missing module named 'pyodide.ffi' - imported by urllib3.contrib.emscripten.fetch (delayed, optional)
missing module named pyodide - imported by urllib3.contrib.emscripten.fetch (top-level)
missing module named js - imported by urllib3.contrib.emscripten.fetch (top-level)
missing module named isoduration - imported by jsonschema._format (top-level)
missing module named uri_template - imported by jsonschema._format (top-level)
missing module named jsonpointer - imported by jsonschema._format (top-level)
missing module named webcolors - imported by jsonschema._format (top-level)
missing module named rfc3339_validator - imported by jsonschema._format (top-level)
missing module named rfc3987_syntax - imported by jsonschema._format (optional)
missing module named rfc3986_validator - imported by jsonschema._format (optional)
missing module named rfc3987 - imported by jsonschema._format (optional)
missing module named fqdn - imported by jsonschema._format (top-level)
missing module named 'watchdog.observers' - imported by werkzeug._reloader (delayed)
missing module named 'watchdog.events' - imported by werkzeug._reloader (delayed)
missing module named watchdog - imported by werkzeug._reloader (delayed)
missing module named 'cryptography.hazmat' - imported by werkzeug.serving (delayed, optional)
missing module named '_typeshed.wsgi' - imported by werkzeug.exceptions (conditional), werkzeug.http (conditional), werkzeug.wsgi (conditional), werkzeug.utils (conditional), werkzeug.wrappers.response (conditional), werkzeug.test (conditional), werkzeug.datastructures.headers (conditional), werkzeug.formparser (conditional), werkzeug.wrappers.request (conditional), werkzeug.serving (conditional), werkzeug.debug (conditional), werkzeug.middleware.shared_data (conditional), werkzeug.local (conditional), werkzeug.routing.exceptions (conditional), werkzeug.routing.map (conditional), flask.typing (conditional), flask.ctx (conditional), flask.testing (conditional), flask.cli (conditional), flask.app (conditional)
missing module named asgiref - imported by flask.app (delayed, optional)
missing module named dotenv - imported by flask.cli (delayed, optional)

File diff suppressed because it is too large Load Diff

View File

@ -55,9 +55,12 @@ class CacheManager:
def refresh_cache(self):
"""后台线程:定期刷新缓存"""
while self.running:
start_time = time.time()
try:
for plc in self.config["plcs"]:
plc_name = plc["name"]
refresh_interval = plc.get("refresh_interval", 0.5)
client = self.plc_manager.get_plc(plc_name)
# 检查PLC连接状态
@ -96,6 +99,23 @@ class CacheManager:
with self.lock:
self.cache[plc_name][name]["status"] = self.plc_connection_status[plc_name]
self.logger.warning(f"Error updating status for {plc_name}/{name}: {e}")
"""计算刷新一个PLC的时间"""
# 计算实际执行时间
execution_time = time.time() - start_time
#计算需要睡眠的时间确保总等于refresh_time
sleep_time = max(0, refresh_interval - execution_time)
time.sleep(sleep_time)
print(f"plc_name: {plc_name},"
f"Cache refresh completed.Execution time: {execution_time:.3f}s,"
f"Sleep time: {sleep_time:.3f}s,"
f"Total interval: {execution_time + sleep_time:.3f}s")
# 记录实际刷新间隔
self.logger.debug(f"plc_name: {plc_name},"
f"Cache refresh completed.Execution time: {execution_time:.3f}s,"
f"Sleep time: {sleep_time:.3f}s,"
f"Total interval: {execution_time + sleep_time:.3f}s")
time.sleep(self.refresh_interval)
except Exception as e:
@ -291,7 +311,6 @@ class CacheManager:
return False, f"PLC not connected (status: {plc_status})", plc_status, 0
try:
print(data)
success = client.write_db(area["db_number"], area["offset"] + offset, data)
if success:
# 更新缓存中的这部分数据
@ -333,9 +352,7 @@ class CacheManager:
return False, f"PLC not connected (status: {plc_status})", plc_status, 0
try:
print("data:", data)
for i, byte in enumerate(data):
print("i,byte:", i, byte)
byte_data = bytes([byte])
current_offset = offset + (i * 2)
byte_value = byte_data[0]
@ -345,7 +362,6 @@ class CacheManager:
set_int(value, 0, byte_value)
data = value
print(area["db_number"], current_offset, data)
success = client.batch_write_db(area["db_number"], current_offset, data)
if success:
# 更新缓存中的这部分数据
@ -388,11 +404,9 @@ class CacheManager:
try:
value = bytearray(offset + 1)
for bit, bit_value in enumerate(data):
print("i,byte:", bit, bit_value)
set_bool(value, offset, bit, bit_value)
data = value
print(area["db_number"], offset, data)
success = client.batch_write_db_bool(area["db_number"], offset, data)
if success:
# 更新缓存中的这部分数据

View File

@ -17,6 +17,11 @@ class ConfigValidator:
"ip": {"type": "string", "format": "ipv4"},
"rack": {"type": "integer", "minimum": 0},
"slot": {"type": "integer", "minimum": 0},
"refresh_interval": {
"type": "number",
"minimum": 0.01,
"default": 0.5
},
"areas": {
"type": "array",
"minItems": 1,
@ -53,9 +58,13 @@ class ConfigValidator:
"required": ["plcs"]
}
"""
@staticmethod:静态方法装饰器使validate_config不依赖于类的实例可以通过类直接调用
如ConfigValidator.validate_config(config)
"""
@staticmethod
def validate_config(config):
"""验证配置是否符合规范"""
"""使用JSONSchema验证配置是否符合规范"""
try:
# 添加IPv4格式验证
validator = Draft7Validator(

View File

@ -1,66 +0,0 @@
{
"plcs": [
{
"name": "PLC1",
"ip": "192.168.0.100",
"rack": 0,
"slot": 1,
"areas": [
{
"name": "DB100_Read",
"type": "read",
"db_number": 100,
"offset": 0,
"size": 4000,
"structure": [
{
"name": "temperature",
"type": "real",
"offset": 0
},
{
"name": "pressure",
"type": "int",
"offset": 4
},
{
"name": "status",
"type": "bool",
"offset": 6,
"bit": 0
}
]
},
{
"name": "DB100_Write",
"type": "write",
"db_number": 100,
"offset": 4000,
"size": 5000
},
{
"name": "DB202_Params",
"type": "read_write",
"db_number": 202,
"offset": 0,
"size": 2000
}
]
},
{
"name": "PLC2",
"ip": "192.168.0.101",
"rack": 0,
"slot": 1,
"areas": [
{
"name": "DB100_Read",
"type": "read",
"db_number": 100,
"offset": 0,
"size": 4000
}
]
}
]
}

View File

@ -1,66 +0,0 @@
{
"plcs": [
{
"name": "PLC1",
"ip": "192.168.0.100",
"rack": 0,
"slot": 1,
"areas": [
{
"name": "DB100_Read",
"type": "read",
"db_number": 100,
"offset": 0,
"size": 4000,
"structure": [
{
"name": "temperature",
"type": "real",
"offset": 0
},
{
"name": "pressure",
"type": "int",
"offset": 4
},
{
"name": "status",
"type": "bool",
"offset": 6,
"bit": 0
}
]
},
{
"name": "DB100_Write",
"type": "write",
"db_number": 100,
"offset": 4000,
"size": 5000
},
{
"name": "DB202_Params",
"type": "read_write",
"db_number": 202,
"offset": 0,
"size": 2000
}
]
},
{
"name": "PLC2",
"ip": "192.168.0.101",
"rack": 0,
"slot": 1,
"areas": [
{
"name": "DB100_Read",
"type": "read",
"db_number": 100,
"offset": 0,
"size": 4000
}
]
}
]
}

Binary file not shown.

View File

@ -1,28 +0,0 @@
Copyright 2010 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,92 +0,0 @@
Metadata-Version: 2.1
Name: MarkupSafe
Version: 3.0.2
Summary: Safely add untrusted strings to HTML/XML markup.
Maintainer-email: Pallets <contact@palletsprojects.com>
License: Copyright 2010 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/
Project-URL: Source, https://github.com/pallets/markupsafe/
Project-URL: Chat, https://discord.gg/pallets
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Text Processing :: Markup :: HTML
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE.txt
# MarkupSafe
MarkupSafe implements a text object that escapes characters so it is
safe to use in HTML and XML. Characters that have special meanings are
replaced so that they display as the actual characters. This mitigates
injection attacks, meaning untrusted user input can safely be displayed
on a page.
## Examples
```pycon
>>> from markupsafe import Markup, escape
>>> # escape replaces special characters and wraps in Markup
>>> escape("<script>alert(document.cookie);</script>")
Markup('&lt;script&gt;alert(document.cookie);&lt;/script&gt;')
>>> # wrap in Markup to mark text "safe" and prevent escaping
>>> Markup("<strong>Hello</strong>")
Markup('<strong>hello</strong>')
>>> escape(Markup("<strong>Hello</strong>"))
Markup('<strong>hello</strong>')
>>> # Markup is a str subclass
>>> # methods and operators escape their arguments
>>> template = Markup("Hello <em>{name}</em>")
>>> template.format(name='"World"')
Markup('Hello <em>&#34;World&#34;</em>')
```
## Donate
The Pallets organization develops and supports MarkupSafe and other
popular packages. In order to grow the community of contributors and
users, and allow the maintainers to devote more time to the projects,
[please donate today][].
[please donate today]: https://palletsprojects.com/donate

View File

@ -1,14 +0,0 @@
MarkupSafe-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
MarkupSafe-3.0.2.dist-info/LICENSE.txt,sha256=RjHsDbX9kKVH4zaBcmTGeYIUM4FG-KyUtKV_lu6MnsQ,1503
MarkupSafe-3.0.2.dist-info/METADATA,sha256=nhoabjupBG41j_JxPCJ3ylgrZ6Fx8oMCFbiLF9Kafqc,4067
MarkupSafe-3.0.2.dist-info/RECORD,,
MarkupSafe-3.0.2.dist-info/WHEEL,sha256=-v_yZ08fSknsoT62oIKG9wp1eCBV9_ao2rO4BeIReTY,101
MarkupSafe-3.0.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
markupsafe/__init__.py,sha256=pREerPwvinB62tNCMOwqxBS2YHV6R52Wcq1d-rB4Z5o,13609
markupsafe/__pycache__/__init__.cpython-313.pyc,,
markupsafe/__pycache__/_native.cpython-313.pyc,,
markupsafe/_native.py,sha256=2ptkJ40yCcp9kq3L1NqpgjfpZB-obniYKFFKUOkHh4Q,218
markupsafe/_speedups.c,sha256=SglUjn40ti9YgQAO--OgkSyv9tXq9vvaHyVhQows4Ok,4353
markupsafe/_speedups.cp313-win_amd64.pyd,sha256=7MA12j0aUiSeNpFy-98h_pPSqgCpLeRacgp3I-j00Yo,13312
markupsafe/_speedups.pyi,sha256=LSDmXYOefH4HVpAXuL8sl7AttLw0oXh1njVoVZp2wqQ,42
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0

View File

@ -1,5 +0,0 @@
Wheel-Version: 1.0
Generator: setuptools (75.2.0)
Root-Is-Purelib: false
Tag: cp313-cp313-win_amd64

View File

@ -1 +0,0 @@
markupsafe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1 +0,0 @@
pip

View File

@ -1,232 +0,0 @@
Metadata-Version: 2.4
Name: attrs
Version: 25.3.0
Summary: Classes Without Boilerplate
Project-URL: Documentation, https://www.attrs.org/
Project-URL: Changelog, https://www.attrs.org/en/stable/changelog.html
Project-URL: GitHub, https://github.com/python-attrs/attrs
Project-URL: Funding, https://github.com/sponsors/hynek
Project-URL: Tidelift, https://tidelift.com/subscription/pkg/pypi-attrs?utm_source=pypi-attrs&utm_medium=pypi
Author-email: Hynek Schlawack <hs@ox.cx>
License-Expression: MIT
License-File: LICENSE
Keywords: attribute,boilerplate,class
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Typing :: Typed
Requires-Python: >=3.8
Provides-Extra: benchmark
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'benchmark'
Requires-Dist: hypothesis; extra == 'benchmark'
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'benchmark'
Requires-Dist: pympler; extra == 'benchmark'
Requires-Dist: pytest-codspeed; extra == 'benchmark'
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'benchmark'
Requires-Dist: pytest-xdist[psutil]; extra == 'benchmark'
Requires-Dist: pytest>=4.3.0; extra == 'benchmark'
Provides-Extra: cov
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'cov'
Requires-Dist: coverage[toml]>=5.3; extra == 'cov'
Requires-Dist: hypothesis; extra == 'cov'
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'cov'
Requires-Dist: pympler; extra == 'cov'
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'cov'
Requires-Dist: pytest-xdist[psutil]; extra == 'cov'
Requires-Dist: pytest>=4.3.0; extra == 'cov'
Provides-Extra: dev
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'dev'
Requires-Dist: hypothesis; extra == 'dev'
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'dev'
Requires-Dist: pre-commit-uv; extra == 'dev'
Requires-Dist: pympler; extra == 'dev'
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'dev'
Requires-Dist: pytest-xdist[psutil]; extra == 'dev'
Requires-Dist: pytest>=4.3.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: cogapp; extra == 'docs'
Requires-Dist: furo; extra == 'docs'
Requires-Dist: myst-parser; extra == 'docs'
Requires-Dist: sphinx; extra == 'docs'
Requires-Dist: sphinx-notfound-page; extra == 'docs'
Requires-Dist: sphinxcontrib-towncrier; extra == 'docs'
Requires-Dist: towncrier; extra == 'docs'
Provides-Extra: tests
Requires-Dist: cloudpickle; (platform_python_implementation == 'CPython') and extra == 'tests'
Requires-Dist: hypothesis; extra == 'tests'
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests'
Requires-Dist: pympler; extra == 'tests'
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests'
Requires-Dist: pytest-xdist[psutil]; extra == 'tests'
Requires-Dist: pytest>=4.3.0; extra == 'tests'
Provides-Extra: tests-mypy
Requires-Dist: mypy>=1.11.1; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests-mypy'
Requires-Dist: pytest-mypy-plugins; (platform_python_implementation == 'CPython' and python_version >= '3.10') and extra == 'tests-mypy'
Description-Content-Type: text/markdown
<p align="center">
<a href="https://www.attrs.org/">
<img src="https://raw.githubusercontent.com/python-attrs/attrs/main/docs/_static/attrs_logo.svg" width="35%" alt="attrs" />
</a>
</p>
*attrs* is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka [dunder methods](https://www.attrs.org/en/latest/glossary.html#term-dunder-methods)).
[Trusted by NASA](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile#list-of-qualifying-repositories-for-mars-2020-helicopter-contributor-achievement) for Mars missions since 2020!
Its main goal is to help you to write **concise** and **correct** software without slowing down your code.
## Sponsors
*attrs* would not be possible without our [amazing sponsors](https://github.com/sponsors/hynek).
Especially those generously supporting us at the *The Organization* tier and higher:
<!-- sponsor-break-begin -->
<p align="center">
<!-- [[[cog
import pathlib, tomllib
for sponsor in tomllib.loads(pathlib.Path("pyproject.toml").read_text())["tool"]["sponcon"]["sponsors"]:
print(f'<a href="{sponsor["url"]}"><img title="{sponsor["title"]}" src="https://www.attrs.org/en/25.3.0/_static/sponsors/{sponsor["img"]}" width="190" /></a>')
]]] -->
<a href="https://www.variomedia.de/"><img title="Variomedia AG" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Variomedia.svg" width="190" /></a>
<a href="https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek"><img title="Tidelift" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Tidelift.svg" width="190" /></a>
<a href="https://klaviyo.com/"><img title="Klaviyo" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Klaviyo.svg" width="190" /></a>
<a href="https://privacy-solutions.org/"><img title="Privacy Solutions" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Privacy-Solutions.svg" width="190" /></a>
<a href="https://www.emsys-renewables.com/"><img title="emsys renewables" src="https://www.attrs.org/en/25.3.0/_static/sponsors/emsys-renewables.svg" width="190" /></a>
<a href="https://filepreviews.io/"><img title="FilePreviews" src="https://www.attrs.org/en/25.3.0/_static/sponsors/FilePreviews.svg" width="190" /></a>
<a href="https://polar.sh/"><img title="Polar" src="https://www.attrs.org/en/25.3.0/_static/sponsors/Polar.svg" width="190" /></a>
<!-- [[[end]]] -->
</p>
<!-- sponsor-break-end -->
<p align="center">
<strong>Please consider <a href="https://github.com/sponsors/hynek">joining them</a> to help make <em>attrs</em>s maintenance more sustainable!</strong>
</p>
<!-- teaser-end -->
## Example
*attrs* gives you a class decorator and a way to declaratively define the attributes on that class:
<!-- code-begin -->
```pycon
>>> from attrs import asdict, define, make_class, Factory
>>> @define
... class SomeClass:
... a_number: int = 42
... list_of_numbers: list[int] = Factory(list)
...
... def hard_math(self, another_number):
... return self.a_number + sum(self.list_of_numbers) * another_number
>>> sc = SomeClass(1, [1, 2, 3])
>>> sc
SomeClass(a_number=1, list_of_numbers=[1, 2, 3])
>>> sc.hard_math(3)
19
>>> sc == SomeClass(1, [1, 2, 3])
True
>>> sc != SomeClass(2, [3, 2, 1])
True
>>> asdict(sc)
{'a_number': 1, 'list_of_numbers': [1, 2, 3]}
>>> SomeClass()
SomeClass(a_number=42, list_of_numbers=[])
>>> C = make_class("C", ["a", "b"])
>>> C("foo", "bar")
C(a='foo', b='bar')
```
After *declaring* your attributes, *attrs* gives you:
- a concise and explicit overview of the class's attributes,
- a nice human-readable `__repr__`,
- equality-checking methods,
- an initializer,
- and much more,
*without* writing dull boilerplate code again and again and *without* runtime performance penalties.
---
This example uses *attrs*'s modern APIs that have been introduced in version 20.1.0, and the *attrs* package import name that has been added in version 21.3.0.
The classic APIs (`@attr.s`, `attr.ib`, plus their serious-business aliases) and the `attr` package import name will remain **indefinitely**.
Check out [*On The Core API Names*](https://www.attrs.org/en/latest/names.html) for an in-depth explanation!
### Hate Type Annotations!?
No problem!
Types are entirely **optional** with *attrs*.
Simply assign `attrs.field()` to the attributes instead of annotating them with types:
```python
from attrs import define, field
@define
class SomeClass:
a_number = field(default=42)
list_of_numbers = field(factory=list)
```
## Data Classes
On the tin, *attrs* might remind you of `dataclasses` (and indeed, `dataclasses` [are a descendant](https://hynek.me/articles/import-attrs/) of *attrs*).
In practice it does a lot more and is more flexible.
For instance, it allows you to define [special handling of NumPy arrays for equality checks](https://www.attrs.org/en/stable/comparison.html#customization), allows more ways to [plug into the initialization process](https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization), has a replacement for `__init_subclass__`, and allows for stepping through the generated methods using a debugger.
For more details, please refer to our [comparison page](https://www.attrs.org/en/stable/why.html#data-classes), but generally speaking, we are more likely to commit crimes against nature to make things work that one would expect to work, but that are quite complicated in practice.
## Project Information
- [**Changelog**](https://www.attrs.org/en/stable/changelog.html)
- [**Documentation**](https://www.attrs.org/)
- [**PyPI**](https://pypi.org/project/attrs/)
- [**Source Code**](https://github.com/python-attrs/attrs)
- [**Contributing**](https://github.com/python-attrs/attrs/blob/main/.github/CONTRIBUTING.md)
- [**Third-party Extensions**](https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs)
- **Get Help**: use the `python-attrs` tag on [Stack Overflow](https://stackoverflow.com/questions/tagged/python-attrs)
### *attrs* for Enterprise
Available as part of the [Tidelift Subscription](https://tidelift.com/?utm_source=lifter&utm_medium=referral&utm_campaign=hynek).
The maintainers of *attrs* and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.
Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.
## Release Information
### Changes
- Restore support for generator-based `field_transformer`s.
[#1417](https://github.com/python-attrs/attrs/issues/1417)
---
[Full changelog →](https://www.attrs.org/en/stable/changelog.html)

View File

@ -1,55 +0,0 @@
attr/__init__.py,sha256=fOYIvt1eGSqQre4uCS3sJWKZ0mwAuC8UD6qba5OS9_U,2057
attr/__init__.pyi,sha256=QIXnnHPoucmDWkbpNsWTP-cgJ1bn8le7DjyRa_wYdew,11281
attr/__pycache__/__init__.cpython-313.pyc,,
attr/__pycache__/_cmp.cpython-313.pyc,,
attr/__pycache__/_compat.cpython-313.pyc,,
attr/__pycache__/_config.cpython-313.pyc,,
attr/__pycache__/_funcs.cpython-313.pyc,,
attr/__pycache__/_make.cpython-313.pyc,,
attr/__pycache__/_next_gen.cpython-313.pyc,,
attr/__pycache__/_version_info.cpython-313.pyc,,
attr/__pycache__/converters.cpython-313.pyc,,
attr/__pycache__/exceptions.cpython-313.pyc,,
attr/__pycache__/filters.cpython-313.pyc,,
attr/__pycache__/setters.cpython-313.pyc,,
attr/__pycache__/validators.cpython-313.pyc,,
attr/_cmp.py,sha256=3Nn1TjxllUYiX_nJoVnEkXoDk0hM1DYKj5DE7GZe4i0,4117
attr/_cmp.pyi,sha256=U-_RU_UZOyPUEQzXE6RMYQQcjkZRY25wTH99sN0s7MM,368
attr/_compat.py,sha256=4hlXbWhdDjQCDK6FKF1EgnZ3POiHgtpp54qE0nxaGHg,2704
attr/_config.py,sha256=dGq3xR6fgZEF6UBt_L0T-eUHIB4i43kRmH0P28sJVw8,843
attr/_funcs.py,sha256=5-tUKJtp3h5El55EcDl6GWXFp68fT8D8U7uCRN6497I,15854
attr/_make.py,sha256=lBUPPmxiA1BeHzB6OlHoCEh--tVvM1ozXO8eXOa6g4c,96664
attr/_next_gen.py,sha256=7FRkbtl_N017SuBhf_Vw3mw2c2pGZhtCGOzadgz7tp4,24395
attr/_typing_compat.pyi,sha256=XDP54TUn-ZKhD62TOQebmzrwFyomhUCoGRpclb6alRA,469
attr/_version_info.py,sha256=exSqb3b5E-fMSsgZAlEw9XcLpEgobPORCZpcaEglAM4,2121
attr/_version_info.pyi,sha256=x_M3L3WuB7r_ULXAWjx959udKQ4HLB8l-hsc1FDGNvk,209
attr/converters.py,sha256=GlDeOzPeTFgeBBLbj9G57Ez5lAk68uhSALRYJ_exe84,3861
attr/converters.pyi,sha256=orU2bff-VjQa2kMDyvnMQV73oJT2WRyQuw4ZR1ym1bE,643
attr/exceptions.py,sha256=HRFq4iybmv7-DcZwyjl6M1euM2YeJVK_hFxuaBGAngI,1977
attr/exceptions.pyi,sha256=zZq8bCUnKAy9mDtBEw42ZhPhAUIHoTKedDQInJD883M,539
attr/filters.py,sha256=ZBiKWLp3R0LfCZsq7X11pn9WX8NslS2wXM4jsnLOGc8,1795
attr/filters.pyi,sha256=3J5BG-dTxltBk1_-RuNRUHrv2qu1v8v4aDNAQ7_mifA,208
attr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
attr/setters.py,sha256=5-dcT63GQK35ONEzSgfXCkbB7pPkaR-qv15mm4PVSzQ,1617
attr/setters.pyi,sha256=NnVkaFU1BB4JB8E4JuXyrzTUgvtMpj8p3wBdJY7uix4,584
attr/validators.py,sha256=WaB1HLAHHqRHWsrv_K9H-sJ7ESil3H3Cmv2d8TtVZx4,20046
attr/validators.pyi,sha256=s2WhKPqskxbsckJfKk8zOuuB088GfgpyxcCYSNFLqNU,2603
attrs-25.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
attrs-25.3.0.dist-info/METADATA,sha256=W38cREj7s1wqNf1fg4hVwZmL1xh0AdSp4IhtTMROinw,10993
attrs-25.3.0.dist-info/RECORD,,
attrs-25.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
attrs-25.3.0.dist-info/licenses/LICENSE,sha256=iCEVyV38KvHutnFPjsbVy8q_Znyv-HKfQkINpj9xTp8,1109
attrs/__init__.py,sha256=qeQJZ4O08yczSn840v9bYOaZyRE81WsVi-QCrY3krCU,1107
attrs/__init__.pyi,sha256=nZmInocjM7tHV4AQw0vxO_fo6oJjL_PonlV9zKKW8DY,7931
attrs/__pycache__/__init__.cpython-313.pyc,,
attrs/__pycache__/converters.cpython-313.pyc,,
attrs/__pycache__/exceptions.cpython-313.pyc,,
attrs/__pycache__/filters.cpython-313.pyc,,
attrs/__pycache__/setters.cpython-313.pyc,,
attrs/__pycache__/validators.cpython-313.pyc,,
attrs/converters.py,sha256=8kQljrVwfSTRu8INwEk8SI0eGrzmWftsT7rM0EqyohM,76
attrs/exceptions.py,sha256=ACCCmg19-vDFaDPY9vFl199SPXCQMN_bENs4DALjzms,76
attrs/filters.py,sha256=VOUMZug9uEU6dUuA0dF1jInUK0PL3fLgP0VBS5d-CDE,73
attrs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
attrs/setters.py,sha256=eL1YidYQV3T2h9_SYIZSZR1FAcHGb1TuCTy0E0Lv2SU,73
attrs/validators.py,sha256=xcy6wD5TtTkdCG1f4XWbocPSO0faBjk5IfVJfP6SUj0,76

View File

@ -1,4 +0,0 @@
Wheel-Version: 1.0
Generator: hatchling 1.27.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2015 Hynek Schlawack and the attrs contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
pip

View File

@ -1,82 +0,0 @@
Metadata-Version: 2.4
Name: click
Version: 8.2.1
Summary: Composable command line interface toolkit
Maintainer-email: Pallets <contact@palletsprojects.com>
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-Expression: BSD-3-Clause
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Typing :: Typed
License-File: LICENSE.txt
Requires-Dist: colorama; platform_system == 'Windows'
Project-URL: Changes, https://click.palletsprojects.com/page/changes/
Project-URL: Chat, https://discord.gg/pallets
Project-URL: Documentation, https://click.palletsprojects.com/
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Source, https://github.com/pallets/click/
# $ click_
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to
implement an intended CLI API.
Click in three points:
- Arbitrary nesting of commands
- Automatic help page generation
- Supports lazy loading of subcommands at runtime
## A Simple Example
```python
import click
@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name", help="The person to greet.")
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for _ in range(count):
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
hello()
```
```
$ python hello.py --count=3
Your name: Click
Hello, Click!
Hello, Click!
Hello, Click!
```
## Donate
The Pallets organization develops and supports Click and other popular
packages. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, [please
donate today][].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/

View File

@ -1,38 +0,0 @@
click-8.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
click-8.2.1.dist-info/METADATA,sha256=dI1MbhHTLoKD2tNCCGnx9rK2gok23HDNylFeLKdLSik,2471
click-8.2.1.dist-info/RECORD,,
click-8.2.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
click-8.2.1.dist-info/licenses/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
click/__init__.py,sha256=6YyS1aeyknZ0LYweWozNZy0A9nZ_11wmYIhv3cbQrYo,4473
click/__pycache__/__init__.cpython-313.pyc,,
click/__pycache__/_compat.cpython-313.pyc,,
click/__pycache__/_termui_impl.cpython-313.pyc,,
click/__pycache__/_textwrap.cpython-313.pyc,,
click/__pycache__/_winconsole.cpython-313.pyc,,
click/__pycache__/core.cpython-313.pyc,,
click/__pycache__/decorators.cpython-313.pyc,,
click/__pycache__/exceptions.cpython-313.pyc,,
click/__pycache__/formatting.cpython-313.pyc,,
click/__pycache__/globals.cpython-313.pyc,,
click/__pycache__/parser.cpython-313.pyc,,
click/__pycache__/shell_completion.cpython-313.pyc,,
click/__pycache__/termui.cpython-313.pyc,,
click/__pycache__/testing.cpython-313.pyc,,
click/__pycache__/types.cpython-313.pyc,,
click/__pycache__/utils.cpython-313.pyc,,
click/_compat.py,sha256=v3xBZkFbvA1BXPRkFfBJc6-pIwPI7345m-kQEnpVAs4,18693
click/_termui_impl.py,sha256=ASXhLi9IQIc0Js9KQSS-3-SLZcPet3VqysBf9WgbbpI,26712
click/_textwrap.py,sha256=BOae0RQ6vg3FkNgSJyOoGzG1meGMxJ_ukWVZKx_v-0o,1400
click/_winconsole.py,sha256=_vxUuUaxwBhoR0vUWCNuHY8VUefiMdCIyU2SXPqoF-A,8465
click/core.py,sha256=gUhpNS9cFBGdEXXdisGVG-eRvGf49RTyFagxulqwdFw,117343
click/decorators.py,sha256=5P7abhJtAQYp_KHgjUvhMv464ERwOzrv2enNknlwHyQ,18461
click/exceptions.py,sha256=1rdtXgHJ1b3OjGkN-UpXB9t_HCBihJvh_DtpmLmwn9s,9891
click/formatting.py,sha256=Bhqx4QXdKQ9W4WKknIwj5KPKFmtduGOuGq1yw_THLZ8,9726
click/globals.py,sha256=gM-Nh6A4M0HB_SgkaF5M4ncGGMDHc_flHXu9_oh4GEU,1923
click/parser.py,sha256=nU1Ah2p11q29ul1vNdU9swPo_PUuKrxU6YXToi71q1c,18979
click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
click/shell_completion.py,sha256=CQSGdjgun4ORbOZrXP0CVhEtPx4knsufOkRsDiK64cM,19857
click/termui.py,sha256=vAYrKC2a7f_NfEIhAThEVYfa__ib5XQbTSCGtJlABRA,30847
click/testing.py,sha256=2eLdAaCJCGToP5Tw-XN8JjrDb3wbJIfARxg3d0crW5M,18702
click/types.py,sha256=KBTRxN28cR1VZ5mb9iJX98MQSw_p9SGzljqfEI8z5Tw,38389
click/utils.py,sha256=b1Mm-usEDBHtEwcPltPIn3zSK4nw2KTp5GC7_oSTlLo,20245

View File

@ -1,4 +0,0 @@
Wheel-Version: 1.0
Generator: flit 3.12.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@ -1,28 +0,0 @@
Copyright 2014 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Binary file not shown.

View File

@ -1 +0,0 @@
pip

View File

@ -1,89 +0,0 @@
Metadata-Version: 2.4
Name: Flask
Version: 3.1.1
Summary: A simple framework for building complex web applications.
Maintainer-email: Pallets <contact@palletsprojects.com>
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-Expression: BSD-3-Clause
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Flask
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Typing :: Typed
License-File: LICENSE.txt
Requires-Dist: blinker>=1.9.0
Requires-Dist: click>=8.1.3
Requires-Dist: importlib-metadata>=3.6.0; python_version < '3.10'
Requires-Dist: itsdangerous>=2.2.0
Requires-Dist: jinja2>=3.1.2
Requires-Dist: markupsafe>=2.1.1
Requires-Dist: werkzeug>=3.1.0
Requires-Dist: asgiref>=3.2 ; extra == "async"
Requires-Dist: python-dotenv ; extra == "dotenv"
Project-URL: Changes, https://flask.palletsprojects.com/page/changes/
Project-URL: Chat, https://discord.gg/pallets
Project-URL: Documentation, https://flask.palletsprojects.com/
Project-URL: Donate, https://palletsprojects.com/donate
Project-URL: Source, https://github.com/pallets/flask/
Provides-Extra: async
Provides-Extra: dotenv
# Flask
Flask is a lightweight [WSGI] web application framework. It is designed
to make getting started quick and easy, with the ability to scale up to
complex applications. It began as a simple wrapper around [Werkzeug]
and [Jinja], and has become one of the most popular Python web
application frameworks.
Flask offers suggestions, but doesn't enforce any dependencies or
project layout. It is up to the developer to choose the tools and
libraries they want to use. There are many extensions provided by the
community that make adding new functionality easy.
[WSGI]: https://wsgi.readthedocs.io/
[Werkzeug]: https://werkzeug.palletsprojects.com/
[Jinja]: https://jinja.palletsprojects.com/
## A Simple Example
```python
# save this as app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello, World!"
```
```
$ flask run
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
## Donate
The Pallets organization develops and supports Flask and the libraries
it uses. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, [please
donate today].
[please donate today]: https://palletsprojects.com/donate
## Contributing
See our [detailed contributing documentation][contrib] for many ways to
contribute, including reporting issues, requesting features, asking or answering
questions, and making PRs.
[contrib]: https://palletsprojects.com/contributing/

View File

@ -1,58 +0,0 @@
../../Scripts/flask.exe,sha256=2xOiYnBmA4B2uhoEaWZCxp6GPo3UkaN1kZLi4kTrduU,108388
flask-3.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
flask-3.1.1.dist-info/METADATA,sha256=EsnOyVfBXjw1BkGn-9lrI5mcv1NwYyB4_CfdW2FSDZQ,3014
flask-3.1.1.dist-info/RECORD,,
flask-3.1.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
flask-3.1.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
flask-3.1.1.dist-info/entry_points.txt,sha256=bBP7hTOS5fz9zLtC7sPofBZAlMkEvBxu7KqS6l5lvc4,40
flask-3.1.1.dist-info/licenses/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
flask/__init__.py,sha256=mHvJN9Swtl1RDtjCqCIYyIniK_SZ_l_hqUynOzgpJ9o,2701
flask/__main__.py,sha256=bYt9eEaoRQWdejEHFD8REx9jxVEdZptECFsV7F49Ink,30
flask/__pycache__/__init__.cpython-313.pyc,,
flask/__pycache__/__main__.cpython-313.pyc,,
flask/__pycache__/app.cpython-313.pyc,,
flask/__pycache__/blueprints.cpython-313.pyc,,
flask/__pycache__/cli.cpython-313.pyc,,
flask/__pycache__/config.cpython-313.pyc,,
flask/__pycache__/ctx.cpython-313.pyc,,
flask/__pycache__/debughelpers.cpython-313.pyc,,
flask/__pycache__/globals.cpython-313.pyc,,
flask/__pycache__/helpers.cpython-313.pyc,,
flask/__pycache__/logging.cpython-313.pyc,,
flask/__pycache__/sessions.cpython-313.pyc,,
flask/__pycache__/signals.cpython-313.pyc,,
flask/__pycache__/templating.cpython-313.pyc,,
flask/__pycache__/testing.cpython-313.pyc,,
flask/__pycache__/typing.cpython-313.pyc,,
flask/__pycache__/views.cpython-313.pyc,,
flask/__pycache__/wrappers.cpython-313.pyc,,
flask/app.py,sha256=XGqgFRsLgBhzIoB2HSftoMTIM3hjDiH6rdV7c3g3IKc,61744
flask/blueprints.py,sha256=p5QE2lY18GItbdr_RKRpZ8Do17g0PvQGIgZkSUDhX2k,4541
flask/cli.py,sha256=Pfh72-BxlvoH0QHCDOc1HvXG7Kq5Xetf3zzNz2kNSHk,37184
flask/config.py,sha256=PiqF0DPam6HW0FH4CH1hpXTBe30NSzjPEOwrz1b6kt0,13219
flask/ctx.py,sha256=4atDhJJ_cpV1VMq4qsfU4E_61M1oN93jlS2H9gjrl58,15120
flask/debughelpers.py,sha256=PGIDhStW_efRjpaa3zHIpo-htStJOR41Ip3OJWPYBwo,6080
flask/globals.py,sha256=XdQZmStBmPIs8t93tjx6pO7Bm3gobAaONWkFcUHaGas,1713
flask/helpers.py,sha256=7njmzkFJvrPSQudsgONsgQzaGrGppeBINevKgWescPk,23521
flask/json/__init__.py,sha256=hLNR898paqoefdeAhraa5wyJy-bmRB2k2dV4EgVy2Z8,5602
flask/json/__pycache__/__init__.cpython-313.pyc,,
flask/json/__pycache__/provider.cpython-313.pyc,,
flask/json/__pycache__/tag.cpython-313.pyc,,
flask/json/provider.py,sha256=5imEzY5HjV2HoUVrQbJLqXCzMNpZXfD0Y1XqdLV2XBA,7672
flask/json/tag.py,sha256=DhaNwuIOhdt2R74oOC9Y4Z8ZprxFYiRb5dUP5byyINw,9281
flask/logging.py,sha256=8sM3WMTubi1cBb2c_lPkWpN0J8dMAqrgKRYLLi1dCVI,2377
flask/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
flask/sansio/README.md,sha256=-0X1tECnilmz1cogx-YhNw5d7guK7GKrq_DEV2OzlU0,228
flask/sansio/__pycache__/app.cpython-313.pyc,,
flask/sansio/__pycache__/blueprints.cpython-313.pyc,,
flask/sansio/__pycache__/scaffold.cpython-313.pyc,,
flask/sansio/app.py,sha256=Wj9NVGtiR1jvkZ9gSFd91usUlM8H0g06aPVz2sMh4bw,38116
flask/sansio/blueprints.py,sha256=Tqe-7EkZ-tbWchm8iDoCfD848f0_3nLv6NNjeIPvHwM,24637
flask/sansio/scaffold.py,sha256=q6wM4Y4aYMGGN_Litsj3PYKpBS3Zvut0xhDmpBEHFdo,30387
flask/sessions.py,sha256=ED_OV3Jl1emsy7Zntb7aFWxyoynt-PzNY0eFUH-Syo0,15495
flask/signals.py,sha256=V7lMUww7CqgJ2ThUBn1PiatZtQanOyt7OZpu2GZI-34,750
flask/templating.py,sha256=2TcXLT85Asflm2W9WOSFxKCmYn5e49w_Jkg9-NaaJWo,7537
flask/testing.py,sha256=JT9fi_-_qsAXIpC1NSWcp1VrO-QSXgmdq95extfCwEw,10136
flask/typing.py,sha256=L-L5t2jKgS0aOmVhioQ_ylqcgiVFnA6yxO-RLNhq-GU,3293
flask/views.py,sha256=xzJx6oJqGElThtEghZN7ZQGMw5TDFyuRxUkecwRuAoA,6962
flask/wrappers.py,sha256=jUkv4mVek2Iq4hwxd4RvqrIMb69Bv0PElDgWLmd5ORo,9406

View File

@ -1,4 +0,0 @@
Wheel-Version: 1.0
Generator: flit 3.12.0
Root-Is-Purelib: true
Tag: py3-none-any

View File

@ -1,3 +0,0 @@
[console_scripts]
flask=flask.cli:main

Some files were not shown because too many files have changed in this diff Show More