From 683508214ef13abb6e81e1ed3508491b79da16b9 Mon Sep 17 00:00:00 2001 From: geerardferrer Date: Mon, 29 Dec 2025 17:16:53 +0100 Subject: [PATCH 1/8] Refactor configuration and enhance API functionality - Updated MongoDB configuration in .env and settings.py for consistency. - Improved .gitignore to include additional patterns. - Added new API endpoints for refreshing student maps and debugging. - Enhanced logging for better traceability during refresh operations. - Cleaned up orphan collections and documents in MongoDB. - Corrected factor names in various metrics properties files for clarity. - Removed obsolete metric files to streamline the project structure. - Adjusted Dockerfile to optimize gunicorn settings. --- .env | 5 +- .gitignore | 3 +- API_calls/StudentDatafromLDRESTAPI.py | 2 + .../acceptance_criteria_check.properties | 2 +- .../AMEP/metrics/assignedtasks.properties | 2 +- .../metrics/closed_tasks_with_AE.properties | 2 +- .../AMEP/metrics/closedtasks.properties | 2 +- .../AMEP/metrics/pattern_check.properties | 2 +- .../AMEP/metrics/tasks_with_EE.properties | 2 +- .../acceptance_criteria_check.properties | 2 +- .../DEFAULT/metrics/assignedtasks.properties | 2 +- .../metrics/closed_tasks_with_AE.properties | 2 +- .../DEFAULT/metrics/closedtasks.properties | 2 +- .../DEFAULT/metrics/pattern_check.properties | 2 +- .../DEFAULT/metrics/tasks_with_EE.properties | 2 +- .../DEFAULT/metrics/test copy.properties | 22 ----- .../DEFAULT/metrics/test copy.query | 27 ------ .../DEFAULT/metrics/test.properties | 22 ----- QUALITY_MODELS/DEFAULT/metrics/test.query | 27 ------ app.py | 84 +++++++++++++++++-- config/settings.py | 4 +- dockerfile | 2 +- ld_refresh.py | 77 +++++++++++++++-- 23 files changed, 172 insertions(+), 127 deletions(-) delete mode 100644 QUALITY_MODELS/DEFAULT/metrics/test copy.properties delete mode 100644 QUALITY_MODELS/DEFAULT/metrics/test copy.query delete mode 100644 QUALITY_MODELS/DEFAULT/metrics/test.properties delete mode 100644 QUALITY_MODELS/DEFAULT/metrics/test.query diff --git a/.env b/.env index ec9a647..6dcc5e5 100644 --- a/.env +++ b/.env @@ -1,11 +1,12 @@ MONGO_HOST=mongodb MONGO_PORT=27017 +MONGO_DB=mongo MONGO_USER=admin -MONGO_PASS=IHxq1V8j3hwH +MONGO_PASS=3LnS985q7tR9 #IHxq1V8j3hwH MONGO_AUTHSRC=admin # This is the URL of the GESSI dashboard API. -BASE_GESSI_URL =http://gessi-dashboard.essi.upc.edu:8888/api +BASE_GESSI_URL =http://host.docker.internal:8888/api #http://gessi-dashboard.essi.upc.edu:8888/api QUALITY_MODELS_DIR = ./QUALITY_MODELS diff --git a/.gitignore b/.gitignore index 1bf159f..5d6cf5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ # .gitignore .env -/menv/ \ No newline at end of file +/menv/ +*.pyc \ No newline at end of file diff --git a/API_calls/StudentDatafromLDRESTAPI.py b/API_calls/StudentDatafromLDRESTAPI.py index 1b26741..44e4ed3 100644 --- a/API_calls/StudentDatafromLDRESTAPI.py +++ b/API_calls/StudentDatafromLDRESTAPI.py @@ -81,11 +81,13 @@ def build_team_students_map() -> dict: # ADDED MANUALLY TO MAKE THE TESTS WORK, REMOVE LATER + ''' team_students_map["LD_Test_Project"] = { "GITHUB": ["PabloGomezNa", "PepitoGomezNa", "charlie"], "TAIGA": ["pgomezn", "pablogz5", "Charlie55"], "EXCEL": ["Pablo", "Marc", "Charlie"] } + ''' return team_students_map diff --git a/QUALITY_MODELS/AMEP/metrics/acceptance_criteria_check.properties b/QUALITY_MODELS/AMEP/metrics/acceptance_criteria_check.properties index f1673d3..ee2453d 100644 --- a/QUALITY_MODELS/AMEP/metrics/acceptance_criteria_check.properties +++ b/QUALITY_MODELS/AMEP/metrics/acceptance_criteria_check.properties @@ -1,7 +1,7 @@ # metric props name=Acceptance Criteria Application description=Percentage of user stories with acceptance criteria with respect to the total number of user stories in this sprint -factors=userstoriesdefinitionquality +factors=userstoriesdefinition_quality weights=1.0 diff --git a/QUALITY_MODELS/AMEP/metrics/assignedtasks.properties b/QUALITY_MODELS/AMEP/metrics/assignedtasks.properties index 22cc749..b99ffb6 100644 --- a/QUALITY_MODELS/AMEP/metrics/assignedtasks.properties +++ b/QUALITY_MODELS/AMEP/metrics/assignedtasks.properties @@ -1,7 +1,7 @@ # metric props name=tasks description=Percentage of tasks made by a student with respect to the total number of tasks in the project -factors=taskscontribution +factors=taskcontribution weights=1.0 diff --git a/QUALITY_MODELS/AMEP/metrics/closed_tasks_with_AE.properties b/QUALITY_MODELS/AMEP/metrics/closed_tasks_with_AE.properties index 1f06c1c..e361c86 100644 --- a/QUALITY_MODELS/AMEP/metrics/closed_tasks_with_AE.properties +++ b/QUALITY_MODELS/AMEP/metrics/closed_tasks_with_AE.properties @@ -1,7 +1,7 @@ # metric props name=Closed Tasks with Actual Effort Information description=Percentage of closed tasks with actual effort information added with respect to the total number of closed tasks in this sprint -factors=taskseffortinformation +factors=taskeffortinformation weights=1.0 diff --git a/QUALITY_MODELS/AMEP/metrics/closedtasks.properties b/QUALITY_MODELS/AMEP/metrics/closedtasks.properties index 7712805..63d3bc2 100644 --- a/QUALITY_MODELS/AMEP/metrics/closedtasks.properties +++ b/QUALITY_MODELS/AMEP/metrics/closedtasks.properties @@ -1,7 +1,7 @@ # metric props name=closed tasks description=Percentage of closed tasks made by a student with respect to the total number of tasks assigned to student -factors=fulfillmentoftasks +factors=fullfillmentoftasks weights=1.0 diff --git a/QUALITY_MODELS/AMEP/metrics/pattern_check.properties b/QUALITY_MODELS/AMEP/metrics/pattern_check.properties index 1fd93bb..15c175b 100644 --- a/QUALITY_MODELS/AMEP/metrics/pattern_check.properties +++ b/QUALITY_MODELS/AMEP/metrics/pattern_check.properties @@ -1,7 +1,7 @@ # metric props name=Use of User Story pattern description=Percentage of user stories with the pattern (AS - I WANT - SO THAT - ) with respect to the total number of user stories in this sprint -factors=userstoriesdefinitionquality +factors=userstoriesdefinition_quality weights=1.0 diff --git a/QUALITY_MODELS/AMEP/metrics/tasks_with_EE.properties b/QUALITY_MODELS/AMEP/metrics/tasks_with_EE.properties index d04ac37..50cfd16 100644 --- a/QUALITY_MODELS/AMEP/metrics/tasks_with_EE.properties +++ b/QUALITY_MODELS/AMEP/metrics/tasks_with_EE.properties @@ -1,7 +1,7 @@ # metric props name=Tasks with Estimated Effort Information description= Percentage of tasks with estimated effort information added with respect to the total number of tasks in this sprint -factors=taskseffortinformation +factors=taskeffortinformation weights=1.0 diff --git a/QUALITY_MODELS/DEFAULT/metrics/acceptance_criteria_check.properties b/QUALITY_MODELS/DEFAULT/metrics/acceptance_criteria_check.properties index b70b6d4..b5da2ef 100644 --- a/QUALITY_MODELS/DEFAULT/metrics/acceptance_criteria_check.properties +++ b/QUALITY_MODELS/DEFAULT/metrics/acceptance_criteria_check.properties @@ -5,7 +5,7 @@ index=$$taiga.userstory.index enabled=true name=Acceptance Criteria Application description=Percentage of user stories with acceptance criteria with respect to the total number of user stories in this sprint -factors=userstoriesdefinitionquality +factors=userstoriesdefinition_quality weights=1.0 # query results diff --git a/QUALITY_MODELS/DEFAULT/metrics/assignedtasks.properties b/QUALITY_MODELS/DEFAULT/metrics/assignedtasks.properties index 498347d..25afa81 100644 --- a/QUALITY_MODELS/DEFAULT/metrics/assignedtasks.properties +++ b/QUALITY_MODELS/DEFAULT/metrics/assignedtasks.properties @@ -5,7 +5,7 @@ index=$$taiga.task.index enabled=true name=tasks description=Percentage of tasks made by a student with respect to the total number of tasks in the project -factors=taskscontribution +factors=taskcontribution weights=1.0 # query results diff --git a/QUALITY_MODELS/DEFAULT/metrics/closed_tasks_with_AE.properties b/QUALITY_MODELS/DEFAULT/metrics/closed_tasks_with_AE.properties index 8e8b03c..ebd7b3a 100644 --- a/QUALITY_MODELS/DEFAULT/metrics/closed_tasks_with_AE.properties +++ b/QUALITY_MODELS/DEFAULT/metrics/closed_tasks_with_AE.properties @@ -5,7 +5,7 @@ index=$$taiga.task.index enabled=true name=Closed Tasks with Actual Effort Information description=Percentage of closed tasks with actual effort information added with respect to the total number of closed tasks in this sprint -factors=taskseffortinformation +factors=taskeffortinformation weights=1.0 # query results diff --git a/QUALITY_MODELS/DEFAULT/metrics/closedtasks.properties b/QUALITY_MODELS/DEFAULT/metrics/closedtasks.properties index 0c80a6a..7e4641c 100644 --- a/QUALITY_MODELS/DEFAULT/metrics/closedtasks.properties +++ b/QUALITY_MODELS/DEFAULT/metrics/closedtasks.properties @@ -5,7 +5,7 @@ index=$$taiga.task.index enabled=true name=closed tasks description=Percentage of closed tasks made by a student with respect to the total number of tasks assigned to student -factors=fulfillmentoftasks +factors=fullfillmentoftasks weights=1.0 # query results diff --git a/QUALITY_MODELS/DEFAULT/metrics/pattern_check.properties b/QUALITY_MODELS/DEFAULT/metrics/pattern_check.properties index f569a51..7eabcce 100644 --- a/QUALITY_MODELS/DEFAULT/metrics/pattern_check.properties +++ b/QUALITY_MODELS/DEFAULT/metrics/pattern_check.properties @@ -5,7 +5,7 @@ index=$$taiga.userstory.index enabled=true name=Use of User Story pattern description=Percentage of user stories with the pattern (AS - I WANT - SO THAT - ) with respect to the total number of user stories in this sprint -factors=userstoriesdefinitionquality +factors=userstoriesdefinition_quality weights=1.0 # query results diff --git a/QUALITY_MODELS/DEFAULT/metrics/tasks_with_EE.properties b/QUALITY_MODELS/DEFAULT/metrics/tasks_with_EE.properties index 2ba726b..bc78555 100644 --- a/QUALITY_MODELS/DEFAULT/metrics/tasks_with_EE.properties +++ b/QUALITY_MODELS/DEFAULT/metrics/tasks_with_EE.properties @@ -5,7 +5,7 @@ index=$$taiga.task.index enabled=true name=Tasks with Estimated Effort Information description= Percentage of tasks with estimated effort information added with respect to the total number of tasks in this sprint -factors=taskseffortinformation +factors=taskeffortinformation weights=1.0 # query results diff --git a/QUALITY_MODELS/DEFAULT/metrics/test copy.properties b/QUALITY_MODELS/DEFAULT/metrics/test copy.properties deleted file mode 100644 index e25d212..0000000 --- a/QUALITY_MODELS/DEFAULT/metrics/test copy.properties +++ /dev/null @@ -1,22 +0,0 @@ -# values starting with $$ are looked up in project.properties -index=$$github.index - -# metric props -enabled=true -name=Number of Students commits -description=Number of commits made by a student -factors=commitscontribution -weights=1.0 - -# query results -result.commitsAssignee=commitsAssignee - -# metric defines a formula based on execution results of parameter- and metric-queries -metric= commitsAssignee -onError=set0 - - -#possible related_events sent by LD_connect from GITHUB: push, issues from TAIGA: issue, epic, task, userstory, relatedusertory -relatedEvent=push -scope=individual_only - diff --git a/QUALITY_MODELS/DEFAULT/metrics/test copy.query b/QUALITY_MODELS/DEFAULT/metrics/test copy.query deleted file mode 100644 index 60f752b..0000000 --- a/QUALITY_MODELS/DEFAULT/metrics/test copy.query +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "$group": { - "_id": null, - "commitsAssignee": { - "$sum": { - "$cond": [ - { - "$eq": [ - "$user.login", - "$$studentUser" - ] - }, - 1, - 0 - ] - } - } - } - }, - { - "$project": { - "_id": 0, - "commitsAssignee": 1 - } - } -] diff --git a/QUALITY_MODELS/DEFAULT/metrics/test.properties b/QUALITY_MODELS/DEFAULT/metrics/test.properties deleted file mode 100644 index e25d212..0000000 --- a/QUALITY_MODELS/DEFAULT/metrics/test.properties +++ /dev/null @@ -1,22 +0,0 @@ -# values starting with $$ are looked up in project.properties -index=$$github.index - -# metric props -enabled=true -name=Number of Students commits -description=Number of commits made by a student -factors=commitscontribution -weights=1.0 - -# query results -result.commitsAssignee=commitsAssignee - -# metric defines a formula based on execution results of parameter- and metric-queries -metric= commitsAssignee -onError=set0 - - -#possible related_events sent by LD_connect from GITHUB: push, issues from TAIGA: issue, epic, task, userstory, relatedusertory -relatedEvent=push -scope=individual_only - diff --git a/QUALITY_MODELS/DEFAULT/metrics/test.query b/QUALITY_MODELS/DEFAULT/metrics/test.query deleted file mode 100644 index 60f752b..0000000 --- a/QUALITY_MODELS/DEFAULT/metrics/test.query +++ /dev/null @@ -1,27 +0,0 @@ -[ - { - "$group": { - "_id": null, - "commitsAssignee": { - "$sum": { - "$cond": [ - { - "$eq": [ - "$user.login", - "$$studentUser" - ] - }, - 1, - 0 - ] - } - } - } - }, - { - "$project": { - "_id": 0, - "commitsAssignee": 1 - } - } -] diff --git a/app.py b/app.py index 4fec048..e3c9022 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,9 @@ +import json +import os import threading from flask import Flask, request, jsonify import logging +from datetime import datetime from logic.metrics_logic.metric_event_mapping import build_metrics_index_per_qm from logic.metrics_logic.metric_recalculation import compute_metric_for_student, compute_metric_for_team @@ -45,6 +48,7 @@ # Build the team->students map at startup TEAM_STUDENTS_MAP = build_team_students_map() +logging.getLogger(__name__).info("MAPA PROJECTES-ESTUDIANTS: %s", json.dumps(TEAM_STUDENTS_MAP, indent=2, ensure_ascii=False)) TEAM_QUALITYMODEL_MAP = load_qualitymodel_map() @@ -160,9 +164,82 @@ def handle_event(): return jsonify({"status": "received"}), 200 + +###################################### NEW CODE ###################################### +@app.route("/api/refresh", methods=["POST"]) +def handle_refresh(): + """ + HTTP endpoint per refrescar el mapa d'estudiants i recalcular mètriques. + Reconstrueix la variable global TEAM_STUDENTS_MAP. + """ + def refresh_and_update_map(): + global TEAM_STUDENTS_MAP + + logger.info("="*80) + logger.info("🔄 REFRESH INICIAT") + logger.info("="*80) + + # Mostrar mapa ABANS del refresh + logger.info("📋 MAPA ABANS DEL REFRESH:") + for team_id, sources in TEAM_STUDENTS_MAP.items(): + excel_students = sources.get("EXCEL", []) + logger.info(f" - {team_id}: {len(excel_students)} estudiants (EXCEL)") + + # CRÍTICO: Reconstruir el mapa global desde PostgreSQL + logger.info("🔄 Reconstruint TEAM_STUDENTS_MAP des de PostgreSQL...") + TEAM_STUDENTS_MAP = build_team_students_map() + + # Mostrar mapa DESPRÉS del refresh + logger.info("✅ MAPA DESPRÉS DEL REFRESH:") + for team_id, sources in TEAM_STUDENTS_MAP.items(): + excel_students = sources.get("EXCEL", []) + logger.info(f" - {team_id}: {len(excel_students)} estudiants (EXCEL)") + + logger.info("="*80) + logger.info(f"✅ Mapa actualitzat amb {len(TEAM_STUDENTS_MAP)} equips") + logger.info("="*80) + + # Executar refresh diari (recalcular totes les mètriques) + logger.info("🔄 Executant recàlcul de mètriques...") + run_daily_refresh() + logger.info("✅ Refresh completat") + logging.getLogger(__name__).info("MAPA PROJECTES-ESTUDIANTS AFTER REFRESH: %s", json.dumps(TEAM_STUDENTS_MAP, indent=2, ensure_ascii=False)) + + threading.Thread(target=refresh_and_update_map).start() + return jsonify({"status": "refresh started"}), 200 + +@app.route("/api/debug/students-map", methods=["GET"]) +def get_students_map(): + """ + Endpoint de debug per veure el mapa d'estudiants actual. + Mostra quin worker i thread gestiona la petició. + """ + result = {} + for team_id, sources in TEAM_STUDENTS_MAP.items(): + result[team_id] = { + "EXCEL": sources.get("EXCEL", []), + "GITHUB": sources.get("GITHUB", []), + "TAIGA": sources.get("TAIGA", []), + "total_students": len(sources.get("EXCEL", [])) + } + + return jsonify({ + "TEAM_STUDENTS_MAP": result, + "total_teams": len(TEAM_STUDENTS_MAP), + "timestamp": datetime.now().isoformat(), + # INFORMACIÓ DEL WORKER/THREAD + "worker_info": { + "process_id": os.getpid(), # PID del worker + "thread_id": threading.current_thread().ident, # ID del thread + "thread_name": threading.current_thread().name # Nom del thread + } + }), 200 + +####################################### END NEW CODE ###################################### + def run_app(): # Runs the Flask app - app.run(host="0.0.0.0", port=5001, debug=False, use_reloader=False) + app.run(host="0.0.0.0", port=5001, debug=True) @@ -170,10 +247,7 @@ def create_app(): """ Create and configure the Flask application. """ - if not hasattr(app, "scheduler_started"): - start_scheduler() - app.scheduler_started = True - return app + return app # ← la variable que ya tienes arriba if __name__ == "__main__": # Run the app directly diff --git a/config/settings.py b/config/settings.py index 4440dec..5f353df 100644 --- a/config/settings.py +++ b/config/settings.py @@ -19,7 +19,7 @@ #Mongo database settings MONGO_HOST = os.getenv("MONGO_HOST", "mongodb") MONGO_PORT = os.getenv("MONGO_PORT", "27017") -MONGO_DB = os.getenv("MONGO_DB", "event_dashboard") +MONGO_DB = os.getenv("MONGO_DB", "mongo") MONGO_USER = os.getenv("MONGO_USER", "") MONGO_PASS = os.getenv("MONGO_PASS", "") MONGO_AUTHSRC = os.getenv("MONGO_AUTHSRC", MONGO_DB) @@ -31,5 +31,3 @@ else: MONGO_URI = f"mongodb://{MONGO_HOST}:{MONGO_PORT}/{MONGO_DB}" -MONGO_URI = "mongodb://localhost:27017" - diff --git a/dockerfile b/dockerfile index 1a334f2..6541caa 100644 --- a/dockerfile +++ b/dockerfile @@ -20,4 +20,4 @@ EXPOSE 5001 ENV TZ=Europe/Madrid # Run gunicorn for "app:create_app()" factory function -CMD ["gunicorn", "-k", "gthread", "--bind", "0.0.0.0:5001", "--workers", "4", "--threads", "25", "app:create_app()"] +CMD ["gunicorn", "-k", "gthread", "--bind", "0.0.0.0:5001", "--workers", "1", "--threads", "25", "app:create_app()"] diff --git a/ld_refresh.py b/ld_refresh.py index 27a1528..1935db8 100644 --- a/ld_refresh.py +++ b/ld_refresh.py @@ -6,9 +6,10 @@ from database.mongo_client import db API_URL = os.getenv("EVAL_API_URL", "http://localhost:5001/api/event") -TEAM_STUDENTS = build_team_students_map() + QM_MAP = load_qualitymodel_map() +EVENT_TYPES = ["push", "task", "userstory"] @@ -30,18 +31,84 @@ def trigger_team_event(team_id: str, event_type: str) -> None: "quality_model": choose_qualitymodel(team_id, None, QM_MAP) } start = time.perf_counter() - r = requests.post(API_URL, json=payload, timeout=(0.4, 1)) #connect timeout 0.2s, read timeout 1s - logging.info("POST took %.3f s", time.perf_counter() - start) + r = requests.post(API_URL, json=payload, timeout=(0.2, 1)) #connect timeout 0.2s, read timeout 1s + logging.info("POST tardó %.3f s", time.perf_counter() - start) + logging.info("team=%s event=%s → status=%s", team_id, event_type, r.status_code) +def delete_orphan_collections_from_mongo(actual_teams): + for prefix in ["metrics", "factors", "strategic_indicators"]: # afegeix tots els prefixes que toquin + collections = db.list_collection_names() + for coll in collections: + if coll.startswith(prefix + "."): + team_collection = coll.split(".", 1)[1] + if team_collection not in actual_teams: + db.drop_collection(coll) + +def delete_orphan_student_documents(team_students_map): + """ + Elimina documentos de estudiantes que ya no existen en el mapa de estudiantes. + Busca en las colecciones metrics, factors y strategic_indicators. + """ + for team_id, sources in team_students_map.items(): + # Obtener lista de estudiantes válidos: incluye nombres reales (EXCEL) + usernames (GITHUB + TAIGA) + valid_students = [] + valid_students.extend(sources.get("EXCEL", [])) + valid_students.extend(sources.get("GITHUB", [])) + valid_students.extend(sources.get("TAIGA", [])) + + # Eliminar duplicados + valid_students = list(set(valid_students)) + + logging.info(f"🧹 Limpiando estudiantes huérfanos del equipo '{team_id}'...") + logging.info(f" Estudiantes válidos (nombres + usernames): {valid_students}") + + # Limpiar en cada tipo de colección + for prefix in ["metrics", "factors", "strategic_indicators"]: + collection_name = f"{prefix}.{team_id}" + + if collection_name not in db.list_collection_names(): + continue + + collection = db[collection_name] + + # Buscar documentos con student_name que no esté en la lista de válidos + # Los documentos de equipo no tienen student_name, así que los ignoramos + orphan_docs = collection.find({ + "student_name": {"$exists": True, "$nin": valid_students} + }) + + deleted_count = 0 + for doc in orphan_docs: + student_name = doc.get("student_name") + # Intentar obtener el nombre de la métrica/factor/indicador + item_name = doc.get("metric_name") or doc.get("factor_name") or doc.get("indicator_name") or doc.get("name", "documento") + + logging.info(f" ❌ Eliminando '{item_name}' del estudiante '{student_name}'") + collection.delete_one({"_id": doc["_id"]}) + deleted_count += 1 + + if deleted_count > 0: + logging.info(f" ✅ Eliminados {deleted_count} documentos huérfanos de '{collection_name}'") def run_daily_refresh() -> None: '''Function to run the daily refresh of events.''' + TEAM_STUDENTS = build_team_students_map() + actual_teams = list(TEAM_STUDENTS.keys()) + + # 1. Eliminar colecciones de equipos que ya no existen + delete_orphan_collections_from_mongo(actual_teams) + + # 2. Eliminar documentos de estudiantes que ya no están en los equipos + # delete_orphan_student_documents(TEAM_STUDENTS) + + # 3. Recalcular métricas para todos los equipos activos for team in TEAM_STUDENTS.keys(): # Get all the teams from the TEAM_STUDENTS map + ''' if not team_is_active(team): - logging.info("Team %s does not have activity we ommit", team) # If the team is not active, skip it + logging.info("Equipo %s sin actividad previa; se omite.", team) # If the team is not active, skip it continue - + ''' events= get_available_events() for event in events: # If the team is active, trigger all the events trigger_team_event(team, event) From 9dbc2b12b79918b950c7ffb5dcb2d8d99428a55e Mon Sep 17 00:00:00 2001 From: geerardferrer Date: Mon, 29 Dec 2025 17:17:10 +0100 Subject: [PATCH 2/8] Remove logging statements from event triggering and orphan student document cleanup --- ld_refresh.py | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/ld_refresh.py b/ld_refresh.py index 1935db8..1eb33d3 100644 --- a/ld_refresh.py +++ b/ld_refresh.py @@ -32,9 +32,6 @@ def trigger_team_event(team_id: str, event_type: str) -> None: } start = time.perf_counter() r = requests.post(API_URL, json=payload, timeout=(0.2, 1)) #connect timeout 0.2s, read timeout 1s - logging.info("POST tardó %.3f s", time.perf_counter() - start) - - logging.info("team=%s event=%s → status=%s", team_id, event_type, r.status_code) def delete_orphan_collections_from_mongo(actual_teams): for prefix in ["metrics", "factors", "strategic_indicators"]: # afegeix tots els prefixes que toquin @@ -60,9 +57,6 @@ def delete_orphan_student_documents(team_students_map): # Eliminar duplicados valid_students = list(set(valid_students)) - logging.info(f"🧹 Limpiando estudiantes huérfanos del equipo '{team_id}'...") - logging.info(f" Estudiantes válidos (nombres + usernames): {valid_students}") - # Limpiar en cada tipo de colección for prefix in ["metrics", "factors", "strategic_indicators"]: collection_name = f"{prefix}.{team_id}" @@ -83,13 +77,9 @@ def delete_orphan_student_documents(team_students_map): student_name = doc.get("student_name") # Intentar obtener el nombre de la métrica/factor/indicador item_name = doc.get("metric_name") or doc.get("factor_name") or doc.get("indicator_name") or doc.get("name", "documento") - - logging.info(f" ❌ Eliminando '{item_name}' del estudiante '{student_name}'") + collection.delete_one({"_id": doc["_id"]}) deleted_count += 1 - - if deleted_count > 0: - logging.info(f" ✅ Eliminados {deleted_count} documentos huérfanos de '{collection_name}'") def run_daily_refresh() -> None: '''Function to run the daily refresh of events.''' From 164a65a87518f566b77db1580bb86dc7f715a473 Mon Sep 17 00:00:00 2001 From: EncryptEx <41539618+EncryptEx@users.noreply.github.com> Date: Mon, 16 Mar 2026 11:31:22 +0100 Subject: [PATCH 3/8] deleted __pycache__ , myenvn and .env --- .env | 12 - .../StudentDatafromLDRESTAPI.cpython-310.pyc | Bin 1765 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 144 -> 0 bytes .../load_config_file.cpython-310.pyc | Bin 847 -> 0 bytes .../__pycache__/logger_setup.cpython-310.pyc | Bin 799 -> 0 bytes .../quality_model_config.cpython-310.pyc | Bin 1137 -> 0 bytes .../quality_model_loader.cpython-310.pyc | Bin 1357 -> 0 bytes __pycache__/app.cpython-310.pyc | Bin 3598 -> 0 bytes __pycache__/app.cpython-311.pyc | Bin 3477 -> 0 bytes __pycache__/ld_refresh.cpython-310.pyc | Bin 2049 -> 0 bytes config/__pycache__/__init__.cpython-310.pyc | Bin 141 -> 0 bytes .../load_config_file.cpython-310.pyc | Bin 1114 -> 0 bytes .../__pycache__/logger_config.cpython-310.pyc | Bin 801 -> 0 bytes .../quality_model_config.cpython-310.pyc | Bin 1151 -> 0 bytes config/__pycache__/settings.cpython-310.pyc | Bin 809 -> 0 bytes .../config_variables.cpython-310.pyc | Bin 315 -> 0 bytes database/__pycache__/__init__.cpython-310.pyc | Bin 143 -> 0 bytes .../__pycache__/mongo_client.cpython-310.pyc | Bin 565 -> 0 bytes .../quality_model_loader.cpython-310.pyc | Bin 1360 -> 0 bytes .../factor_event_mapping.cpython-310.pyc | Bin 2279 -> 0 bytes .../factor_recalculation.cpython-310.pyc | Bin 2708 -> 0 bytes .../store_factors_mongo.cpython-310.pyc | Bin 2123 -> 0 bytes .../indicator_event_mapping.cpython-310.pyc | Bin 2175 -> 0 bytes .../indicator_recalculation.cpython-310.pyc | Bin 2216 -> 0 bytes .../store_indicator_mongo.cpython-310.pyc | Bin 2053 -> 0 bytes .../metric_event_mapping.cpython-310.pyc | Bin 2191 -> 0 bytes .../metric_event_mapping.cpython-311.pyc | Bin 3401 -> 0 bytes .../metric_placeholder.cpython-310.pyc | Bin 2031 -> 0 bytes .../metric_placeholder.cpython-311.pyc | Bin 2265 -> 0 bytes .../metric_recalculation.cpython-310.pyc | Bin 4576 -> 0 bytes .../metric_recalculation.cpython-311.pyc | Bin 6628 -> 0 bytes .../metricsrelation.cpython-310.pyc | Bin 1861 -> 0 bytes .../run_mogo_query.cpython-310.pyc | Bin 1920 -> 0 bytes .../store_metric_mongo.cpython-310.pyc | Bin 2218 -> 0 bytes utils/__pycache__/__init__.cpython-310.pyc | Bin 140 -> 0 bytes .../evaluation_test.cpython-310.pyc | Bin 3182 -> 0 bytes .../DateTime-5.5.dist-info/INSTALLER | 1 - .../DateTime-5.5.dist-info/LICENSE.txt | 44 - .../DateTime-5.5.dist-info/METADATA | 1167 --- .../DateTime-5.5.dist-info/RECORD | 22 - .../DateTime-5.5.dist-info/REQUESTED | 0 .../DateTime-5.5.dist-info/WHEEL | 5 - .../DateTime-5.5.dist-info/top_level.txt | 1 - venv/Lib/site-packages/DateTime/DateTime.py | 1948 ---- venv/Lib/site-packages/DateTime/DateTime.txt | 785 -- venv/Lib/site-packages/DateTime/__init__.py | 18 - .../__pycache__/DateTime.cpython-310.pyc | Bin 58873 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 256 -> 0 bytes .../__pycache__/interfaces.cpython-310.pyc | Bin 17620 -> 0 bytes .../__pycache__/pytz_support.cpython-310.pyc | Bin 10062 -> 0 bytes venv/Lib/site-packages/DateTime/interfaces.py | 375 - venv/Lib/site-packages/DateTime/pytz.txt | 192 - .../site-packages/DateTime/pytz_support.py | 269 - .../site-packages/DateTime/tests/__init__.py | 15 - .../__pycache__/__init__.cpython-310.pyc | Bin 172 -> 0 bytes .../__pycache__/test_datetime.cpython-310.pyc | Bin 22384 -> 0 bytes .../DateTime/tests/julian_testdata.txt | 57 - .../DateTime/tests/test_datetime.py | 764 -- .../MarkupSafe-3.0.2.dist-info/INSTALLER | 1 - .../MarkupSafe-3.0.2.dist-info/LICENSE.txt | 28 - .../MarkupSafe-3.0.2.dist-info/METADATA | 92 - .../MarkupSafe-3.0.2.dist-info/RECORD | 14 - .../MarkupSafe-3.0.2.dist-info/WHEEL | 5 - .../MarkupSafe-3.0.2.dist-info/top_level.txt | 1 - .../__pycache__/pathlib.cpython-310.pyc | Bin 36192 -> 0 bytes .../site-packages/_distutils_hack/__init__.py | 222 - .../__pycache__/__init__.cpython-310.pyc | Bin 7577 -> 0 bytes .../__pycache__/override.cpython-310.pyc | Bin 224 -> 0 bytes .../site-packages/_distutils_hack/override.py | 1 - .../blinker-1.9.0.dist-info/INSTALLER | 1 - .../blinker-1.9.0.dist-info/LICENSE.txt | 20 - .../blinker-1.9.0.dist-info/METADATA | 60 - .../blinker-1.9.0.dist-info/RECORD | 12 - .../blinker-1.9.0.dist-info/WHEEL | 4 - venv/Lib/site-packages/blinker/__init__.py | 17 - .../__pycache__/__init__.cpython-310.pyc | Bin 463 -> 0 bytes .../__pycache__/_utilities.cpython-310.pyc | Bin 2161 -> 0 bytes .../blinker/__pycache__/base.cpython-310.pyc | Bin 17598 -> 0 bytes venv/Lib/site-packages/blinker/_utilities.py | 64 - venv/Lib/site-packages/blinker/base.py | 512 - venv/Lib/site-packages/blinker/py.typed | 0 venv/Lib/site-packages/bson/__init__.py | 1484 --- .../bson/__pycache__/__init__.cpython-310.pyc | Bin 42401 -> 0 bytes .../bson/__pycache__/_helpers.cpython-310.pyc | Bin 1171 -> 0 bytes .../bson/__pycache__/binary.cpython-310.pyc | Bin 12903 -> 0 bytes .../bson/__pycache__/code.cpython-310.pyc | Bin 3185 -> 0 bytes .../__pycache__/codec_options.cpython-310.pyc | Bin 17458 -> 0 bytes .../__pycache__/datetime_ms.cpython-310.pyc | Bin 6261 -> 0 bytes .../bson/__pycache__/dbref.cpython-310.pyc | Bin 4792 -> 0 bytes .../__pycache__/decimal128.cpython-310.pyc | Bin 9784 -> 0 bytes .../bson/__pycache__/errors.cpython-310.pyc | Bin 1197 -> 0 bytes .../bson/__pycache__/int64.cpython-310.pyc | Bin 1139 -> 0 bytes .../__pycache__/json_util.cpython-310.pyc | Bin 32884 -> 0 bytes .../bson/__pycache__/max_key.cpython-310.pyc | Bin 1942 -> 0 bytes .../bson/__pycache__/min_key.cpython-310.pyc | Bin 1942 -> 0 bytes .../bson/__pycache__/objectid.cpython-310.pyc | Bin 9072 -> 0 bytes .../bson/__pycache__/raw_bson.cpython-310.pyc | Bin 7241 -> 0 bytes .../bson/__pycache__/regex.cpython-310.pyc | Bin 4580 -> 0 bytes .../bson/__pycache__/son.cpython-310.pyc | Bin 7269 -> 0 bytes .../__pycache__/timestamp.cpython-310.pyc | Bin 4300 -> 0 bytes .../bson/__pycache__/typings.cpython-310.pyc | Bin 704 -> 0 bytes .../bson/__pycache__/tz_util.cpython-310.pyc | Bin 2072 -> 0 bytes .../bson/_cbson.cp310-win_amd64.pyd | Bin 46592 -> 0 bytes .../bson/_cbson.cp39-win_amd64.pyd | Bin 46592 -> 0 bytes venv/Lib/site-packages/bson/_cbsonmodule.c | 3267 ------- venv/Lib/site-packages/bson/_cbsonmodule.h | 181 - venv/Lib/site-packages/bson/_helpers.py | 43 - venv/Lib/site-packages/bson/binary.py | 551 -- venv/Lib/site-packages/bson/bson-endian.h | 233 - venv/Lib/site-packages/bson/buffer.c | 157 - venv/Lib/site-packages/bson/buffer.h | 51 - venv/Lib/site-packages/bson/code.py | 100 - venv/Lib/site-packages/bson/codec_options.py | 511 - venv/Lib/site-packages/bson/datetime_ms.py | 182 - venv/Lib/site-packages/bson/dbref.py | 133 - venv/Lib/site-packages/bson/decimal128.py | 312 - venv/Lib/site-packages/bson/errors.py | 36 - venv/Lib/site-packages/bson/int64.py | 39 - venv/Lib/site-packages/bson/json_util.py | 1164 --- venv/Lib/site-packages/bson/max_key.py | 56 - venv/Lib/site-packages/bson/min_key.py | 56 - venv/Lib/site-packages/bson/objectid.py | 274 - venv/Lib/site-packages/bson/py.typed | 2 - venv/Lib/site-packages/bson/raw_bson.py | 196 - venv/Lib/site-packages/bson/regex.py | 133 - venv/Lib/site-packages/bson/son.py | 211 - venv/Lib/site-packages/bson/time64.c | 781 -- venv/Lib/site-packages/bson/time64.h | 67 - venv/Lib/site-packages/bson/time64_config.h | 78 - venv/Lib/site-packages/bson/time64_limits.h | 95 - venv/Lib/site-packages/bson/timestamp.py | 123 - venv/Lib/site-packages/bson/typings.py | 31 - venv/Lib/site-packages/bson/tz_util.py | 56 - .../certifi-2025.4.26.dist-info/INSTALLER | 1 - .../certifi-2025.4.26.dist-info/METADATA | 78 - .../certifi-2025.4.26.dist-info/RECORD | 14 - .../certifi-2025.4.26.dist-info/WHEEL | 5 - .../licenses/LICENSE | 20 - .../certifi-2025.4.26.dist-info/top_level.txt | 1 - venv/Lib/site-packages/certifi/__init__.py | 4 - venv/Lib/site-packages/certifi/__main__.py | 12 - .../__pycache__/__init__.cpython-310.pyc | Bin 278 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 416 -> 0 bytes .../certifi/__pycache__/core.cpython-310.pyc | Bin 2109 -> 0 bytes venv/Lib/site-packages/certifi/cacert.pem | 4676 --------- venv/Lib/site-packages/certifi/core.py | 114 - venv/Lib/site-packages/certifi/py.typed | 0 .../INSTALLER | 1 - .../METADATA | 731 -- .../charset_normalizer-3.4.2.dist-info/RECORD | 35 - .../charset_normalizer-3.4.2.dist-info/WHEEL | 5 - .../entry_points.txt | 2 - .../licenses/LICENSE | 21 - .../top_level.txt | 1 - .../charset_normalizer/__init__.py | 48 - .../charset_normalizer/__main__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 1620 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 309 -> 0 bytes .../__pycache__/api.cpython-310.pyc | Bin 11803 -> 0 bytes .../__pycache__/cd.cpython-310.pyc | Bin 9736 -> 0 bytes .../__pycache__/constant.cpython-310.pyc | Bin 32527 -> 0 bytes .../__pycache__/legacy.cpython-310.pyc | Bin 2141 -> 0 bytes .../__pycache__/md.cpython-310.pyc | Bin 16099 -> 0 bytes .../__pycache__/models.cpython-310.pyc | Bin 12192 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 8987 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 311 -> 0 bytes .../site-packages/charset_normalizer/api.py | 668 -- .../site-packages/charset_normalizer/cd.py | 395 - .../charset_normalizer/cli/__init__.py | 8 - .../charset_normalizer/cli/__main__.py | 381 - .../cli/__pycache__/__init__.cpython-310.pyc | Bin 312 -> 0 bytes .../cli/__pycache__/__main__.cpython-310.pyc | Bin 9329 -> 0 bytes .../charset_normalizer/constant.py | 2015 ---- .../charset_normalizer/legacy.py | 64 - .../charset_normalizer/md.cp310-win_amd64.pyd | Bin 10752 -> 0 bytes .../site-packages/charset_normalizer/md.py | 635 -- .../md__mypyc.cp310-win_amd64.pyd | Bin 122880 -> 0 bytes .../charset_normalizer/models.py | 360 - .../site-packages/charset_normalizer/py.typed | 0 .../site-packages/charset_normalizer/utils.py | 414 - .../charset_normalizer/version.py | 8 - .../click-8.1.8.dist-info/INSTALLER | 1 - .../click-8.1.8.dist-info/LICENSE.txt | 28 - .../click-8.1.8.dist-info/METADATA | 74 - .../click-8.1.8.dist-info/RECORD | 38 - .../site-packages/click-8.1.8.dist-info/WHEEL | 4 - venv/Lib/site-packages/click/__init__.py | 75 - .../__pycache__/__init__.cpython-310.pyc | Bin 2640 -> 0 bytes .../click/__pycache__/_compat.cpython-310.pyc | Bin 15675 -> 0 bytes .../__pycache__/_termui_impl.cpython-310.pyc | Bin 16567 -> 0 bytes .../__pycache__/_textwrap.cpython-310.pyc | Bin 1541 -> 0 bytes .../__pycache__/_winconsole.cpython-310.pyc | Bin 7659 -> 0 bytes .../click/__pycache__/core.cpython-310.pyc | Bin 91468 -> 0 bytes .../__pycache__/decorators.cpython-310.pyc | Bin 17708 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 10348 -> 0 bytes .../__pycache__/formatting.cpython-310.pyc | Bin 9454 -> 0 bytes .../click/__pycache__/globals.cpython-310.pyc | Bin 2426 -> 0 bytes .../click/__pycache__/parser.cpython-310.pyc | Bin 13671 -> 0 bytes .../shell_completion.cpython-310.pyc | Bin 16924 -> 0 bytes .../click/__pycache__/termui.cpython-310.pyc | Bin 26127 -> 0 bytes .../click/__pycache__/testing.cpython-310.pyc | Bin 15289 -> 0 bytes .../click/__pycache__/types.cpython-310.pyc | Bin 33728 -> 0 bytes .../click/__pycache__/utils.cpython-310.pyc | Bin 18876 -> 0 bytes venv/Lib/site-packages/click/_compat.py | 623 -- venv/Lib/site-packages/click/_termui_impl.py | 788 -- venv/Lib/site-packages/click/_textwrap.py | 49 - venv/Lib/site-packages/click/_winconsole.py | 279 - venv/Lib/site-packages/click/core.py | 3047 ------ venv/Lib/site-packages/click/decorators.py | 562 -- venv/Lib/site-packages/click/exceptions.py | 296 - venv/Lib/site-packages/click/formatting.py | 301 - venv/Lib/site-packages/click/globals.py | 67 - venv/Lib/site-packages/click/parser.py | 531 - venv/Lib/site-packages/click/py.typed | 0 .../site-packages/click/shell_completion.py | 603 -- venv/Lib/site-packages/click/termui.py | 784 -- venv/Lib/site-packages/click/testing.py | 483 - venv/Lib/site-packages/click/types.py | 1093 --- venv/Lib/site-packages/click/utils.py | 624 -- .../colorama-0.4.6.dist-info/INSTALLER | 1 - .../colorama-0.4.6.dist-info/METADATA | 441 - .../colorama-0.4.6.dist-info/RECORD | 31 - .../colorama-0.4.6.dist-info/WHEEL | 5 - .../licenses/LICENSE.txt | 27 - venv/Lib/site-packages/colorama/__init__.py | 7 - .../__pycache__/__init__.cpython-310.pyc | Bin 452 -> 0 bytes .../colorama/__pycache__/ansi.cpython-310.pyc | Bin 2978 -> 0 bytes .../__pycache__/ansitowin32.cpython-310.pyc | Bin 8490 -> 0 bytes .../__pycache__/initialise.cpython-310.pyc | Bin 2235 -> 0 bytes .../__pycache__/win32.cpython-310.pyc | Bin 4445 -> 0 bytes .../__pycache__/winterm.cpython-310.pyc | Bin 5141 -> 0 bytes venv/Lib/site-packages/colorama/ansi.py | 102 - .../Lib/site-packages/colorama/ansitowin32.py | 277 - venv/Lib/site-packages/colorama/initialise.py | 121 - .../site-packages/colorama/tests/__init__.py | 1 - .../__pycache__/__init__.cpython-310.pyc | Bin 172 -> 0 bytes .../__pycache__/ansi_test.cpython-310.pyc | Bin 2264 -> 0 bytes .../ansitowin32_test.cpython-310.pyc | Bin 11575 -> 0 bytes .../initialise_test.cpython-310.pyc | Bin 6872 -> 0 bytes .../__pycache__/isatty_test.cpython-310.pyc | Bin 2663 -> 0 bytes .../tests/__pycache__/utils.cpython-310.pyc | Bin 1572 -> 0 bytes .../__pycache__/winterm_test.cpython-310.pyc | Bin 3165 -> 0 bytes .../site-packages/colorama/tests/ansi_test.py | 76 - .../colorama/tests/ansitowin32_test.py | 294 - .../colorama/tests/initialise_test.py | 189 - .../colorama/tests/isatty_test.py | 57 - .../Lib/site-packages/colorama/tests/utils.py | 49 - .../colorama/tests/winterm_test.py | 131 - venv/Lib/site-packages/colorama/win32.py | 180 - venv/Lib/site-packages/colorama/winterm.py | 195 - .../site-packages/distutils-precedence.pth | 1 - venv/Lib/site-packages/dns/__init__.py | 70 - .../dns/__pycache__/__init__.cpython-310.pyc | Bin 689 -> 0 bytes .../__pycache__/_asyncbackend.cpython-310.pyc | Bin 4134 -> 0 bytes .../_asyncio_backend.cpython-310.pyc | Bin 8945 -> 0 bytes .../dns/__pycache__/_ddr.cpython-310.pyc | Bin 4113 -> 0 bytes .../dns/__pycache__/_features.cpython-310.pyc | Bin 2405 -> 0 bytes .../_immutable_ctx.cpython-310.pyc | Bin 2169 -> 0 bytes .../__pycache__/_trio_backend.cpython-310.pyc | Bin 7640 -> 0 bytes .../__pycache__/asyncbackend.cpython-310.pyc | Bin 2621 -> 0 bytes .../__pycache__/asyncquery.cpython-310.pyc | Bin 20584 -> 0 bytes .../__pycache__/asyncresolver.cpython-310.pyc | Bin 13198 -> 0 bytes .../dns/__pycache__/dnssec.cpython-310.pyc | Bin 32767 -> 0 bytes .../__pycache__/dnssectypes.cpython-310.pyc | Bin 1632 -> 0 bytes .../dns/__pycache__/e164.cpython-310.pyc | Bin 3491 -> 0 bytes .../dns/__pycache__/edns.cpython-310.pyc | Bin 16917 -> 0 bytes .../dns/__pycache__/entropy.cpython-310.pyc | Bin 3381 -> 0 bytes .../dns/__pycache__/enum.cpython-310.pyc | Bin 3263 -> 0 bytes .../dns/__pycache__/exception.cpython-310.pyc | Bin 5627 -> 0 bytes .../dns/__pycache__/flags.cpython-310.pyc | Bin 2178 -> 0 bytes .../dns/__pycache__/grange.cpython-310.pyc | Bin 1149 -> 0 bytes .../dns/__pycache__/immutable.cpython-310.pyc | Bin 2432 -> 0 bytes .../dns/__pycache__/inet.cpython-310.pyc | Bin 4569 -> 0 bytes .../dns/__pycache__/ipv4.cpython-310.pyc | Bin 1860 -> 0 bytes .../dns/__pycache__/ipv6.cpython-310.pyc | Bin 3917 -> 0 bytes .../dns/__pycache__/message.cpython-310.pyc | Bin 52897 -> 0 bytes .../dns/__pycache__/name.cpython-310.pyc | Bin 34762 -> 0 bytes .../dns/__pycache__/namedict.cpython-310.pyc | Bin 3012 -> 0 bytes .../__pycache__/nameserver.cpython-310.pyc | Bin 9267 -> 0 bytes .../dns/__pycache__/node.cpython-310.pyc | Bin 11615 -> 0 bytes .../dns/__pycache__/opcode.cpython-310.pyc | Bin 2481 -> 0 bytes .../dns/__pycache__/query.cpython-310.pyc | Bin 44326 -> 0 bytes .../dns/__pycache__/rcode.cpython-310.pyc | Bin 3261 -> 0 bytes .../dns/__pycache__/rdata.cpython-310.pyc | Bin 24337 -> 0 bytes .../__pycache__/rdataclass.cpython-310.pyc | Bin 2784 -> 0 bytes .../dns/__pycache__/rdataset.cpython-310.pyc | Bin 15298 -> 0 bytes .../dns/__pycache__/rdatatype.cpython-310.pyc | Bin 6741 -> 0 bytes .../dns/__pycache__/renderer.cpython-310.pyc | Bin 9910 -> 0 bytes .../dns/__pycache__/resolver.cpython-310.pyc | Bin 52699 -> 0 bytes .../__pycache__/reversename.cpython-310.pyc | Bin 3065 -> 0 bytes .../dns/__pycache__/rrset.cpython-310.pyc | Bin 7937 -> 0 bytes .../dns/__pycache__/serial.cpython-310.pyc | Bin 2876 -> 0 bytes .../dns/__pycache__/set.cpython-310.pyc | Bin 8740 -> 0 bytes .../dns/__pycache__/tokenizer.cpython-310.pyc | Bin 17127 -> 0 bytes .../__pycache__/transaction.cpython-310.pyc | Bin 19872 -> 0 bytes .../dns/__pycache__/tsig.cpython-310.pyc | Bin 10256 -> 0 bytes .../__pycache__/tsigkeyring.cpython-310.pyc | Bin 1852 -> 0 bytes .../dns/__pycache__/ttl.cpython-310.pyc | Bin 1693 -> 0 bytes .../dns/__pycache__/update.cpython-310.pyc | Bin 8885 -> 0 bytes .../dns/__pycache__/version.cpython-310.pyc | Bin 580 -> 0 bytes .../dns/__pycache__/versioned.cpython-310.pyc | Bin 8876 -> 0 bytes .../dns/__pycache__/win32util.cpython-310.pyc | Bin 5556 -> 0 bytes .../dns/__pycache__/wire.cpython-310.pyc | Bin 3314 -> 0 bytes .../dns/__pycache__/xfr.cpython-310.pyc | Bin 7820 -> 0 bytes .../dns/__pycache__/zone.cpython-310.pyc | Bin 45435 -> 0 bytes .../dns/__pycache__/zonefile.cpython-310.pyc | Bin 17735 -> 0 bytes .../dns/__pycache__/zonetypes.cpython-310.pyc | Bin 1043 -> 0 bytes venv/Lib/site-packages/dns/_asyncbackend.py | 100 - .../Lib/site-packages/dns/_asyncio_backend.py | 275 - venv/Lib/site-packages/dns/_ddr.py | 154 - venv/Lib/site-packages/dns/_features.py | 95 - venv/Lib/site-packages/dns/_immutable_ctx.py | 76 - venv/Lib/site-packages/dns/_trio_backend.py | 253 - venv/Lib/site-packages/dns/asyncbackend.py | 101 - venv/Lib/site-packages/dns/asyncquery.py | 913 -- venv/Lib/site-packages/dns/asyncresolver.py | 475 - venv/Lib/site-packages/dns/dnssec.py | 1247 --- .../site-packages/dns/dnssecalgs/__init__.py | 121 - .../__pycache__/__init__.cpython-310.pyc | Bin 3740 -> 0 bytes .../__pycache__/base.cpython-310.pyc | Bin 3766 -> 0 bytes .../__pycache__/cryptography.cpython-310.pyc | Bin 2664 -> 0 bytes .../__pycache__/dsa.cpython-310.pyc | Bin 3823 -> 0 bytes .../__pycache__/ecdsa.cpython-310.pyc | Bin 3867 -> 0 bytes .../__pycache__/eddsa.cpython-310.pyc | Bin 2990 -> 0 bytes .../__pycache__/rsa.cpython-310.pyc | Bin 4712 -> 0 bytes venv/Lib/site-packages/dns/dnssecalgs/base.py | 89 - .../dns/dnssecalgs/cryptography.py | 68 - venv/Lib/site-packages/dns/dnssecalgs/dsa.py | 106 - .../Lib/site-packages/dns/dnssecalgs/ecdsa.py | 97 - .../Lib/site-packages/dns/dnssecalgs/eddsa.py | 70 - venv/Lib/site-packages/dns/dnssecalgs/rsa.py | 124 - venv/Lib/site-packages/dns/dnssectypes.py | 71 - venv/Lib/site-packages/dns/e164.py | 116 - venv/Lib/site-packages/dns/edns.py | 572 -- venv/Lib/site-packages/dns/entropy.py | 130 - venv/Lib/site-packages/dns/enum.py | 116 - venv/Lib/site-packages/dns/exception.py | 169 - venv/Lib/site-packages/dns/flags.py | 123 - venv/Lib/site-packages/dns/grange.py | 72 - venv/Lib/site-packages/dns/immutable.py | 68 - venv/Lib/site-packages/dns/inet.py | 197 - venv/Lib/site-packages/dns/ipv4.py | 77 - venv/Lib/site-packages/dns/ipv6.py | 217 - venv/Lib/site-packages/dns/message.py | 1933 ---- venv/Lib/site-packages/dns/name.py | 1284 --- venv/Lib/site-packages/dns/namedict.py | 109 - venv/Lib/site-packages/dns/nameserver.py | 363 - venv/Lib/site-packages/dns/node.py | 359 - venv/Lib/site-packages/dns/opcode.py | 117 - venv/Lib/site-packages/dns/py.typed | 0 venv/Lib/site-packages/dns/query.py | 1665 ---- venv/Lib/site-packages/dns/quic/__init__.py | 80 - .../quic/__pycache__/__init__.cpython-310.pyc | Bin 2548 -> 0 bytes .../quic/__pycache__/_asyncio.cpython-310.pyc | Bin 8984 -> 0 bytes .../quic/__pycache__/_common.cpython-310.pyc | Bin 9454 -> 0 bytes .../quic/__pycache__/_sync.cpython-310.pyc | Bin 10191 -> 0 bytes .../quic/__pycache__/_trio.cpython-310.pyc | Bin 7818 -> 0 bytes venv/Lib/site-packages/dns/quic/_asyncio.py | 267 - venv/Lib/site-packages/dns/quic/_common.py | 339 - venv/Lib/site-packages/dns/quic/_sync.py | 295 - venv/Lib/site-packages/dns/quic/_trio.py | 246 - venv/Lib/site-packages/dns/rcode.py | 168 - venv/Lib/site-packages/dns/rdata.py | 911 -- venv/Lib/site-packages/dns/rdataclass.py | 118 - venv/Lib/site-packages/dns/rdataset.py | 512 - venv/Lib/site-packages/dns/rdatatype.py | 336 - .../site-packages/dns/rdtypes/ANY/AFSDB.py | 45 - .../site-packages/dns/rdtypes/ANY/AMTRELAY.py | 91 - venv/Lib/site-packages/dns/rdtypes/ANY/AVC.py | 26 - venv/Lib/site-packages/dns/rdtypes/ANY/CAA.py | 71 - .../site-packages/dns/rdtypes/ANY/CDNSKEY.py | 33 - venv/Lib/site-packages/dns/rdtypes/ANY/CDS.py | 29 - .../Lib/site-packages/dns/rdtypes/ANY/CERT.py | 116 - .../site-packages/dns/rdtypes/ANY/CNAME.py | 28 - .../site-packages/dns/rdtypes/ANY/CSYNC.py | 68 - venv/Lib/site-packages/dns/rdtypes/ANY/DLV.py | 24 - .../site-packages/dns/rdtypes/ANY/DNAME.py | 27 - .../site-packages/dns/rdtypes/ANY/DNSKEY.py | 33 - venv/Lib/site-packages/dns/rdtypes/ANY/DS.py | 24 - .../site-packages/dns/rdtypes/ANY/EUI48.py | 30 - .../site-packages/dns/rdtypes/ANY/EUI64.py | 30 - .../Lib/site-packages/dns/rdtypes/ANY/GPOS.py | 126 - .../site-packages/dns/rdtypes/ANY/HINFO.py | 64 - venv/Lib/site-packages/dns/rdtypes/ANY/HIP.py | 85 - .../Lib/site-packages/dns/rdtypes/ANY/ISDN.py | 78 - venv/Lib/site-packages/dns/rdtypes/ANY/L32.py | 41 - venv/Lib/site-packages/dns/rdtypes/ANY/L64.py | 47 - venv/Lib/site-packages/dns/rdtypes/ANY/LOC.py | 353 - venv/Lib/site-packages/dns/rdtypes/ANY/LP.py | 42 - venv/Lib/site-packages/dns/rdtypes/ANY/MX.py | 24 - venv/Lib/site-packages/dns/rdtypes/ANY/NID.py | 47 - .../site-packages/dns/rdtypes/ANY/NINFO.py | 26 - venv/Lib/site-packages/dns/rdtypes/ANY/NS.py | 24 - .../Lib/site-packages/dns/rdtypes/ANY/NSEC.py | 67 - .../site-packages/dns/rdtypes/ANY/NSEC3.py | 126 - .../dns/rdtypes/ANY/NSEC3PARAM.py | 69 - .../dns/rdtypes/ANY/OPENPGPKEY.py | 53 - venv/Lib/site-packages/dns/rdtypes/ANY/OPT.py | 77 - venv/Lib/site-packages/dns/rdtypes/ANY/PTR.py | 24 - .../site-packages/dns/rdtypes/ANY/RESINFO.py | 24 - venv/Lib/site-packages/dns/rdtypes/ANY/RP.py | 58 - .../site-packages/dns/rdtypes/ANY/RRSIG.py | 157 - venv/Lib/site-packages/dns/rdtypes/ANY/RT.py | 24 - .../site-packages/dns/rdtypes/ANY/SMIMEA.py | 9 - venv/Lib/site-packages/dns/rdtypes/ANY/SOA.py | 86 - venv/Lib/site-packages/dns/rdtypes/ANY/SPF.py | 26 - .../site-packages/dns/rdtypes/ANY/SSHFP.py | 68 - .../Lib/site-packages/dns/rdtypes/ANY/TKEY.py | 142 - .../Lib/site-packages/dns/rdtypes/ANY/TLSA.py | 9 - .../Lib/site-packages/dns/rdtypes/ANY/TSIG.py | 160 - venv/Lib/site-packages/dns/rdtypes/ANY/TXT.py | 24 - venv/Lib/site-packages/dns/rdtypes/ANY/URI.py | 79 - .../site-packages/dns/rdtypes/ANY/WALLET.py | 9 - venv/Lib/site-packages/dns/rdtypes/ANY/X25.py | 57 - .../site-packages/dns/rdtypes/ANY/ZONEMD.py | 66 - .../site-packages/dns/rdtypes/ANY/__init__.py | 70 - .../ANY/__pycache__/AFSDB.cpython-310.pyc | Bin 783 -> 0 bytes .../ANY/__pycache__/AMTRELAY.cpython-310.pyc | Bin 2542 -> 0 bytes .../ANY/__pycache__/AVC.cpython-310.pyc | Bin 462 -> 0 bytes .../ANY/__pycache__/CAA.cpython-310.pyc | Bin 2009 -> 0 bytes .../ANY/__pycache__/CDNSKEY.cpython-310.pyc | Bin 541 -> 0 bytes .../ANY/__pycache__/CDS.cpython-310.pyc | Bin 547 -> 0 bytes .../ANY/__pycache__/CERT.cpython-310.pyc | Bin 2789 -> 0 bytes .../ANY/__pycache__/CNAME.cpython-310.pyc | Bin 670 -> 0 bytes .../ANY/__pycache__/CSYNC.cpython-310.pyc | Bin 2112 -> 0 bytes .../ANY/__pycache__/DLV.cpython-310.pyc | Bin 459 -> 0 bytes .../ANY/__pycache__/DNAME.cpython-310.pyc | Bin 668 -> 0 bytes .../ANY/__pycache__/DNSKEY.cpython-310.pyc | Bin 538 -> 0 bytes .../ANY/__pycache__/DS.cpython-310.pyc | Bin 456 -> 0 bytes .../ANY/__pycache__/EUI48.cpython-310.pyc | Bin 523 -> 0 bytes .../ANY/__pycache__/EUI64.cpython-310.pyc | Bin 523 -> 0 bytes .../ANY/__pycache__/GPOS.cpython-310.pyc | Bin 3280 -> 0 bytes .../ANY/__pycache__/HINFO.cpython-310.pyc | Bin 1824 -> 0 bytes .../ANY/__pycache__/HIP.cpython-310.pyc | Bin 2675 -> 0 bytes .../ANY/__pycache__/ISDN.cpython-310.pyc | Bin 2014 -> 0 bytes .../ANY/__pycache__/L32.cpython-310.pyc | Bin 1661 -> 0 bytes .../ANY/__pycache__/L64.cpython-310.pyc | Bin 1866 -> 0 bytes .../ANY/__pycache__/LOC.cpython-310.pyc | Bin 7755 -> 0 bytes .../ANY/__pycache__/LP.cpython-310.pyc | Bin 1647 -> 0 bytes .../ANY/__pycache__/MX.cpython-310.pyc | Bin 456 -> 0 bytes .../ANY/__pycache__/NID.cpython-310.pyc | Bin 1860 -> 0 bytes .../ANY/__pycache__/NINFO.cpython-310.pyc | Bin 468 -> 0 bytes .../ANY/__pycache__/NS.cpython-310.pyc | Bin 456 -> 0 bytes .../ANY/__pycache__/NSEC.cpython-310.pyc | Bin 1983 -> 0 bytes .../ANY/__pycache__/NSEC3.cpython-310.pyc | Bin 3459 -> 0 bytes .../__pycache__/NSEC3PARAM.cpython-310.pyc | Bin 2085 -> 0 bytes .../__pycache__/OPENPGPKEY.cpython-310.pyc | Bin 1653 -> 0 bytes .../ANY/__pycache__/OPT.cpython-310.pyc | Bin 2387 -> 0 bytes .../ANY/__pycache__/PTR.cpython-310.pyc | Bin 459 -> 0 bytes .../ANY/__pycache__/RESINFO.cpython-310.pyc | Bin 474 -> 0 bytes .../ANY/__pycache__/RP.cpython-310.pyc | Bin 1659 -> 0 bytes .../ANY/__pycache__/RRSIG.cpython-310.pyc | Bin 3715 -> 0 bytes .../ANY/__pycache__/RT.cpython-310.pyc | Bin 474 -> 0 bytes .../ANY/__pycache__/SMIMEA.cpython-310.pyc | Bin 474 -> 0 bytes .../ANY/__pycache__/SOA.cpython-310.pyc | Bin 2183 -> 0 bytes .../ANY/__pycache__/SPF.cpython-310.pyc | Bin 462 -> 0 bytes .../ANY/__pycache__/SSHFP.cpython-310.pyc | Bin 1966 -> 0 bytes .../ANY/__pycache__/TKEY.cpython-310.pyc | Bin 2751 -> 0 bytes .../ANY/__pycache__/TLSA.cpython-310.pyc | Bin 468 -> 0 bytes .../ANY/__pycache__/TSIG.cpython-310.pyc | Bin 3229 -> 0 bytes .../ANY/__pycache__/TXT.cpython-310.pyc | Bin 462 -> 0 bytes .../ANY/__pycache__/URI.cpython-310.pyc | Bin 2602 -> 0 bytes .../ANY/__pycache__/WALLET.cpython-310.pyc | Bin 471 -> 0 bytes .../ANY/__pycache__/X25.cpython-310.pyc | Bin 1628 -> 0 bytes .../ANY/__pycache__/ZONEMD.cpython-310.pyc | Bin 2424 -> 0 bytes .../ANY/__pycache__/__init__.cpython-310.pyc | Bin 552 -> 0 bytes venv/Lib/site-packages/dns/rdtypes/CH/A.py | 59 - .../site-packages/dns/rdtypes/CH/__init__.py | 22 - .../rdtypes/CH/__pycache__/A.cpython-310.pyc | Bin 1689 -> 0 bytes .../CH/__pycache__/__init__.cpython-310.pyc | Bin 234 -> 0 bytes venv/Lib/site-packages/dns/rdtypes/IN/A.py | 51 - venv/Lib/site-packages/dns/rdtypes/IN/AAAA.py | 51 - venv/Lib/site-packages/dns/rdtypes/IN/APL.py | 150 - .../Lib/site-packages/dns/rdtypes/IN/DHCID.py | 54 - .../Lib/site-packages/dns/rdtypes/IN/HTTPS.py | 9 - .../site-packages/dns/rdtypes/IN/IPSECKEY.py | 91 - venv/Lib/site-packages/dns/rdtypes/IN/KX.py | 24 - .../Lib/site-packages/dns/rdtypes/IN/NAPTR.py | 110 - venv/Lib/site-packages/dns/rdtypes/IN/NSAP.py | 60 - .../site-packages/dns/rdtypes/IN/NSAP_PTR.py | 24 - venv/Lib/site-packages/dns/rdtypes/IN/PX.py | 73 - venv/Lib/site-packages/dns/rdtypes/IN/SRV.py | 75 - venv/Lib/site-packages/dns/rdtypes/IN/SVCB.py | 9 - venv/Lib/site-packages/dns/rdtypes/IN/WKS.py | 100 - .../site-packages/dns/rdtypes/IN/__init__.py | 35 - .../rdtypes/IN/__pycache__/A.cpython-310.pyc | Bin 1533 -> 0 bytes .../IN/__pycache__/AAAA.cpython-310.pyc | Bin 1557 -> 0 bytes .../IN/__pycache__/APL.cpython-310.pyc | Bin 3762 -> 0 bytes .../IN/__pycache__/DHCID.cpython-310.pyc | Bin 1599 -> 0 bytes .../IN/__pycache__/HTTPS.cpython-310.pyc | Bin 470 -> 0 bytes .../IN/__pycache__/IPSECKEY.cpython-310.pyc | Bin 2469 -> 0 bytes .../rdtypes/IN/__pycache__/KX.cpython-310.pyc | Bin 473 -> 0 bytes .../IN/__pycache__/NAPTR.cpython-310.pyc | Bin 2931 -> 0 bytes .../IN/__pycache__/NSAP.cpython-310.pyc | Bin 1800 -> 0 bytes .../IN/__pycache__/NSAP_PTR.cpython-310.pyc | Bin 481 -> 0 bytes .../rdtypes/IN/__pycache__/PX.cpython-310.pyc | Bin 2213 -> 0 bytes .../IN/__pycache__/SRV.cpython-310.pyc | Bin 2401 -> 0 bytes .../IN/__pycache__/SVCB.cpython-310.pyc | Bin 467 -> 0 bytes .../IN/__pycache__/WKS.cpython-310.pyc | Bin 2634 -> 0 bytes .../IN/__pycache__/__init__.cpython-310.pyc | Bin 318 -> 0 bytes .../Lib/site-packages/dns/rdtypes/__init__.py | 33 - .../__pycache__/__init__.cpython-310.pyc | Bin 317 -> 0 bytes .../__pycache__/dnskeybase.cpython-310.pyc | Bin 2452 -> 0 bytes .../__pycache__/dsbase.cpython-310.pyc | Bin 2489 -> 0 bytes .../__pycache__/euibase.cpython-310.pyc | Bin 2133 -> 0 bytes .../__pycache__/mxbase.cpython-310.pyc | Bin 3103 -> 0 bytes .../__pycache__/nsbase.cpython-310.pyc | Bin 2091 -> 0 bytes .../__pycache__/svcbbase.cpython-310.pyc | Bin 17343 -> 0 bytes .../__pycache__/tlsabase.cpython-310.pyc | Bin 2081 -> 0 bytes .../__pycache__/txtbase.cpython-310.pyc | Bin 3154 -> 0 bytes .../rdtypes/__pycache__/util.cpython-310.pyc | Bin 7165 -> 0 bytes .../site-packages/dns/rdtypes/dnskeybase.py | 87 - venv/Lib/site-packages/dns/rdtypes/dsbase.py | 85 - venv/Lib/site-packages/dns/rdtypes/euibase.py | 70 - venv/Lib/site-packages/dns/rdtypes/mxbase.py | 87 - venv/Lib/site-packages/dns/rdtypes/nsbase.py | 63 - .../Lib/site-packages/dns/rdtypes/svcbbase.py | 585 -- .../Lib/site-packages/dns/rdtypes/tlsabase.py | 71 - venv/Lib/site-packages/dns/rdtypes/txtbase.py | 106 - venv/Lib/site-packages/dns/rdtypes/util.py | 257 - venv/Lib/site-packages/dns/renderer.py | 346 - venv/Lib/site-packages/dns/resolver.py | 2053 ---- venv/Lib/site-packages/dns/reversename.py | 105 - venv/Lib/site-packages/dns/rrset.py | 285 - venv/Lib/site-packages/dns/serial.py | 118 - venv/Lib/site-packages/dns/set.py | 308 - venv/Lib/site-packages/dns/tokenizer.py | 708 -- venv/Lib/site-packages/dns/transaction.py | 649 -- venv/Lib/site-packages/dns/tsig.py | 352 - venv/Lib/site-packages/dns/tsigkeyring.py | 68 - venv/Lib/site-packages/dns/ttl.py | 92 - venv/Lib/site-packages/dns/update.py | 386 - venv/Lib/site-packages/dns/version.py | 58 - venv/Lib/site-packages/dns/versioned.py | 318 - venv/Lib/site-packages/dns/win32util.py | 242 - venv/Lib/site-packages/dns/wire.py | 89 - venv/Lib/site-packages/dns/xfr.py | 343 - venv/Lib/site-packages/dns/zone.py | 1434 --- venv/Lib/site-packages/dns/zonefile.py | 744 -- venv/Lib/site-packages/dns/zonetypes.py | 37 - .../dnspython-2.7.0.dist-info/INSTALLER | 1 - .../dnspython-2.7.0.dist-info/METADATA | 149 - .../dnspython-2.7.0.dist-info/RECORD | 294 - .../dnspython-2.7.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 35 - .../docutils-0.21.2.dist-info/COPYING.txt | 159 - .../docutils-0.21.2.dist-info/INSTALLER | 1 - .../docutils-0.21.2.dist-info/METADATA | 63 - .../docutils-0.21.2.dist-info/RECORD | 347 - .../docutils-0.21.2.dist-info/WHEEL | 4 - .../entry_points.txt | 13 - venv/Lib/site-packages/docutils/__init__.py | 291 - venv/Lib/site-packages/docutils/__main__.py | 96 - .../__pycache__/__init__.cpython-310.pyc | Bin 5459 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 2605 -> 0 bytes .../docutils/__pycache__/core.cpython-310.pyc | Bin 24899 -> 0 bytes .../__pycache__/examples.cpython-310.pyc | Bin 3463 -> 0 bytes .../__pycache__/frontend.cpython-310.pyc | Bin 32420 -> 0 bytes .../docutils/__pycache__/io.cpython-310.pyc | Bin 18064 -> 0 bytes .../__pycache__/nodes.cpython-310.pyc | Bin 79996 -> 0 bytes .../__pycache__/statemachine.cpython-310.pyc | Bin 48739 -> 0 bytes venv/Lib/site-packages/docutils/core.py | 780 -- venv/Lib/site-packages/docutils/docutils.conf | 5 - venv/Lib/site-packages/docutils/examples.py | 99 - venv/Lib/site-packages/docutils/frontend.py | 1065 -- venv/Lib/site-packages/docutils/io.py | 637 -- .../docutils/languages/__init__.py | 83 - .../__pycache__/__init__.cpython-310.pyc | Bin 2444 -> 0 bytes .../languages/__pycache__/af.cpython-310.pyc | Bin 1135 -> 0 bytes .../languages/__pycache__/ar.cpython-310.pyc | Bin 1258 -> 0 bytes .../languages/__pycache__/ca.cpython-310.pyc | Bin 1178 -> 0 bytes .../languages/__pycache__/cs.cpython-310.pyc | Bin 1157 -> 0 bytes .../languages/__pycache__/da.cpython-310.pyc | Bin 1157 -> 0 bytes .../languages/__pycache__/de.cpython-310.pyc | Bin 1139 -> 0 bytes .../languages/__pycache__/en.cpython-310.pyc | Bin 1090 -> 0 bytes .../languages/__pycache__/eo.cpython-310.pyc | Bin 1150 -> 0 bytes .../languages/__pycache__/es.cpython-310.pyc | Bin 1212 -> 0 bytes .../languages/__pycache__/fa.cpython-310.pyc | Bin 1241 -> 0 bytes .../languages/__pycache__/fi.cpython-310.pyc | Bin 1227 -> 0 bytes .../languages/__pycache__/fr.cpython-310.pyc | Bin 1160 -> 0 bytes .../languages/__pycache__/gl.cpython-310.pyc | Bin 1202 -> 0 bytes .../languages/__pycache__/he.cpython-310.pyc | Bin 1225 -> 0 bytes .../languages/__pycache__/it.cpython-310.pyc | Bin 1162 -> 0 bytes .../languages/__pycache__/ja.cpython-310.pyc | Bin 1165 -> 0 bytes .../languages/__pycache__/ka.cpython-310.pyc | Bin 1580 -> 0 bytes .../languages/__pycache__/ko.cpython-310.pyc | Bin 1149 -> 0 bytes .../languages/__pycache__/lt.cpython-310.pyc | Bin 1218 -> 0 bytes .../languages/__pycache__/lv.cpython-310.pyc | Bin 1226 -> 0 bytes .../languages/__pycache__/nl.cpython-310.pyc | Bin 1136 -> 0 bytes .../languages/__pycache__/pl.cpython-310.pyc | Bin 1173 -> 0 bytes .../__pycache__/pt_br.cpython-310.pyc | Bin 1189 -> 0 bytes .../languages/__pycache__/ru.cpython-310.pyc | Bin 1555 -> 0 bytes .../languages/__pycache__/sk.cpython-310.pyc | Bin 1170 -> 0 bytes .../languages/__pycache__/sv.cpython-310.pyc | Bin 1140 -> 0 bytes .../languages/__pycache__/uk.cpython-310.pyc | Bin 1541 -> 0 bytes .../__pycache__/zh_cn.cpython-310.pyc | Bin 1180 -> 0 bytes .../__pycache__/zh_tw.cpython-310.pyc | Bin 1506 -> 0 bytes .../site-packages/docutils/languages/af.py | 58 - .../site-packages/docutils/languages/ar.py | 60 - .../site-packages/docutils/languages/ca.py | 65 - .../site-packages/docutils/languages/cs.py | 60 - .../site-packages/docutils/languages/da.py | 61 - .../site-packages/docutils/languages/de.py | 58 - .../site-packages/docutils/languages/en.py | 60 - .../site-packages/docutils/languages/eo.py | 61 - .../site-packages/docutils/languages/es.py | 58 - .../site-packages/docutils/languages/fa.py | 60 - .../site-packages/docutils/languages/fi.py | 60 - .../site-packages/docutils/languages/fr.py | 58 - .../site-packages/docutils/languages/gl.py | 62 - .../site-packages/docutils/languages/he.py | 62 - .../site-packages/docutils/languages/it.py | 58 - .../site-packages/docutils/languages/ja.py | 60 - .../site-packages/docutils/languages/ka.py | 58 - .../site-packages/docutils/languages/ko.py | 60 - .../site-packages/docutils/languages/lt.py | 60 - .../site-packages/docutils/languages/lv.py | 59 - .../site-packages/docutils/languages/nl.py | 60 - .../site-packages/docutils/languages/pl.py | 60 - .../site-packages/docutils/languages/pt_br.py | 60 - .../site-packages/docutils/languages/ru.py | 58 - .../site-packages/docutils/languages/sk.py | 58 - .../site-packages/docutils/languages/sv.py | 59 - .../site-packages/docutils/languages/uk.py | 58 - .../site-packages/docutils/languages/zh_cn.py | 62 - .../site-packages/docutils/languages/zh_tw.py | 61 - venv/Lib/site-packages/docutils/nodes.py | 2301 ----- .../docutils/parsers/__init__.py | 92 - .../__pycache__/__init__.cpython-310.pyc | Bin 2964 -> 0 bytes .../commonmark_wrapper.cpython-310.pyc | Bin 1166 -> 0 bytes .../parsers/__pycache__/null.cpython-310.pyc | Bin 655 -> 0 bytes .../recommonmark_wrapper.cpython-310.pyc | Bin 3896 -> 0 bytes .../docutils/parsers/commonmark_wrapper.py | 56 - .../site-packages/docutils/parsers/null.py | 20 - .../docutils/parsers/recommonmark_wrapper.py | 147 - .../docutils/parsers/rst/__init__.py | 413 - .../rst/__pycache__/__init__.cpython-310.pyc | Bin 14762 -> 0 bytes .../rst/__pycache__/roles.cpython-310.pyc | Bin 11848 -> 0 bytes .../rst/__pycache__/states.cpython-310.pyc | Bin 91700 -> 0 bytes .../__pycache__/tableparser.cpython-310.pyc | Bin 17581 -> 0 bytes .../parsers/rst/directives/__init__.py | 466 - .../__pycache__/__init__.cpython-310.pyc | Bin 13511 -> 0 bytes .../__pycache__/admonitions.cpython-310.pyc | Bin 2943 -> 0 bytes .../__pycache__/body.cpython-310.pyc | Bin 8093 -> 0 bytes .../__pycache__/html.cpython-310.pyc | Bin 694 -> 0 bytes .../__pycache__/images.cpython-310.pyc | Bin 5120 -> 0 bytes .../__pycache__/misc.cpython-310.pyc | Bin 16872 -> 0 bytes .../__pycache__/parts.cpython-310.pyc | Bin 3834 -> 0 bytes .../__pycache__/references.cpython-310.pyc | Bin 1018 -> 0 bytes .../__pycache__/tables.cpython-310.pyc | Bin 15522 -> 0 bytes .../parsers/rst/directives/admonitions.py | 101 - .../docutils/parsers/rst/directives/body.py | 305 - .../docutils/parsers/rst/directives/html.py | 21 - .../docutils/parsers/rst/directives/images.py | 173 - .../docutils/parsers/rst/directives/misc.py | 642 -- .../docutils/parsers/rst/directives/parts.py | 126 - .../parsers/rst/directives/references.py | 29 - .../docutils/parsers/rst/directives/tables.py | 538 - .../docutils/parsers/rst/include/README.txt | 17 - .../docutils/parsers/rst/include/isoamsa.txt | 162 - .../docutils/parsers/rst/include/isoamsb.txt | 126 - .../docutils/parsers/rst/include/isoamsc.txt | 29 - .../docutils/parsers/rst/include/isoamsn.txt | 96 - .../docutils/parsers/rst/include/isoamso.txt | 62 - .../docutils/parsers/rst/include/isoamsr.txt | 191 - .../docutils/parsers/rst/include/isobox.txt | 46 - .../docutils/parsers/rst/include/isocyr1.txt | 73 - .../docutils/parsers/rst/include/isocyr2.txt | 32 - .../docutils/parsers/rst/include/isodia.txt | 20 - .../docutils/parsers/rst/include/isogrk1.txt | 55 - .../docutils/parsers/rst/include/isogrk2.txt | 26 - .../docutils/parsers/rst/include/isogrk3.txt | 52 - .../parsers/rst/include/isogrk4-wide.txt | 49 - .../docutils/parsers/rst/include/isogrk4.txt | 8 - .../docutils/parsers/rst/include/isolat1.txt | 68 - .../docutils/parsers/rst/include/isolat2.txt | 128 - .../parsers/rst/include/isomfrk-wide.txt | 58 - .../docutils/parsers/rst/include/isomfrk.txt | 11 - .../parsers/rst/include/isomopf-wide.txt | 32 - .../docutils/parsers/rst/include/isomopf.txt | 13 - .../parsers/rst/include/isomscr-wide.txt | 58 - .../docutils/parsers/rst/include/isomscr.txt | 17 - .../docutils/parsers/rst/include/isonum.txt | 82 - .../docutils/parsers/rst/include/isopub.txt | 90 - .../docutils/parsers/rst/include/isotech.txt | 168 - .../docutils/parsers/rst/include/mmlalias.txt | 554 -- .../parsers/rst/include/mmlextra-wide.txt | 113 - .../docutils/parsers/rst/include/mmlextra.txt | 87 - .../docutils/parsers/rst/include/s5defs.txt | 68 - .../parsers/rst/include/xhtml1-lat1.txt | 102 - .../parsers/rst/include/xhtml1-special.txt | 37 - .../parsers/rst/include/xhtml1-symbol.txt | 130 - .../parsers/rst/languages/__init__.py | 40 - .../__pycache__/__init__.cpython-310.pyc | Bin 1311 -> 0 bytes .../languages/__pycache__/af.cpython-310.pyc | Bin 2690 -> 0 bytes .../languages/__pycache__/ar.cpython-310.pyc | Bin 2605 -> 0 bytes .../languages/__pycache__/ca.cpython-310.pyc | Bin 3137 -> 0 bytes .../languages/__pycache__/cs.cpython-310.pyc | Bin 3716 -> 0 bytes .../languages/__pycache__/da.cpython-310.pyc | Bin 2713 -> 0 bytes .../languages/__pycache__/de.cpython-310.pyc | Bin 2502 -> 0 bytes .../languages/__pycache__/en.cpython-310.pyc | Bin 1850 -> 0 bytes .../languages/__pycache__/eo.cpython-310.pyc | Bin 2795 -> 0 bytes .../languages/__pycache__/es.cpython-310.pyc | Bin 3009 -> 0 bytes .../languages/__pycache__/fa.cpython-310.pyc | Bin 2704 -> 0 bytes .../languages/__pycache__/fi.cpython-310.pyc | Bin 2710 -> 0 bytes .../languages/__pycache__/fr.cpython-310.pyc | Bin 2577 -> 0 bytes .../languages/__pycache__/gl.cpython-310.pyc | Bin 2569 -> 0 bytes .../languages/__pycache__/he.cpython-310.pyc | Bin 2063 -> 0 bytes .../languages/__pycache__/it.cpython-310.pyc | Bin 2465 -> 0 bytes .../languages/__pycache__/ja.cpython-310.pyc | Bin 2931 -> 0 bytes .../languages/__pycache__/ka.cpython-310.pyc | Bin 3835 -> 0 bytes .../languages/__pycache__/ko.cpython-310.pyc | Bin 2629 -> 0 bytes .../languages/__pycache__/lt.cpython-310.pyc | Bin 2639 -> 0 bytes .../languages/__pycache__/lv.cpython-310.pyc | Bin 2596 -> 0 bytes .../languages/__pycache__/nl.cpython-310.pyc | Bin 2710 -> 0 bytes .../languages/__pycache__/pl.cpython-310.pyc | Bin 2420 -> 0 bytes .../__pycache__/pt_br.cpython-310.pyc | Bin 2839 -> 0 bytes .../languages/__pycache__/ru.cpython-310.pyc | Bin 3137 -> 0 bytes .../languages/__pycache__/sk.cpython-310.pyc | Bin 3141 -> 0 bytes .../languages/__pycache__/sv.cpython-310.pyc | Bin 2275 -> 0 bytes .../languages/__pycache__/uk.cpython-310.pyc | Bin 3234 -> 0 bytes .../__pycache__/zh_cn.cpython-310.pyc | Bin 3007 -> 0 bytes .../__pycache__/zh_tw.cpython-310.pyc | Bin 3986 -> 0 bytes .../docutils/parsers/rst/languages/af.py | 108 - .../docutils/parsers/rst/languages/ar.py | 99 - .../docutils/parsers/rst/languages/ca.py | 130 - .../docutils/parsers/rst/languages/cs.py | 110 - .../docutils/parsers/rst/languages/da.py | 114 - .../docutils/parsers/rst/languages/de.py | 107 - .../docutils/parsers/rst/languages/en.py | 114 - .../docutils/parsers/rst/languages/eo.py | 119 - .../docutils/parsers/rst/languages/es.py | 123 - .../docutils/parsers/rst/languages/fa.py | 102 - .../docutils/parsers/rst/languages/fi.py | 98 - .../docutils/parsers/rst/languages/fr.py | 108 - .../docutils/parsers/rst/languages/gl.py | 106 - .../docutils/parsers/rst/languages/he.py | 110 - .../docutils/parsers/rst/languages/it.py | 99 - .../docutils/parsers/rst/languages/ja.py | 119 - .../docutils/parsers/rst/languages/ka.py | 90 - .../docutils/parsers/rst/languages/ko.py | 111 - .../docutils/parsers/rst/languages/lt.py | 109 - .../docutils/parsers/rst/languages/lv.py | 108 - .../docutils/parsers/rst/languages/nl.py | 114 - .../docutils/parsers/rst/languages/pl.py | 101 - .../docutils/parsers/rst/languages/pt_br.py | 110 - .../docutils/parsers/rst/languages/ru.py | 90 - .../docutils/parsers/rst/languages/sk.py | 96 - .../docutils/parsers/rst/languages/sv.py | 96 - .../docutils/parsers/rst/languages/uk.py | 91 - .../docutils/parsers/rst/languages/zh_cn.py | 104 - .../docutils/parsers/rst/languages/zh_tw.py | 109 - .../docutils/parsers/rst/roles.py | 439 - .../docutils/parsers/rst/states.py | 3145 ------ .../docutils/parsers/rst/tableparser.py | 539 - .../docutils/readers/__init__.py | 113 - .../__pycache__/__init__.cpython-310.pyc | Bin 3448 -> 0 bytes .../__pycache__/doctree.cpython-310.pyc | Bin 1519 -> 0 bytes .../readers/__pycache__/pep.cpython-310.pyc | Bin 1630 -> 0 bytes .../__pycache__/standalone.cpython-310.pyc | Bin 1984 -> 0 bytes .../site-packages/docutils/readers/doctree.py | 46 - .../Lib/site-packages/docutils/readers/pep.py | 48 - .../docutils/readers/standalone.py | 65 - .../site-packages/docutils/statemachine.py | 1525 --- .../docutils/transforms/__init__.py | 185 - .../__pycache__/__init__.cpython-310.pyc | Bin 5757 -> 0 bytes .../__pycache__/components.cpython-310.pyc | Bin 2149 -> 0 bytes .../__pycache__/frontmatter.cpython-310.pyc | Bin 16527 -> 0 bytes .../__pycache__/misc.cpython-310.pyc | Bin 3759 -> 0 bytes .../__pycache__/parts.cpython-310.pyc | Bin 5925 -> 0 bytes .../__pycache__/peps.cpython-310.pyc | Bin 9025 -> 0 bytes .../__pycache__/references.cpython-310.pyc | Bin 24556 -> 0 bytes .../__pycache__/universal.cpython-310.pyc | Bin 9240 -> 0 bytes .../__pycache__/writer_aux.cpython-310.pyc | Bin 2968 -> 0 bytes .../docutils/transforms/components.py | 54 - .../docutils/transforms/frontmatter.py | 540 - .../site-packages/docutils/transforms/misc.py | 144 - .../docutils/transforms/parts.py | 176 - .../site-packages/docutils/transforms/peps.py | 308 - .../docutils/transforms/references.py | 924 -- .../docutils/transforms/universal.py | 335 - .../docutils/transforms/writer_aux.py | 99 - .../site-packages/docutils/utils/__init__.py | 861 -- .../__pycache__/__init__.cpython-310.pyc | Bin 26664 -> 0 bytes .../__pycache__/code_analyzer.cpython-310.pyc | Bin 4148 -> 0 bytes .../error_reporting.cpython-310.pyc | Bin 6651 -> 0 bytes .../punctuation_chars.cpython-310.pyc | Bin 3152 -> 0 bytes .../utils/__pycache__/roman.cpython-310.pyc | Bin 3700 -> 0 bytes .../__pycache__/smartquotes.cpython-310.pyc | Bin 29081 -> 0 bytes .../__pycache__/urischemes.cpython-310.pyc | Bin 5860 -> 0 bytes .../docutils/utils/code_analyzer.py | 136 - .../docutils/utils/error_reporting.py | 222 - .../docutils/utils/math/__init__.py | 73 - .../math/__pycache__/__init__.cpython-310.pyc | Bin 2473 -> 0 bytes .../__pycache__/latex2mathml.cpython-310.pyc | Bin 19254 -> 0 bytes .../__pycache__/math2html.cpython-310.pyc | Bin 106059 -> 0 bytes .../mathalphabet2unichar.cpython-310.pyc | Bin 18302 -> 0 bytes .../mathml_elements.cpython-310.pyc | Bin 14638 -> 0 bytes .../tex2mathml_extern.cpython-310.pyc | Bin 5609 -> 0 bytes .../__pycache__/tex2unichar.cpython-310.pyc | Bin 20545 -> 0 bytes .../__pycache__/unichar2tex.cpython-310.pyc | Bin 32211 -> 0 bytes .../docutils/utils/math/latex2mathml.py | 1252 --- .../docutils/utils/math/math2html.py | 3165 ------ .../utils/math/mathalphabet2unichar.py | 892 -- .../docutils/utils/math/mathml_elements.py | 478 - .../docutils/utils/math/tex2mathml_extern.py | 261 - .../docutils/utils/math/tex2unichar.py | 730 -- .../docutils/utils/math/unichar2tex.py | 808 -- .../docutils/utils/punctuation_chars.py | 123 - .../Lib/site-packages/docutils/utils/roman.py | 154 - .../docutils/utils/smartquotes.py | 1004 -- .../docutils/utils/urischemes.py | 138 - .../docutils/writers/__init__.py | 159 - .../__pycache__/__init__.cpython-310.pyc | Bin 4529 -> 0 bytes .../__pycache__/_html_base.cpython-310.pyc | Bin 63532 -> 0 bytes .../__pycache__/docutils_xml.cpython-310.pyc | Bin 5547 -> 0 bytes .../__pycache__/manpage.cpython-310.pyc | Bin 40678 -> 0 bytes .../writers/__pycache__/null.cpython-310.pyc | Bin 727 -> 0 bytes .../__pycache__/pseudoxml.cpython-310.pyc | Bin 1183 -> 0 bytes .../docutils/writers/_html_base.py | 1887 ---- .../docutils/writers/docutils_xml.py | 187 - .../docutils/writers/html4css1/__init__.py | 955 -- .../__pycache__/__init__.cpython-310.pyc | Bin 32158 -> 0 bytes .../docutils/writers/html4css1/html4css1.css | 350 - .../docutils/writers/html4css1/template.txt | 8 - .../writers/html5_polyglot/__init__.py | 393 - .../__pycache__/__init__.cpython-310.pyc | Bin 13085 -> 0 bytes .../html5_polyglot/italic-field-names.css | 26 - .../docutils/writers/html5_polyglot/math.css | 332 - .../writers/html5_polyglot/minimal.css | 293 - .../docutils/writers/html5_polyglot/plain.css | 307 - .../writers/html5_polyglot/responsive.css | 486 - .../writers/html5_polyglot/template.txt | 8 - .../writers/html5_polyglot/tuftig.css | 566 -- .../docutils/writers/latex2e/__init__.py | 3323 ------- .../__pycache__/__init__.cpython-310.pyc | Bin 94654 -> 0 bytes .../docutils/writers/latex2e/default.tex | 14 - .../docutils/writers/latex2e/docutils.sty | 223 - .../docutils/writers/latex2e/titlepage.tex | 19 - .../docutils/writers/latex2e/titlingpage.tex | 18 - .../docutils/writers/latex2e/xelatex.tex | 21 - .../site-packages/docutils/writers/manpage.py | 1214 --- .../site-packages/docutils/writers/null.py | 25 - .../docutils/writers/odf_odt/__init__.py | 3461 ------- .../__pycache__/__init__.cpython-310.pyc | Bin 92320 -> 0 bytes .../__pycache__/prepstyles.cpython-310.pyc | Bin 1937 -> 0 bytes .../pygmentsformatter.cpython-310.pyc | Bin 2814 -> 0 bytes .../docutils/writers/odf_odt/prepstyles.py | 78 - .../writers/odf_odt/pygmentsformatter.py | 109 - .../docutils/writers/odf_odt/styles.odt | Bin 16500 -> 0 bytes .../docutils/writers/pep_html/__init__.py | 101 - .../__pycache__/__init__.cpython-310.pyc | Bin 3286 -> 0 bytes .../docutils/writers/pep_html/pep.css | 344 - .../docutils/writers/pep_html/template.txt | 25 - .../docutils/writers/pseudoxml.py | 40 - .../docutils/writers/s5_html/__init__.py | 353 - .../__pycache__/__init__.cpython-310.pyc | Bin 10721 -> 0 bytes .../writers/s5_html/themes/README.txt | 6 - .../writers/s5_html/themes/big-black/__base__ | 2 - .../s5_html/themes/big-black/framing.css | 25 - .../s5_html/themes/big-black/pretty.css | 109 - .../s5_html/themes/big-white/framing.css | 24 - .../s5_html/themes/big-white/pretty.css | 107 - .../s5_html/themes/default/framing.css | 25 - .../writers/s5_html/themes/default/opera.css | 8 - .../s5_html/themes/default/outline.css | 16 - .../writers/s5_html/themes/default/pretty.css | 120 - .../writers/s5_html/themes/default/print.css | 24 - .../s5_html/themes/default/s5-core.css | 11 - .../writers/s5_html/themes/default/slides.css | 10 - .../writers/s5_html/themes/default/slides.js | 558 -- .../s5_html/themes/medium-black/__base__ | 2 - .../s5_html/themes/medium-black/pretty.css | 115 - .../s5_html/themes/medium-white/framing.css | 24 - .../s5_html/themes/medium-white/pretty.css | 113 - .../s5_html/themes/small-black/__base__ | 2 - .../s5_html/themes/small-black/pretty.css | 116 - .../s5_html/themes/small-white/framing.css | 24 - .../s5_html/themes/small-white/pretty.css | 114 - .../docutils/writers/xetex/__init__.py | 147 - .../__pycache__/__init__.cpython-310.pyc | Bin 4083 -> 0 bytes venv/Lib/site-packages/dotenv/__init__.py | 49 - venv/Lib/site-packages/dotenv/__main__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 1246 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 313 -> 0 bytes .../dotenv/__pycache__/cli.cpython-310.pyc | Bin 5982 -> 0 bytes .../__pycache__/ipython.cpython-310.pyc | Bin 1471 -> 0 bytes .../dotenv/__pycache__/main.cpython-310.pyc | Bin 10611 -> 0 bytes .../dotenv/__pycache__/parser.cpython-310.pyc | Bin 6140 -> 0 bytes .../__pycache__/variables.cpython-310.pyc | Bin 3529 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 184 -> 0 bytes venv/Lib/site-packages/dotenv/cli.py | 190 - venv/Lib/site-packages/dotenv/ipython.py | 39 - venv/Lib/site-packages/dotenv/main.py | 398 - venv/Lib/site-packages/dotenv/parser.py | 175 - venv/Lib/site-packages/dotenv/py.typed | 1 - venv/Lib/site-packages/dotenv/variables.py | 86 - venv/Lib/site-packages/dotenv/version.py | 1 - .../flask-3.1.0.dist-info/INSTALLER | 1 - .../flask-3.1.0.dist-info/LICENSE.txt | 28 - .../flask-3.1.0.dist-info/METADATA | 81 - .../flask-3.1.0.dist-info/RECORD | 58 - .../flask-3.1.0.dist-info/REQUESTED | 0 .../site-packages/flask-3.1.0.dist-info/WHEEL | 4 - .../flask-3.1.0.dist-info/entry_points.txt | 3 - venv/Lib/site-packages/flask/__init__.py | 60 - venv/Lib/site-packages/flask/__main__.py | 3 - .../__pycache__/__init__.cpython-310.pyc | Bin 2278 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 203 -> 0 bytes .../flask/__pycache__/app.cpython-310.pyc | Bin 50874 -> 0 bytes .../__pycache__/blueprints.cpython-310.pyc | Bin 4158 -> 0 bytes .../flask/__pycache__/cli.cpython-310.pyc | Bin 29905 -> 0 bytes .../flask/__pycache__/config.cpython-310.pyc | Bin 13396 -> 0 bytes .../flask/__pycache__/ctx.cpython-310.pyc | Bin 14844 -> 0 bytes .../__pycache__/debughelpers.cpython-310.pyc | Bin 6582 -> 0 bytes .../flask/__pycache__/globals.cpython-310.pyc | Bin 1571 -> 0 bytes .../flask/__pycache__/helpers.cpython-310.pyc | Bin 22093 -> 0 bytes .../flask/__pycache__/logging.cpython-310.pyc | Bin 2538 -> 0 bytes .../__pycache__/sessions.cpython-310.pyc | Bin 14234 -> 0 bytes .../flask/__pycache__/signals.cpython-310.pyc | Bin 801 -> 0 bytes .../__pycache__/templating.cpython-310.pyc | Bin 7075 -> 0 bytes .../flask/__pycache__/testing.cpython-310.pyc | Bin 9795 -> 0 bytes .../flask/__pycache__/typing.cpython-310.pyc | Bin 1801 -> 0 bytes .../flask/__pycache__/views.cpython-310.pyc | Bin 5539 -> 0 bytes .../__pycache__/wrappers.cpython-310.pyc | Bin 8381 -> 0 bytes venv/Lib/site-packages/flask/app.py | 1536 --- venv/Lib/site-packages/flask/blueprints.py | 128 - venv/Lib/site-packages/flask/cli.py | 1133 --- venv/Lib/site-packages/flask/config.py | 367 - venv/Lib/site-packages/flask/ctx.py | 449 - venv/Lib/site-packages/flask/debughelpers.py | 178 - venv/Lib/site-packages/flask/globals.py | 51 - venv/Lib/site-packages/flask/helpers.py | 634 -- venv/Lib/site-packages/flask/json/__init__.py | 170 - .../json/__pycache__/__init__.cpython-310.pyc | Bin 5985 -> 0 bytes .../json/__pycache__/provider.cpython-310.pyc | Bin 7677 -> 0 bytes .../json/__pycache__/tag.cpython-310.pyc | Bin 11635 -> 0 bytes venv/Lib/site-packages/flask/json/provider.py | 215 - venv/Lib/site-packages/flask/json/tag.py | 327 - venv/Lib/site-packages/flask/logging.py | 79 - venv/Lib/site-packages/flask/py.typed | 0 venv/Lib/site-packages/flask/sansio/README.md | 6 - .../sansio/__pycache__/app.cpython-310.pyc | Bin 28634 -> 0 bytes .../__pycache__/blueprints.cpython-310.pyc | Bin 22924 -> 0 bytes .../__pycache__/scaffold.cpython-310.pyc | Bin 23841 -> 0 bytes venv/Lib/site-packages/flask/sansio/app.py | 964 -- .../site-packages/flask/sansio/blueprints.py | 632 -- .../site-packages/flask/sansio/scaffold.py | 792 -- venv/Lib/site-packages/flask/sessions.py | 398 - venv/Lib/site-packages/flask/signals.py | 17 - venv/Lib/site-packages/flask/templating.py | 219 - venv/Lib/site-packages/flask/testing.py | 297 - venv/Lib/site-packages/flask/typing.py | 90 - venv/Lib/site-packages/flask/views.py | 191 - venv/Lib/site-packages/flask/wrappers.py | 257 - venv/Lib/site-packages/gridfs/__init__.py | 54 - .../__pycache__/__init__.cpython-310.pyc | Bin 1002 -> 0 bytes .../gridfs/__pycache__/errors.cpython-310.pyc | Bin 1042 -> 0 bytes .../__pycache__/grid_file.cpython-310.pyc | Bin 327 -> 0 bytes .../grid_file_shared.cpython-310.pyc | Bin 4331 -> 0 bytes .../gridfs/asynchronous/__init__.py | 42 - .../__pycache__/__init__.cpython-310.pyc | Bin 849 -> 0 bytes .../__pycache__/grid_file.cpython-310.pyc | Bin 69106 -> 0 bytes .../gridfs/asynchronous/grid_file.py | 2008 ---- venv/Lib/site-packages/gridfs/errors.py | 34 - venv/Lib/site-packages/gridfs/grid_file.py | 18 - .../site-packages/gridfs/grid_file_shared.py | 168 - venv/Lib/site-packages/gridfs/py.typed | 2 - .../__pycache__/grid_file.cpython-310.pyc | Bin 67449 -> 0 bytes .../gridfs/synchronous/grid_file.py | 1994 ---- .../gunicorn-23.0.0.dist-info/INSTALLER | 1 - .../gunicorn-23.0.0.dist-info/LICENSE | 23 - .../gunicorn-23.0.0.dist-info/METADATA | 130 - .../gunicorn-23.0.0.dist-info/RECORD | 77 - .../gunicorn-23.0.0.dist-info/REQUESTED | 0 .../gunicorn-23.0.0.dist-info/WHEEL | 5 - .../entry_points.txt | 5 - .../gunicorn-23.0.0.dist-info/top_level.txt | 1 - venv/Lib/site-packages/gunicorn/__init__.py | 8 - venv/Lib/site-packages/gunicorn/__main__.py | 10 - .../__pycache__/__init__.cpython-310.pyc | Bin 418 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 280 -> 0 bytes .../__pycache__/arbiter.cpython-310.pyc | Bin 17332 -> 0 bytes .../__pycache__/config.cpython-310.pyc | Bin 70412 -> 0 bytes .../__pycache__/debug.cpython-310.pyc | Bin 1985 -> 0 bytes .../__pycache__/errors.cpython-310.pyc | Bin 1027 -> 0 bytes .../__pycache__/glogging.cpython-310.pyc | Bin 11403 -> 0 bytes .../__pycache__/pidfile.cpython-310.pyc | Bin 2406 -> 0 bytes .../__pycache__/reloader.cpython-310.pyc | Bin 3948 -> 0 bytes .../gunicorn/__pycache__/sock.cpython-310.pyc | Bin 7028 -> 0 bytes .../__pycache__/systemd.cpython-310.pyc | Bin 2490 -> 0 bytes .../gunicorn/__pycache__/util.cpython-310.pyc | Bin 13987 -> 0 bytes .../site-packages/gunicorn/app/__init__.py | 3 - .../app/__pycache__/__init__.cpython-310.pyc | Bin 170 -> 0 bytes .../app/__pycache__/base.cpython-310.pyc | Bin 6573 -> 0 bytes .../app/__pycache__/pasterapp.cpython-310.pyc | Bin 2147 -> 0 bytes .../app/__pycache__/wsgiapp.cpython-310.pyc | Bin 2239 -> 0 bytes venv/Lib/site-packages/gunicorn/app/base.py | 235 - .../site-packages/gunicorn/app/pasterapp.py | 74 - .../Lib/site-packages/gunicorn/app/wsgiapp.py | 70 - venv/Lib/site-packages/gunicorn/arbiter.py | 671 -- venv/Lib/site-packages/gunicorn/config.py | 2442 ----- venv/Lib/site-packages/gunicorn/debug.py | 68 - venv/Lib/site-packages/gunicorn/errors.py | 28 - venv/Lib/site-packages/gunicorn/glogging.py | 473 - .../site-packages/gunicorn/http/__init__.py | 8 - .../http/__pycache__/__init__.cpython-310.pyc | Bin 336 -> 0 bytes .../http/__pycache__/body.cpython-310.pyc | Bin 6658 -> 0 bytes .../http/__pycache__/errors.cpython-310.pyc | Bin 6338 -> 0 bytes .../http/__pycache__/message.cpython-310.pyc | Bin 9736 -> 0 bytes .../http/__pycache__/parser.cpython-310.pyc | Bin 1380 -> 0 bytes .../http/__pycache__/unreader.cpython-310.pyc | Bin 2407 -> 0 bytes .../http/__pycache__/wsgi.cpython-310.pyc | Bin 9169 -> 0 bytes venv/Lib/site-packages/gunicorn/http/body.py | 268 - .../Lib/site-packages/gunicorn/http/errors.py | 145 - .../site-packages/gunicorn/http/message.py | 463 - .../Lib/site-packages/gunicorn/http/parser.py | 51 - .../site-packages/gunicorn/http/unreader.py | 78 - venv/Lib/site-packages/gunicorn/http/wsgi.py | 401 - .../gunicorn/instrument/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 177 -> 0 bytes .../__pycache__/statsd.cpython-310.pyc | Bin 4280 -> 0 bytes .../gunicorn/instrument/statsd.py | 134 - venv/Lib/site-packages/gunicorn/pidfile.py | 85 - venv/Lib/site-packages/gunicorn/reloader.py | 131 - venv/Lib/site-packages/gunicorn/sock.py | 231 - venv/Lib/site-packages/gunicorn/systemd.py | 75 - venv/Lib/site-packages/gunicorn/util.py | 653 -- .../gunicorn/workers/__init__.py | 14 - .../__pycache__/__init__.cpython-310.pyc | Bin 537 -> 0 bytes .../workers/__pycache__/base.cpython-310.pyc | Bin 7825 -> 0 bytes .../__pycache__/base_async.cpython-310.pyc | Bin 4207 -> 0 bytes .../__pycache__/geventlet.cpython-310.pyc | Bin 5008 -> 0 bytes .../__pycache__/ggevent.cpython-310.pyc | Bin 5709 -> 0 bytes .../__pycache__/gthread.cpython-310.pyc | Bin 9463 -> 0 bytes .../__pycache__/gtornado.cpython-310.pyc | Bin 4428 -> 0 bytes .../workers/__pycache__/sync.cpython-310.pyc | Bin 5438 -> 0 bytes .../__pycache__/workertmp.cpython-310.pyc | Bin 1709 -> 0 bytes .../site-packages/gunicorn/workers/base.py | 287 - .../gunicorn/workers/base_async.py | 147 - .../gunicorn/workers/geventlet.py | 186 - .../site-packages/gunicorn/workers/ggevent.py | 193 - .../site-packages/gunicorn/workers/gthread.py | 372 - .../gunicorn/workers/gtornado.py | 166 - .../site-packages/gunicorn/workers/sync.py | 209 - .../gunicorn/workers/workertmp.py | 53 - .../idna-3.10.dist-info/INSTALLER | 1 - .../idna-3.10.dist-info/LICENSE.md | 31 - .../idna-3.10.dist-info/METADATA | 250 - .../site-packages/idna-3.10.dist-info/RECORD | 22 - .../site-packages/idna-3.10.dist-info/WHEEL | 4 - venv/Lib/site-packages/idna/__init__.py | 45 - .../idna/__pycache__/__init__.cpython-310.pyc | Bin 826 -> 0 bytes .../idna/__pycache__/codec.cpython-310.pyc | Bin 3247 -> 0 bytes .../idna/__pycache__/compat.cpython-310.pyc | Bin 729 -> 0 bytes .../idna/__pycache__/core.cpython-310.pyc | Bin 9681 -> 0 bytes .../idna/__pycache__/idnadata.cpython-310.pyc | Bin 194422 -> 0 bytes .../__pycache__/intranges.cpython-310.pyc | Bin 1958 -> 0 bytes .../__pycache__/package_data.cpython-310.pyc | Bin 186 -> 0 bytes .../__pycache__/uts46data.cpython-310.pyc | Bin 152350 -> 0 bytes venv/Lib/site-packages/idna/codec.py | 122 - venv/Lib/site-packages/idna/compat.py | 15 - venv/Lib/site-packages/idna/core.py | 437 - venv/Lib/site-packages/idna/idnadata.py | 4243 -------- venv/Lib/site-packages/idna/intranges.py | 57 - venv/Lib/site-packages/idna/package_data.py | 1 - venv/Lib/site-packages/idna/py.typed | 0 venv/Lib/site-packages/idna/uts46data.py | 8681 ----------------- .../itsdangerous-2.2.0.dist-info/INSTALLER | 1 - .../itsdangerous-2.2.0.dist-info/LICENSE.txt | 28 - .../itsdangerous-2.2.0.dist-info/METADATA | 60 - .../itsdangerous-2.2.0.dist-info/RECORD | 22 - .../itsdangerous-2.2.0.dist-info/WHEEL | 4 - .../site-packages/itsdangerous/__init__.py | 38 - .../__pycache__/__init__.cpython-310.pyc | Bin 1452 -> 0 bytes .../__pycache__/_json.cpython-310.pyc | Bin 970 -> 0 bytes .../__pycache__/encoding.cpython-310.pyc | Bin 1921 -> 0 bytes .../__pycache__/exc.cpython-310.pyc | Bin 3386 -> 0 bytes .../__pycache__/serializer.cpython-310.pyc | Bin 11718 -> 0 bytes .../__pycache__/signer.cpython-310.pyc | Bin 8997 -> 0 bytes .../__pycache__/timed.cpython-310.pyc | Bin 6557 -> 0 bytes .../__pycache__/url_safe.cpython-310.pyc | Bin 2851 -> 0 bytes venv/Lib/site-packages/itsdangerous/_json.py | 18 - .../site-packages/itsdangerous/encoding.py | 54 - venv/Lib/site-packages/itsdangerous/exc.py | 106 - venv/Lib/site-packages/itsdangerous/py.typed | 0 .../site-packages/itsdangerous/serializer.py | 406 - venv/Lib/site-packages/itsdangerous/signer.py | 266 - venv/Lib/site-packages/itsdangerous/timed.py | 228 - .../site-packages/itsdangerous/url_safe.py | 83 - .../jinja2-3.1.6.dist-info/INSTALLER | 1 - .../jinja2-3.1.6.dist-info/METADATA | 84 - .../jinja2-3.1.6.dist-info/RECORD | 57 - .../jinja2-3.1.6.dist-info/WHEEL | 4 - .../jinja2-3.1.6.dist-info/entry_points.txt | 3 - .../licenses/LICENSE.txt | 28 - venv/Lib/site-packages/jinja2/__init__.py | 38 - .../__pycache__/__init__.cpython-310.pyc | Bin 1592 -> 0 bytes .../__pycache__/_identifier.cpython-310.pyc | Bin 2067 -> 0 bytes .../__pycache__/async_utils.cpython-310.pyc | Bin 3444 -> 0 bytes .../__pycache__/bccache.cpython-310.pyc | Bin 13966 -> 0 bytes .../__pycache__/compiler.cpython-310.pyc | Bin 55246 -> 0 bytes .../__pycache__/constants.cpython-310.pyc | Bin 1528 -> 0 bytes .../jinja2/__pycache__/debug.cpython-310.pyc | Bin 3984 -> 0 bytes .../__pycache__/defaults.cpython-310.pyc | Bin 1328 -> 0 bytes .../__pycache__/environment.cpython-310.pyc | Bin 53436 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 5527 -> 0 bytes .../jinja2/__pycache__/ext.cpython-310.pyc | Bin 25868 -> 0 bytes .../__pycache__/filters.cpython-310.pyc | Bin 52110 -> 0 bytes .../__pycache__/idtracking.cpython-310.pyc | Bin 11079 -> 0 bytes .../jinja2/__pycache__/lexer.cpython-310.pyc | Bin 20437 -> 0 bytes .../__pycache__/loaders.cpython-310.pyc | Bin 21251 -> 0 bytes .../jinja2/__pycache__/meta.cpython-310.pyc | Bin 3808 -> 0 bytes .../__pycache__/nativetypes.cpython-310.pyc | Bin 5003 -> 0 bytes .../jinja2/__pycache__/nodes.cpython-310.pyc | Bin 40318 -> 0 bytes .../__pycache__/optimizer.cpython-310.pyc | Bin 1948 -> 0 bytes .../jinja2/__pycache__/parser.cpython-310.pyc | Bin 28105 -> 0 bytes .../__pycache__/runtime.cpython-310.pyc | Bin 32348 -> 0 bytes .../__pycache__/sandbox.cpython-310.pyc | Bin 12230 -> 0 bytes .../jinja2/__pycache__/tests.cpython-310.pyc | Bin 6688 -> 0 bytes .../jinja2/__pycache__/utils.cpython-310.pyc | Bin 24819 -> 0 bytes .../__pycache__/visitor.cpython-310.pyc | Bin 3967 -> 0 bytes venv/Lib/site-packages/jinja2/_identifier.py | 6 - venv/Lib/site-packages/jinja2/async_utils.py | 99 - venv/Lib/site-packages/jinja2/bccache.py | 408 - venv/Lib/site-packages/jinja2/compiler.py | 1998 ---- venv/Lib/site-packages/jinja2/constants.py | 20 - venv/Lib/site-packages/jinja2/debug.py | 191 - venv/Lib/site-packages/jinja2/defaults.py | 48 - venv/Lib/site-packages/jinja2/environment.py | 1672 ---- venv/Lib/site-packages/jinja2/exceptions.py | 166 - venv/Lib/site-packages/jinja2/ext.py | 870 -- venv/Lib/site-packages/jinja2/filters.py | 1873 ---- venv/Lib/site-packages/jinja2/idtracking.py | 318 - venv/Lib/site-packages/jinja2/lexer.py | 868 -- venv/Lib/site-packages/jinja2/loaders.py | 693 -- venv/Lib/site-packages/jinja2/meta.py | 112 - venv/Lib/site-packages/jinja2/nativetypes.py | 130 - venv/Lib/site-packages/jinja2/nodes.py | 1206 --- venv/Lib/site-packages/jinja2/optimizer.py | 48 - venv/Lib/site-packages/jinja2/parser.py | 1049 -- venv/Lib/site-packages/jinja2/py.typed | 0 venv/Lib/site-packages/jinja2/runtime.py | 1062 -- venv/Lib/site-packages/jinja2/sandbox.py | 436 - venv/Lib/site-packages/jinja2/tests.py | 256 - venv/Lib/site-packages/jinja2/utils.py | 766 -- venv/Lib/site-packages/jinja2/visitor.py | 92 - venv/Lib/site-packages/markupsafe/__init__.py | 395 - .../__pycache__/__init__.cpython-310.pyc | Bin 15397 -> 0 bytes .../__pycache__/_native.cpython-310.pyc | Bin 402 -> 0 bytes venv/Lib/site-packages/markupsafe/_native.py | 8 - venv/Lib/site-packages/markupsafe/_speedups.c | 204 - .../markupsafe/_speedups.cp310-win_amd64.pyd | Bin 13312 -> 0 bytes .../site-packages/markupsafe/_speedups.pyi | 1 - venv/Lib/site-packages/markupsafe/py.typed | 0 .../packaging-25.0.dist-info/INSTALLER | 1 - .../packaging-25.0.dist-info/METADATA | 105 - .../packaging-25.0.dist-info/RECORD | 40 - .../packaging-25.0.dist-info/WHEEL | 4 - .../packaging-25.0.dist-info/licenses/LICENSE | 3 - .../licenses/LICENSE.APACHE | 177 - .../licenses/LICENSE.BSD | 23 - venv/Lib/site-packages/packaging/__init__.py | 15 - .../__pycache__/__init__.cpython-310.pyc | Bin 497 -> 0 bytes .../__pycache__/_elffile.cpython-310.pyc | Bin 3368 -> 0 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 6558 -> 0 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 3421 -> 0 bytes .../__pycache__/_parser.cpython-310.pyc | Bin 9237 -> 0 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 2679 -> 0 bytes .../__pycache__/_tokenizer.cpython-310.pyc | Bin 5928 -> 0 bytes .../__pycache__/markers.cpython-310.pyc | Bin 8789 -> 0 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 18722 -> 0 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 2891 -> 0 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 31365 -> 0 bytes .../__pycache__/tags.cpython-310.pyc | Bin 16440 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 4625 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 15014 -> 0 bytes venv/Lib/site-packages/packaging/_elffile.py | 109 - .../Lib/site-packages/packaging/_manylinux.py | 262 - .../Lib/site-packages/packaging/_musllinux.py | 85 - venv/Lib/site-packages/packaging/_parser.py | 353 - .../site-packages/packaging/_structures.py | 61 - .../Lib/site-packages/packaging/_tokenizer.py | 195 - .../packaging/licenses/__init__.py | 145 - .../__pycache__/__init__.cpython-310.pyc | Bin 2584 -> 0 bytes .../__pycache__/_spdx.cpython-310.pyc | Bin 40956 -> 0 bytes .../site-packages/packaging/licenses/_spdx.py | 759 -- venv/Lib/site-packages/packaging/markers.py | 362 - venv/Lib/site-packages/packaging/metadata.py | 862 -- venv/Lib/site-packages/packaging/py.typed | 0 .../site-packages/packaging/requirements.py | 91 - .../Lib/site-packages/packaging/specifiers.py | 1019 -- venv/Lib/site-packages/packaging/tags.py | 656 -- venv/Lib/site-packages/packaging/utils.py | 163 - venv/Lib/site-packages/packaging/version.py | 582 -- .../pathlib-1.0.1.dist-info/INSTALLER | 1 - .../pathlib-1.0.1.dist-info/LICENSE.txt | 19 - .../pathlib-1.0.1.dist-info/METADATA | 180 - .../pathlib-1.0.1.dist-info/RECORD | 9 - .../pathlib-1.0.1.dist-info/REQUESTED | 0 .../pathlib-1.0.1.dist-info/WHEEL | 5 - .../pathlib-1.0.1.dist-info/top_level.txt | 1 - venv/Lib/site-packages/pathlib.py | 1280 --- .../pip-22.2.1.dist-info/INSTALLER | 1 - .../pip-22.2.1.dist-info/LICENSE.txt | 20 - .../pip-22.2.1.dist-info/METADATA | 90 - .../site-packages/pip-22.2.1.dist-info/RECORD | 992 -- .../pip-22.2.1.dist-info/REQUESTED | 0 .../site-packages/pip-22.2.1.dist-info/WHEEL | 5 - .../pip-22.2.1.dist-info/entry_points.txt | 4 - .../pip-22.2.1.dist-info/top_level.txt | 1 - venv/Lib/site-packages/pip/__init__.py | 13 - venv/Lib/site-packages/pip/__main__.py | 31 - venv/Lib/site-packages/pip/__pip-runner__.py | 37 - .../pip/__pycache__/__init__.cpython-310.pyc | Bin 617 -> 0 bytes .../pip/__pycache__/__main__.cpython-310.pyc | Bin 579 -> 0 bytes .../__pip-runner__.cpython-310.pyc | Bin 1386 -> 0 bytes .../site-packages/pip/_internal/__init__.py | 19 - .../__pycache__/__init__.cpython-310.pyc | Bin 738 -> 0 bytes .../__pycache__/build_env.cpython-310.pyc | Bin 9169 -> 0 bytes .../__pycache__/cache.cpython-310.pyc | Bin 9200 -> 0 bytes .../__pycache__/configuration.cpython-310.pyc | Bin 11198 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 23110 -> 0 bytes .../__pycache__/main.cpython-310.pyc | Bin 603 -> 0 bytes .../__pycache__/pyproject.cpython-310.pyc | Bin 3607 -> 0 bytes .../self_outdated_check.cpython-310.pyc | Bin 6559 -> 0 bytes .../__pycache__/wheel_builder.cpython-310.pyc | Bin 9191 -> 0 bytes .../site-packages/pip/_internal/build_env.py | 290 - venv/Lib/site-packages/pip/_internal/cache.py | 289 - .../pip/_internal/cli/__init__.py | 4 - .../cli/__pycache__/__init__.cpython-310.pyc | Bin 258 -> 0 bytes .../autocompletion.cpython-310.pyc | Bin 5293 -> 0 bytes .../__pycache__/base_command.cpython-310.pyc | Bin 6327 -> 0 bytes .../__pycache__/cmdoptions.cpython-310.pyc | Bin 23661 -> 0 bytes .../command_context.cpython-310.pyc | Bin 1298 -> 0 bytes .../cli/__pycache__/main.cpython-310.pyc | Bin 1356 -> 0 bytes .../__pycache__/main_parser.cpython-310.pyc | Bin 2142 -> 0 bytes .../cli/__pycache__/parser.cpython-310.pyc | Bin 9940 -> 0 bytes .../__pycache__/progress_bars.cpython-310.pyc | Bin 1882 -> 0 bytes .../__pycache__/req_command.cpython-310.pyc | Bin 13077 -> 0 bytes .../cli/__pycache__/spinners.cpython-310.pyc | Bin 4920 -> 0 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 337 -> 0 bytes .../pip/_internal/cli/autocompletion.py | 171 - .../pip/_internal/cli/base_command.py | 223 - .../pip/_internal/cli/cmdoptions.py | 1062 -- .../pip/_internal/cli/command_context.py | 27 - .../site-packages/pip/_internal/cli/main.py | 70 - .../pip/_internal/cli/main_parser.py | 87 - .../site-packages/pip/_internal/cli/parser.py | 294 - .../pip/_internal/cli/progress_bars.py | 68 - .../pip/_internal/cli/req_command.py | 502 - .../pip/_internal/cli/spinners.py | 159 - .../pip/_internal/cli/status_codes.py | 6 - .../pip/_internal/commands/__init__.py | 132 - .../__pycache__/__init__.cpython-310.pyc | Bin 3237 -> 0 bytes .../__pycache__/cache.cpython-310.pyc | Bin 6220 -> 0 bytes .../__pycache__/check.cpython-310.pyc | Bin 1555 -> 0 bytes .../__pycache__/completion.cpython-310.pyc | Bin 4146 -> 0 bytes .../__pycache__/configuration.cpython-310.pyc | Bin 8811 -> 0 bytes .../__pycache__/debug.cpython-310.pyc | Bin 6652 -> 0 bytes .../__pycache__/download.cpython-310.pyc | Bin 4032 -> 0 bytes .../__pycache__/freeze.cpython-310.pyc | Bin 2620 -> 0 bytes .../commands/__pycache__/hash.cpython-310.pyc | Bin 2134 -> 0 bytes .../commands/__pycache__/help.cpython-310.pyc | Bin 1295 -> 0 bytes .../__pycache__/index.cpython-310.pyc | Bin 4544 -> 0 bytes .../__pycache__/inspect.cpython-310.pyc | Bin 3108 -> 0 bytes .../__pycache__/install.cpython-310.pyc | Bin 19405 -> 0 bytes .../commands/__pycache__/list.cpython-310.pyc | Bin 10176 -> 0 bytes .../__pycache__/search.cpython-310.pyc | Bin 5348 -> 0 bytes .../commands/__pycache__/show.cpython-310.pyc | Bin 6380 -> 0 bytes .../__pycache__/uninstall.cpython-310.pyc | Bin 3208 -> 0 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 4871 -> 0 bytes .../pip/_internal/commands/cache.py | 223 - .../pip/_internal/commands/check.py | 53 - .../pip/_internal/commands/completion.py | 126 - .../pip/_internal/commands/configuration.py | 276 - .../pip/_internal/commands/debug.py | 199 - .../pip/_internal/commands/download.py | 142 - .../pip/_internal/commands/freeze.py | 97 - .../pip/_internal/commands/hash.py | 59 - .../pip/_internal/commands/help.py | 41 - .../pip/_internal/commands/index.py | 138 - .../pip/_internal/commands/inspect.py | 97 - .../pip/_internal/commands/install.py | 827 -- .../pip/_internal/commands/list.py | 360 - .../pip/_internal/commands/search.py | 174 - .../pip/_internal/commands/show.py | 183 - .../pip/_internal/commands/uninstall.py | 106 - .../pip/_internal/commands/wheel.py | 178 - .../pip/_internal/configuration.py | 374 - .../pip/_internal/distributions/__init__.py | 21 - .../__pycache__/__init__.cpython-310.pyc | Bin 785 -> 0 bytes .../__pycache__/base.cpython-310.pyc | Bin 1873 -> 0 bytes .../__pycache__/installed.cpython-310.pyc | Bin 1250 -> 0 bytes .../__pycache__/sdist.cpython-310.pyc | Bin 4981 -> 0 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 1617 -> 0 bytes .../pip/_internal/distributions/base.py | 39 - .../pip/_internal/distributions/installed.py | 23 - .../pip/_internal/distributions/sdist.py | 150 - .../pip/_internal/distributions/wheel.py | 34 - .../site-packages/pip/_internal/exceptions.py | 658 -- .../pip/_internal/index/__init__.py | 2 - .../__pycache__/__init__.cpython-310.pyc | Bin 212 -> 0 bytes .../__pycache__/collector.cpython-310.pyc | Bin 17690 -> 0 bytes .../package_finder.cpython-310.pyc | Bin 29049 -> 0 bytes .../index/__pycache__/sources.cpython-310.pyc | Bin 7105 -> 0 bytes .../pip/_internal/index/collector.py | 620 -- .../pip/_internal/index/package_finder.py | 1025 -- .../pip/_internal/index/sources.py | 224 - .../pip/_internal/locations/__init__.py | 530 - .../__pycache__/__init__.cpython-310.pyc | Bin 12516 -> 0 bytes .../__pycache__/_distutils.cpython-310.pyc | Bin 4741 -> 0 bytes .../__pycache__/_sysconfig.cpython-310.pyc | Bin 6185 -> 0 bytes .../__pycache__/base.cpython-310.pyc | Bin 2388 -> 0 bytes .../pip/_internal/locations/_distutils.py | 180 - .../pip/_internal/locations/_sysconfig.py | 218 - .../pip/_internal/locations/base.py | 81 - venv/Lib/site-packages/pip/_internal/main.py | 12 - .../pip/_internal/metadata/__init__.py | 105 - .../__pycache__/__init__.cpython-310.pyc | Bin 3993 -> 0 bytes .../__pycache__/_json.cpython-310.pyc | Bin 2172 -> 0 bytes .../metadata/__pycache__/base.cpython-310.pyc | Bin 25933 -> 0 bytes .../__pycache__/pkg_resources.cpython-310.pyc | Bin 9795 -> 0 bytes .../pip/_internal/metadata/_json.py | 84 - .../pip/_internal/metadata/base.py | 670 -- .../_internal/metadata/importlib/__init__.py | 4 - .../__pycache__/__init__.cpython-310.pyc | Bin 303 -> 0 bytes .../__pycache__/_compat.cpython-310.pyc | Bin 2109 -> 0 bytes .../__pycache__/_dists.cpython-310.pyc | Bin 8365 -> 0 bytes .../__pycache__/_envs.cpython-310.pyc | Bin 7476 -> 0 bytes .../_internal/metadata/importlib/_compat.py | 43 - .../_internal/metadata/importlib/_dists.py | 206 - .../pip/_internal/metadata/importlib/_envs.py | 180 - .../pip/_internal/metadata/pkg_resources.py | 253 - .../pip/_internal/models/__init__.py | 2 - .../__pycache__/__init__.cpython-310.pyc | Bin 246 -> 0 bytes .../__pycache__/candidate.cpython-310.pyc | Bin 1398 -> 0 bytes .../__pycache__/direct_url.cpython-310.pyc | Bin 7092 -> 0 bytes .../format_control.cpython-310.pyc | Bin 2723 -> 0 bytes .../models/__pycache__/index.cpython-310.pyc | Bin 1215 -> 0 bytes .../installation_report.cpython-310.pyc | Bin 1725 -> 0 bytes .../models/__pycache__/link.cpython-310.pyc | Bin 10521 -> 0 bytes .../models/__pycache__/scheme.cpython-310.pyc | Bin 1014 -> 0 bytes .../__pycache__/search_scope.cpython-310.pyc | Bin 3469 -> 0 bytes .../selection_prefs.cpython-310.pyc | Bin 1676 -> 0 bytes .../__pycache__/target_python.cpython-310.pyc | Bin 3431 -> 0 bytes .../models/__pycache__/wheel.cpython-310.pyc | Bin 4425 -> 0 bytes .../pip/_internal/models/candidate.py | 34 - .../pip/_internal/models/direct_url.py | 212 - .../pip/_internal/models/format_control.py | 80 - .../pip/_internal/models/index.py | 28 - .../_internal/models/installation_report.py | 53 - .../pip/_internal/models/link.py | 314 - .../pip/_internal/models/scheme.py | 31 - .../pip/_internal/models/search_scope.py | 129 - .../pip/_internal/models/selection_prefs.py | 51 - .../pip/_internal/models/target_python.py | 110 - .../pip/_internal/models/wheel.py | 92 - .../pip/_internal/network/__init__.py | 2 - .../__pycache__/__init__.cpython-310.pyc | Bin 234 -> 0 bytes .../network/__pycache__/auth.cpython-310.pyc | Bin 7514 -> 0 bytes .../network/__pycache__/cache.cpython-310.pyc | Bin 2921 -> 0 bytes .../__pycache__/download.cpython-310.pyc | Bin 5516 -> 0 bytes .../__pycache__/lazy_wheel.cpython-310.pyc | Bin 8401 -> 0 bytes .../__pycache__/session.cpython-310.pyc | Bin 12414 -> 0 bytes .../network/__pycache__/utils.cpython-310.pyc | Bin 1437 -> 0 bytes .../__pycache__/xmlrpc.cpython-310.pyc | Bin 2047 -> 0 bytes .../pip/_internal/network/auth.py | 323 - .../pip/_internal/network/cache.py | 69 - .../pip/_internal/network/download.py | 186 - .../pip/_internal/network/lazy_wheel.py | 210 - .../pip/_internal/network/session.py | 518 - .../pip/_internal/network/utils.py | 96 - .../pip/_internal/network/xmlrpc.py | 60 - .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 182 -> 0 bytes .../__pycache__/check.cpython-310.pyc | Bin 3995 -> 0 bytes .../__pycache__/freeze.cpython-310.pyc | Bin 6187 -> 0 bytes .../__pycache__/prepare.cpython-310.pyc | Bin 14039 -> 0 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 188 -> 0 bytes .../__pycache__/build_tracker.cpython-310.pyc | Bin 4269 -> 0 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 1415 -> 0 bytes .../metadata_editable.cpython-310.pyc | Bin 1449 -> 0 bytes .../metadata_legacy.cpython-310.pyc | Bin 2360 -> 0 bytes .../build/__pycache__/wheel.cpython-310.pyc | Bin 1205 -> 0 bytes .../wheel_editable.cpython-310.pyc | Bin 1429 -> 0 bytes .../__pycache__/wheel_legacy.cpython-310.pyc | Bin 2745 -> 0 bytes .../operations/build/build_tracker.py | 124 - .../_internal/operations/build/metadata.py | 39 - .../operations/build/metadata_editable.py | 41 - .../operations/build/metadata_legacy.py | 74 - .../pip/_internal/operations/build/wheel.py | 37 - .../operations/build/wheel_editable.py | 46 - .../operations/build/wheel_legacy.py | 102 - .../pip/_internal/operations/check.py | 149 - .../pip/_internal/operations/freeze.py | 254 - .../_internal/operations/install/__init__.py | 2 - .../__pycache__/__init__.cpython-310.pyc | Bin 246 -> 0 bytes .../editable_legacy.cpython-310.pyc | Bin 1533 -> 0 bytes .../__pycache__/legacy.cpython-310.pyc | Bin 3331 -> 0 bytes .../install/__pycache__/wheel.cpython-310.pyc | Bin 21105 -> 0 bytes .../operations/install/editable_legacy.py | 47 - .../_internal/operations/install/legacy.py | 120 - .../pip/_internal/operations/install/wheel.py | 736 -- .../pip/_internal/operations/prepare.py | 614 -- .../site-packages/pip/_internal/pyproject.py | 175 - .../pip/_internal/req/__init__.py | 94 - .../req/__pycache__/__init__.cpython-310.pyc | Bin 2589 -> 0 bytes .../__pycache__/constructors.cpython-310.pyc | Bin 12361 -> 0 bytes .../req/__pycache__/req_file.cpython-310.pyc | Bin 13526 -> 0 bytes .../__pycache__/req_install.cpython-310.pyc | Bin 22667 -> 0 bytes .../req/__pycache__/req_set.cpython-310.pyc | Bin 3897 -> 0 bytes .../__pycache__/req_uninstall.cpython-310.pyc | Bin 19048 -> 0 bytes .../pip/_internal/req/constructors.py | 501 - .../pip/_internal/req/req_file.py | 540 - .../pip/_internal/req/req_install.py | 879 -- .../pip/_internal/req/req_set.py | 82 - .../pip/_internal/req/req_uninstall.py | 640 -- .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 182 -> 0 bytes .../__pycache__/base.cpython-310.pyc | Bin 1034 -> 0 bytes .../pip/_internal/resolution/base.py | 20 - .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 189 -> 0 bytes .../__pycache__/resolver.cpython-310.pyc | Bin 14937 -> 0 bytes .../_internal/resolution/legacy/resolver.py | 600 -- .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 193 -> 0 bytes .../__pycache__/base.cpython-310.pyc | Bin 6436 -> 0 bytes .../__pycache__/candidates.cpython-310.pyc | Bin 18577 -> 0 bytes .../__pycache__/factory.cpython-310.pyc | Bin 19057 -> 0 bytes .../found_candidates.cpython-310.pyc | Bin 4853 -> 0 bytes .../__pycache__/provider.cpython-310.pyc | Bin 7694 -> 0 bytes .../__pycache__/reporter.cpython-310.pyc | Bin 3162 -> 0 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 7451 -> 0 bytes .../__pycache__/resolver.cpython-310.pyc | Bin 8166 -> 0 bytes .../_internal/resolution/resolvelib/base.py | 141 - .../resolution/resolvelib/candidates.py | 556 -- .../resolution/resolvelib/factory.py | 731 -- .../resolution/resolvelib/found_candidates.py | 155 - .../resolution/resolvelib/provider.py | 248 - .../resolution/resolvelib/reporter.py | 68 - .../resolution/resolvelib/requirements.py | 166 - .../resolution/resolvelib/resolver.py | 296 - .../pip/_internal/self_outdated_check.py | 239 - .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 177 -> 0 bytes .../utils/__pycache__/_log.cpython-310.pyc | Bin 1505 -> 0 bytes .../utils/__pycache__/appdirs.cpython-310.pyc | Bin 1603 -> 0 bytes .../utils/__pycache__/compat.cpython-310.pyc | Bin 1493 -> 0 bytes .../compatibility_tags.cpython-310.pyc | Bin 4062 -> 0 bytes .../__pycache__/datetime.cpython-310.pyc | Bin 500 -> 0 bytes .../__pycache__/deprecation.cpython-310.pyc | Bin 3322 -> 0 bytes .../direct_url_helpers.cpython-310.pyc | Bin 2068 -> 0 bytes .../distutils_args.cpython-310.pyc | Bin 1042 -> 0 bytes .../__pycache__/egg_link.cpython-310.pyc | Bin 2133 -> 0 bytes .../__pycache__/encoding.cpython-310.pyc | Bin 1290 -> 0 bytes .../__pycache__/entrypoints.cpython-310.pyc | Bin 2628 -> 0 bytes .../__pycache__/filesystem.cpython-310.pyc | Bin 4466 -> 0 bytes .../__pycache__/filetypes.cpython-310.pyc | Bin 927 -> 0 bytes .../utils/__pycache__/glibc.cpython-310.pyc | Bin 1656 -> 0 bytes .../utils/__pycache__/hashes.cpython-310.pyc | Bin 5179 -> 0 bytes .../inject_securetransport.cpython-310.pyc | Bin 972 -> 0 bytes .../utils/__pycache__/logging.cpython-310.pyc | Bin 9704 -> 0 bytes .../utils/__pycache__/misc.cpython-310.pyc | Bin 21583 -> 0 bytes .../utils/__pycache__/models.cpython-310.pyc | Bin 1973 -> 0 bytes .../__pycache__/packaging.cpython-310.pyc | Bin 2065 -> 0 bytes .../setuptools_build.cpython-310.pyc | Bin 4580 -> 0 bytes .../__pycache__/subprocess.cpython-310.pyc | Bin 5753 -> 0 bytes .../__pycache__/temp_dir.cpython-310.pyc | Bin 7300 -> 0 bytes .../__pycache__/unpacking.cpython-310.pyc | Bin 6651 -> 0 bytes .../utils/__pycache__/urls.cpython-310.pyc | Bin 1578 -> 0 bytes .../__pycache__/virtualenv.cpython-310.pyc | Bin 3273 -> 0 bytes .../utils/__pycache__/wheel.cpython-310.pyc | Bin 4398 -> 0 bytes .../site-packages/pip/_internal/utils/_log.py | 38 - .../pip/_internal/utils/appdirs.py | 52 - .../pip/_internal/utils/compat.py | 63 - .../pip/_internal/utils/compatibility_tags.py | 165 - .../pip/_internal/utils/datetime.py | 11 - .../pip/_internal/utils/deprecation.py | 120 - .../pip/_internal/utils/direct_url_helpers.py | 87 - .../pip/_internal/utils/distutils_args.py | 43 - .../pip/_internal/utils/egg_link.py | 75 - .../pip/_internal/utils/encoding.py | 36 - .../pip/_internal/utils/entrypoints.py | 79 - .../pip/_internal/utils/filesystem.py | 153 - .../pip/_internal/utils/filetypes.py | 27 - .../pip/_internal/utils/glibc.py | 88 - .../pip/_internal/utils/hashes.py | 144 - .../_internal/utils/inject_securetransport.py | 35 - .../pip/_internal/utils/logging.py | 348 - .../site-packages/pip/_internal/utils/misc.py | 723 -- .../pip/_internal/utils/models.py | 39 - .../pip/_internal/utils/packaging.py | 57 - .../pip/_internal/utils/setuptools_build.py | 195 - .../pip/_internal/utils/subprocess.py | 260 - .../pip/_internal/utils/temp_dir.py | 246 - .../pip/_internal/utils/unpacking.py | 257 - .../site-packages/pip/_internal/utils/urls.py | 62 - .../pip/_internal/utils/virtualenv.py | 104 - .../pip/_internal/utils/wheel.py | 136 - .../pip/_internal/vcs/__init__.py | 15 - .../vcs/__pycache__/__init__.cpython-310.pyc | Bin 500 -> 0 bytes .../vcs/__pycache__/bazaar.cpython-310.pyc | Bin 3327 -> 0 bytes .../vcs/__pycache__/git.cpython-310.pyc | Bin 12530 -> 0 bytes .../vcs/__pycache__/mercurial.cpython-310.pyc | Bin 5046 -> 0 bytes .../__pycache__/subversion.cpython-310.pyc | Bin 8434 -> 0 bytes .../versioncontrol.cpython-310.pyc | Bin 21129 -> 0 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 101 - .../site-packages/pip/_internal/vcs/git.py | 526 - .../pip/_internal/vcs/mercurial.py | 163 - .../pip/_internal/vcs/subversion.py | 324 - .../pip/_internal/vcs/versioncontrol.py | 705 -- .../pip/_internal/wheel_builder.py | 383 - .../Lib/site-packages/pip/_vendor/__init__.py | 120 - .../__pycache__/__init__.cpython-310.pyc | Bin 3113 -> 0 bytes .../_vendor/__pycache__/six.cpython-310.pyc | Bin 27571 -> 0 bytes .../typing_extensions.cpython-310.pyc | Bin 60711 -> 0 bytes .../pip/_vendor/cachecontrol/__init__.py | 18 - .../__pycache__/__init__.cpython-310.pyc | Bin 628 -> 0 bytes .../__pycache__/_cmd.cpython-310.pyc | Bin 1566 -> 0 bytes .../__pycache__/adapter.cpython-310.pyc | Bin 3142 -> 0 bytes .../__pycache__/cache.cpython-310.pyc | Bin 2676 -> 0 bytes .../__pycache__/compat.cpython-310.pyc | Bin 742 -> 0 bytes .../__pycache__/controller.cpython-310.pyc | Bin 8582 -> 0 bytes .../__pycache__/filewrapper.cpython-310.pyc | Bin 2778 -> 0 bytes .../__pycache__/heuristics.cpython-310.pyc | Bin 4702 -> 0 bytes .../__pycache__/serialize.cpython-310.pyc | Bin 4317 -> 0 bytes .../__pycache__/wrapper.cpython-310.pyc | Bin 673 -> 0 bytes .../pip/_vendor/cachecontrol/_cmd.py | 61 - .../pip/_vendor/cachecontrol/adapter.py | 137 - .../pip/_vendor/cachecontrol/cache.py | 65 - .../_vendor/cachecontrol/caches/__init__.py | 9 - .../__pycache__/__init__.cpython-310.pyc | Bin 347 -> 0 bytes .../__pycache__/file_cache.cpython-310.pyc | Bin 4947 -> 0 bytes .../__pycache__/redis_cache.cpython-310.pyc | Bin 1605 -> 0 bytes .../_vendor/cachecontrol/caches/file_cache.py | 188 - .../cachecontrol/caches/redis_cache.py | 39 - .../pip/_vendor/cachecontrol/compat.py | 32 - .../pip/_vendor/cachecontrol/controller.py | 439 - .../pip/_vendor/cachecontrol/filewrapper.py | 111 - .../pip/_vendor/cachecontrol/heuristics.py | 139 - .../pip/_vendor/cachecontrol/serialize.py | 190 - .../pip/_vendor/cachecontrol/wrapper.py | 33 - .../pip/_vendor/certifi/__init__.py | 4 - .../pip/_vendor/certifi/__main__.py | 12 - .../__pycache__/__init__.cpython-310.pyc | Bin 290 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 440 -> 0 bytes .../certifi/__pycache__/core.cpython-310.pyc | Bin 1784 -> 0 bytes .../pip/_vendor/certifi/cacert.pem | 4685 --------- .../site-packages/pip/_vendor/certifi/core.py | 84 - .../pip/_vendor/chardet/__init__.py | 93 - .../__pycache__/__init__.cpython-310.pyc | Bin 2367 -> 0 bytes .../__pycache__/big5freq.cpython-310.pyc | Bin 27164 -> 0 bytes .../__pycache__/big5prober.cpython-310.pyc | Bin 1106 -> 0 bytes .../chardistribution.cpython-310.pyc | Bin 6209 -> 0 bytes .../charsetgroupprober.cpython-310.pyc | Bin 2200 -> 0 bytes .../__pycache__/charsetprober.cpython-310.pyc | Bin 3388 -> 0 bytes .../codingstatemachine.cpython-310.pyc | Bin 2873 -> 0 bytes .../__pycache__/cp949prober.cpython-310.pyc | Bin 1113 -> 0 bytes .../chardet/__pycache__/enums.cpython-310.pyc | Bin 2549 -> 0 bytes .../__pycache__/escprober.cpython-310.pyc | Bin 2594 -> 0 bytes .../chardet/__pycache__/escsm.cpython-310.pyc | Bin 8363 -> 0 bytes .../__pycache__/eucjpprober.cpython-310.pyc | Bin 2397 -> 0 bytes .../__pycache__/euckrfreq.cpython-310.pyc | Bin 12048 -> 0 bytes .../__pycache__/euckrprober.cpython-310.pyc | Bin 1114 -> 0 bytes .../__pycache__/euctwfreq.cpython-310.pyc | Bin 27168 -> 0 bytes .../__pycache__/euctwprober.cpython-310.pyc | Bin 1114 -> 0 bytes .../__pycache__/gb2312freq.cpython-310.pyc | Bin 19092 -> 0 bytes .../__pycache__/gb2312prober.cpython-310.pyc | Bin 1122 -> 0 bytes .../__pycache__/hebrewprober.cpython-310.pyc | Bin 3005 -> 0 bytes .../__pycache__/jisfreq.cpython-310.pyc | Bin 22120 -> 0 bytes .../__pycache__/johabfreq.cpython-310.pyc | Bin 138744 -> 0 bytes .../__pycache__/johabprober.cpython-310.pyc | Bin 1113 -> 0 bytes .../__pycache__/jpcntx.cpython-310.pyc | Bin 37616 -> 0 bytes .../langbulgarianmodel.cpython-310.pyc | Bin 47912 -> 0 bytes .../langgreekmodel.cpython-310.pyc | Bin 46102 -> 0 bytes .../langhebrewmodel.cpython-310.pyc | Bin 44549 -> 0 bytes .../langhungarianmodel.cpython-310.pyc | Bin 47872 -> 0 bytes .../langrussianmodel.cpython-310.pyc | Bin 61013 -> 0 bytes .../__pycache__/langthaimodel.cpython-310.pyc | Bin 44725 -> 0 bytes .../langturkishmodel.cpython-310.pyc | Bin 44566 -> 0 bytes .../__pycache__/latin1prober.cpython-310.pyc | Bin 4390 -> 0 bytes .../mbcharsetprober.cpython-310.pyc | Bin 2216 -> 0 bytes .../mbcsgroupprober.cpython-310.pyc | Bin 1167 -> 0 bytes .../__pycache__/mbcssm.cpython-310.pyc | Bin 20690 -> 0 bytes .../sbcharsetprober.cpython-310.pyc | Bin 3183 -> 0 bytes .../sbcsgroupprober.cpython-310.pyc | Bin 1706 -> 0 bytes .../__pycache__/sjisprober.cpython-310.pyc | Bin 2435 -> 0 bytes .../universaldetector.cpython-310.pyc | Bin 6452 -> 0 bytes .../__pycache__/utf1632prober.cpython-310.pyc | Bin 5866 -> 0 bytes .../__pycache__/utf8prober.cpython-310.pyc | Bin 1949 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 424 -> 0 bytes .../pip/_vendor/chardet/big5freq.py | 386 - .../pip/_vendor/chardet/big5prober.py | 47 - .../pip/_vendor/chardet/chardistribution.py | 259 - .../pip/_vendor/chardet/charsetgroupprober.py | 109 - .../pip/_vendor/chardet/charsetprober.py | 138 - .../pip/_vendor/chardet/cli/__init__.py | 0 .../cli/__pycache__/__init__.cpython-310.pyc | Bin 181 -> 0 bytes .../__pycache__/chardetect.cpython-310.pyc | Bin 2389 -> 0 bytes .../pip/_vendor/chardet/cli/chardetect.py | 86 - .../pip/_vendor/chardet/codingstatemachine.py | 88 - .../pip/_vendor/chardet/cp949prober.py | 49 - .../pip/_vendor/chardet/enums.py | 82 - .../pip/_vendor/chardet/escprober.py | 102 - .../pip/_vendor/chardet/escsm.py | 260 - .../pip/_vendor/chardet/eucjpprober.py | 95 - .../pip/_vendor/chardet/euckrfreq.py | 196 - .../pip/_vendor/chardet/euckrprober.py | 47 - .../pip/_vendor/chardet/euctwfreq.py | 388 - .../pip/_vendor/chardet/euctwprober.py | 47 - .../pip/_vendor/chardet/gb2312freq.py | 284 - .../pip/_vendor/chardet/gb2312prober.py | 47 - .../pip/_vendor/chardet/hebrewprober.py | 302 - .../pip/_vendor/chardet/jisfreq.py | 325 - .../pip/_vendor/chardet/johabfreq.py | 2382 ----- .../pip/_vendor/chardet/johabprober.py | 47 - .../pip/_vendor/chardet/jpcntx.py | 237 - .../pip/_vendor/chardet/langbulgarianmodel.py | 4649 --------- .../pip/_vendor/chardet/langgreekmodel.py | 4397 --------- .../pip/_vendor/chardet/langhebrewmodel.py | 4380 --------- .../pip/_vendor/chardet/langhungarianmodel.py | 4649 --------- .../pip/_vendor/chardet/langrussianmodel.py | 5725 ----------- .../pip/_vendor/chardet/langthaimodel.py | 4380 --------- .../pip/_vendor/chardet/langturkishmodel.py | 4380 --------- .../pip/_vendor/chardet/latin1prober.py | 145 - .../pip/_vendor/chardet/mbcharsetprober.py | 95 - .../pip/_vendor/chardet/mbcsgroupprober.py | 56 - .../pip/_vendor/chardet/mbcssm.py | 660 -- .../pip/_vendor/chardet/metadata/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 186 -> 0 bytes .../__pycache__/languages.cpython-310.pyc | Bin 7944 -> 0 bytes .../pip/_vendor/chardet/metadata/languages.py | 351 - .../pip/_vendor/chardet/sbcharsetprober.py | 160 - .../pip/_vendor/chardet/sbcsgroupprober.py | 88 - .../pip/_vendor/chardet/sjisprober.py | 98 - .../pip/_vendor/chardet/universaldetector.py | 328 - .../pip/_vendor/chardet/utf1632prober.py | 223 - .../pip/_vendor/chardet/utf8prober.py | 80 - .../pip/_vendor/chardet/version.py | 9 - .../pip/_vendor/colorama/__init__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 429 -> 0 bytes .../colorama/__pycache__/ansi.cpython-310.pyc | Bin 2990 -> 0 bytes .../__pycache__/ansitowin32.cpython-310.pyc | Bin 8192 -> 0 bytes .../__pycache__/initialise.cpython-310.pyc | Bin 1676 -> 0 bytes .../__pycache__/win32.cpython-310.pyc | Bin 3936 -> 0 bytes .../__pycache__/winterm.cpython-310.pyc | Bin 4553 -> 0 bytes .../pip/_vendor/colorama/ansi.py | 102 - .../pip/_vendor/colorama/ansitowin32.py | 266 - .../pip/_vendor/colorama/initialise.py | 80 - .../pip/_vendor/colorama/win32.py | 152 - .../pip/_vendor/colorama/winterm.py | 169 - .../pip/_vendor/distlib/__init__.py | 23 - .../__pycache__/__init__.cpython-310.pyc | Bin 1048 -> 0 bytes .../__pycache__/compat.cpython-310.pyc | Bin 31394 -> 0 bytes .../__pycache__/database.cpython-310.pyc | Bin 43134 -> 0 bytes .../distlib/__pycache__/index.cpython-310.pyc | Bin 17299 -> 0 bytes .../__pycache__/locators.cpython-310.pyc | Bin 38356 -> 0 bytes .../__pycache__/manifest.cpython-310.pyc | Bin 10216 -> 0 bytes .../__pycache__/markers.cpython-310.pyc | Bin 5022 -> 0 bytes .../__pycache__/metadata.cpython-310.pyc | Bin 26773 -> 0 bytes .../__pycache__/resources.cpython-310.pyc | Bin 11022 -> 0 bytes .../__pycache__/scripts.cpython-310.pyc | Bin 11488 -> 0 bytes .../distlib/__pycache__/util.cpython-310.pyc | Bin 51683 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 20137 -> 0 bytes .../distlib/__pycache__/wheel.cpython-310.pyc | Bin 28117 -> 0 bytes .../pip/_vendor/distlib/compat.py | 1116 --- .../pip/_vendor/distlib/database.py | 1350 --- .../pip/_vendor/distlib/index.py | 508 - .../pip/_vendor/distlib/locators.py | 1300 --- .../pip/_vendor/distlib/manifest.py | 393 - .../pip/_vendor/distlib/markers.py | 152 - .../pip/_vendor/distlib/metadata.py | 1076 -- .../pip/_vendor/distlib/resources.py | 358 - .../pip/_vendor/distlib/scripts.py | 437 - .../site-packages/pip/_vendor/distlib/t32.exe | Bin 97792 -> 0 bytes .../pip/_vendor/distlib/t64-arm.exe | Bin 182784 -> 0 bytes .../site-packages/pip/_vendor/distlib/t64.exe | Bin 107520 -> 0 bytes .../site-packages/pip/_vendor/distlib/util.py | 1932 ---- .../pip/_vendor/distlib/version.py | 739 -- .../site-packages/pip/_vendor/distlib/w32.exe | Bin 91648 -> 0 bytes .../pip/_vendor/distlib/w64-arm.exe | Bin 168448 -> 0 bytes .../site-packages/pip/_vendor/distlib/w64.exe | Bin 101888 -> 0 bytes .../pip/_vendor/distlib/wheel.py | 1082 -- .../pip/_vendor/distro/__init__.py | 54 - .../pip/_vendor/distro/__main__.py | 4 - .../__pycache__/__init__.cpython-310.pyc | Bin 901 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 255 -> 0 bytes .../distro/__pycache__/distro.cpython-310.pyc | Bin 41318 -> 0 bytes .../pip/_vendor/distro/distro.py | 1374 --- .../pip/_vendor/idna/__init__.py | 44 - .../idna/__pycache__/__init__.cpython-310.pyc | Bin 833 -> 0 bytes .../idna/__pycache__/codec.cpython-310.pyc | Bin 2804 -> 0 bytes .../idna/__pycache__/compat.cpython-310.pyc | Bin 733 -> 0 bytes .../idna/__pycache__/core.cpython-310.pyc | Bin 9576 -> 0 bytes .../idna/__pycache__/idnadata.cpython-310.pyc | Bin 38211 -> 0 bytes .../__pycache__/intranges.cpython-310.pyc | Bin 1970 -> 0 bytes .../__pycache__/package_data.cpython-310.pyc | Bin 197 -> 0 bytes .../__pycache__/uts46data.cpython-310.pyc | Bin 150932 -> 0 bytes .../site-packages/pip/_vendor/idna/codec.py | 112 - .../site-packages/pip/_vendor/idna/compat.py | 13 - .../site-packages/pip/_vendor/idna/core.py | 397 - .../pip/_vendor/idna/idnadata.py | 2137 ---- .../pip/_vendor/idna/intranges.py | 54 - .../pip/_vendor/idna/package_data.py | 2 - .../pip/_vendor/idna/uts46data.py | 8512 ---------------- .../pip/_vendor/msgpack/__init__.py | 57 - .../__pycache__/__init__.cpython-310.pyc | Bin 1431 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 1794 -> 0 bytes .../msgpack/__pycache__/ext.cpython-310.pyc | Bin 6302 -> 0 bytes .../__pycache__/fallback.cpython-310.pyc | Bin 25469 -> 0 bytes .../pip/_vendor/msgpack/exceptions.py | 48 - .../site-packages/pip/_vendor/msgpack/ext.py | 193 - .../pip/_vendor/msgpack/fallback.py | 1010 -- .../pip/_vendor/packaging/__about__.py | 26 - .../pip/_vendor/packaging/__init__.py | 25 - .../__pycache__/__about__.cpython-310.pyc | Bin 576 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 432 -> 0 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 7286 -> 0 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 4598 -> 0 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 2691 -> 0 bytes .../__pycache__/markers.cpython-310.pyc | Bin 9275 -> 0 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 3961 -> 0 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 21513 -> 0 bytes .../__pycache__/tags.cpython-310.pyc | Bin 12182 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 3561 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 12911 -> 0 bytes .../pip/_vendor/packaging/_manylinux.py | 301 - .../pip/_vendor/packaging/_musllinux.py | 136 - .../pip/_vendor/packaging/_structures.py | 61 - .../pip/_vendor/packaging/markers.py | 304 - .../pip/_vendor/packaging/requirements.py | 146 - .../pip/_vendor/packaging/specifiers.py | 802 -- .../pip/_vendor/packaging/tags.py | 487 - .../pip/_vendor/packaging/utils.py | 136 - .../pip/_vendor/packaging/version.py | 504 - .../pip/_vendor/pep517/__init__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 299 -> 0 bytes .../pep517/__pycache__/build.cpython-310.pyc | Bin 3582 -> 0 bytes .../pep517/__pycache__/check.cpython-310.pyc | Bin 4546 -> 0 bytes .../__pycache__/colorlog.cpython-310.pyc | Bin 2950 -> 0 bytes .../pep517/__pycache__/compat.cpython-310.pyc | Bin 1523 -> 0 bytes .../__pycache__/dirtools.cpython-310.pyc | Bin 1341 -> 0 bytes .../__pycache__/envbuild.cpython-310.pyc | Bin 4364 -> 0 bytes .../pep517/__pycache__/meta.cpython-310.pyc | Bin 2946 -> 0 bytes .../__pycache__/wrappers.cpython-310.pyc | Bin 12292 -> 0 bytes .../site-packages/pip/_vendor/pep517/build.py | 127 - .../site-packages/pip/_vendor/pep517/check.py | 207 - .../pip/_vendor/pep517/colorlog.py | 115 - .../pip/_vendor/pep517/compat.py | 51 - .../pip/_vendor/pep517/dirtools.py | 44 - .../pip/_vendor/pep517/envbuild.py | 171 - .../pip/_vendor/pep517/in_process/__init__.py | 17 - .../__pycache__/__init__.cpython-310.pyc | Bin 907 -> 0 bytes .../__pycache__/_in_process.cpython-310.pyc | Bin 10054 -> 0 bytes .../_vendor/pep517/in_process/_in_process.py | 363 - .../site-packages/pip/_vendor/pep517/meta.py | 92 - .../pip/_vendor/pep517/wrappers.py | 375 - .../pip/_vendor/pkg_resources/__init__.py | 3296 ------- .../__pycache__/__init__.cpython-310.pyc | Bin 99876 -> 0 bytes .../__pycache__/py31compat.cpython-310.pyc | Bin 646 -> 0 bytes .../pip/_vendor/pkg_resources/py31compat.py | 23 - .../pip/_vendor/platformdirs/__init__.py | 340 - .../pip/_vendor/platformdirs/__main__.py | 46 - .../__pycache__/__init__.cpython-310.pyc | Bin 10514 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 1222 -> 0 bytes .../__pycache__/android.cpython-310.pyc | Bin 4312 -> 0 bytes .../__pycache__/api.cpython-310.pyc | Bin 5188 -> 0 bytes .../__pycache__/macos.cpython-310.pyc | Bin 3176 -> 0 bytes .../__pycache__/unix.cpython-310.pyc | Bin 6877 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 279 -> 0 bytes .../__pycache__/windows.cpython-310.pyc | Bin 6420 -> 0 bytes .../pip/_vendor/platformdirs/android.py | 120 - .../pip/_vendor/platformdirs/api.py | 156 - .../pip/_vendor/platformdirs/macos.py | 64 - .../pip/_vendor/platformdirs/unix.py | 181 - .../pip/_vendor/platformdirs/version.py | 4 - .../pip/_vendor/platformdirs/windows.py | 182 - .../pip/_vendor/pygments/__init__.py | 83 - .../pip/_vendor/pygments/__main__.py | 17 - .../__pycache__/__init__.cpython-310.pyc | Bin 2986 -> 0 bytes .../__pycache__/__main__.cpython-310.pyc | Bin 574 -> 0 bytes .../__pycache__/cmdline.cpython-310.pyc | Bin 15439 -> 0 bytes .../__pycache__/console.cpython-310.pyc | Bin 1869 -> 0 bytes .../__pycache__/filter.cpython-310.pyc | Bin 2640 -> 0 bytes .../__pycache__/formatter.cpython-310.pyc | Bin 2996 -> 0 bytes .../__pycache__/lexer.cpython-310.pyc | Bin 24359 -> 0 bytes .../__pycache__/modeline.cpython-310.pyc | Bin 1178 -> 0 bytes .../__pycache__/plugin.cpython-310.pyc | Bin 2030 -> 0 bytes .../__pycache__/regexopt.cpython-310.pyc | Bin 2942 -> 0 bytes .../__pycache__/scanner.cpython-310.pyc | Bin 3544 -> 0 bytes .../__pycache__/sphinxext.cpython-310.pyc | Bin 4528 -> 0 bytes .../__pycache__/style.cpython-310.pyc | Bin 4565 -> 0 bytes .../__pycache__/token.cpython-310.pyc | Bin 4637 -> 0 bytes .../__pycache__/unistring.cpython-310.pyc | Bin 31191 -> 0 bytes .../pygments/__pycache__/util.cpython-310.pyc | Bin 9133 -> 0 bytes .../pip/_vendor/pygments/cmdline.py | 663 -- .../pip/_vendor/pygments/console.py | 70 - .../pip/_vendor/pygments/filter.py | 71 - .../pip/_vendor/pygments/filters/__init__.py | 937 -- .../__pycache__/__init__.cpython-310.pyc | Bin 29503 -> 0 bytes .../pip/_vendor/pygments/formatter.py | 94 - .../_vendor/pygments/formatters/__init__.py | 153 - .../__pycache__/__init__.cpython-310.pyc | Bin 4654 -> 0 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 5522 -> 0 bytes .../__pycache__/bbcode.cpython-310.pyc | Bin 3071 -> 0 bytes .../__pycache__/groff.cpython-310.pyc | Bin 4384 -> 0 bytes .../__pycache__/html.cpython-310.pyc | Bin 29118 -> 0 bytes .../__pycache__/img.cpython-310.pyc | Bin 17483 -> 0 bytes .../__pycache__/irc.cpython-310.pyc | Bin 4574 -> 0 bytes .../__pycache__/latex.cpython-310.pyc | Bin 13784 -> 0 bytes .../__pycache__/other.cpython-310.pyc | Bin 4790 -> 0 bytes .../__pycache__/pangomarkup.cpython-310.pyc | Bin 2090 -> 0 bytes .../__pycache__/rtf.cpython-310.pyc | Bin 4120 -> 0 bytes .../__pycache__/svg.cpython-310.pyc | Bin 6318 -> 0 bytes .../__pycache__/terminal.cpython-310.pyc | Bin 3985 -> 0 bytes .../__pycache__/terminal256.cpython-310.pyc | Bin 9235 -> 0 bytes .../_vendor/pygments/formatters/_mapping.py | 84 - .../pip/_vendor/pygments/formatters/bbcode.py | 108 - .../pip/_vendor/pygments/formatters/groff.py | 170 - .../pip/_vendor/pygments/formatters/html.py | 989 -- .../pip/_vendor/pygments/formatters/img.py | 641 -- .../pip/_vendor/pygments/formatters/irc.py | 179 - .../pip/_vendor/pygments/formatters/latex.py | 521 - .../pip/_vendor/pygments/formatters/other.py | 161 - .../pygments/formatters/pangomarkup.py | 83 - .../pip/_vendor/pygments/formatters/rtf.py | 146 - .../pip/_vendor/pygments/formatters/svg.py | 188 - .../_vendor/pygments/formatters/terminal.py | 127 - .../pygments/formatters/terminal256.py | 338 - .../pip/_vendor/pygments/lexer.py | 882 -- .../pip/_vendor/pygments/lexers/__init__.py | 345 - .../__pycache__/__init__.cpython-310.pyc | Bin 9340 -> 0 bytes .../__pycache__/_mapping.cpython-310.pyc | Bin 60135 -> 0 bytes .../lexers/__pycache__/python.cpython-310.pyc | Bin 29343 -> 0 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 596 -- .../pip/_vendor/pygments/lexers/python.py | 1191 --- .../pip/_vendor/pygments/modeline.py | 43 - .../pip/_vendor/pygments/plugin.py | 69 - .../pip/_vendor/pygments/regexopt.py | 91 - .../pip/_vendor/pygments/scanner.py | 104 - .../pip/_vendor/pygments/sphinxext.py | 155 - .../pip/_vendor/pygments/style.py | 197 - .../pip/_vendor/pygments/styles/__init__.py | 93 - .../__pycache__/__init__.cpython-310.pyc | Bin 3206 -> 0 bytes .../pip/_vendor/pygments/token.py | 212 - .../pip/_vendor/pygments/unistring.py | 153 - .../pip/_vendor/pygments/util.py | 308 - .../pip/_vendor/pyparsing/__init__.py | 331 - .../__pycache__/__init__.cpython-310.pyc | Bin 7115 -> 0 bytes .../__pycache__/actions.cpython-310.pyc | Bin 7165 -> 0 bytes .../__pycache__/common.cpython-310.pyc | Bin 10091 -> 0 bytes .../__pycache__/core.cpython-310.pyc | Bin 176506 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 9049 -> 0 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 35326 -> 0 bytes .../__pycache__/results.cpython-310.pyc | Bin 24773 -> 0 bytes .../__pycache__/testing.cpython-310.pyc | Bin 12085 -> 0 bytes .../__pycache__/unicode.cpython-310.pyc | Bin 10044 -> 0 bytes .../__pycache__/util.cpython-310.pyc | Bin 8591 -> 0 bytes .../pip/_vendor/pyparsing/actions.py | 207 - .../pip/_vendor/pyparsing/common.py | 424 - .../pip/_vendor/pyparsing/core.py | 5814 ----------- .../pip/_vendor/pyparsing/diagram/__init__.py | 642 -- .../__pycache__/__init__.cpython-310.pyc | Bin 16579 -> 0 bytes .../pip/_vendor/pyparsing/exceptions.py | 267 - .../pip/_vendor/pyparsing/helpers.py | 1088 --- .../pip/_vendor/pyparsing/results.py | 760 -- .../pip/_vendor/pyparsing/testing.py | 331 - .../pip/_vendor/pyparsing/unicode.py | 352 - .../pip/_vendor/pyparsing/util.py | 235 - .../pip/_vendor/requests/__init__.py | 182 - .../__pycache__/__init__.cpython-310.pyc | Bin 4002 -> 0 bytes .../__pycache__/__version__.cpython-310.pyc | Bin 541 -> 0 bytes .../_internal_utils.cpython-310.pyc | Bin 1551 -> 0 bytes .../__pycache__/adapters.cpython-310.pyc | Bin 16885 -> 0 bytes .../requests/__pycache__/api.cpython-310.pyc | Bin 6640 -> 0 bytes .../requests/__pycache__/auth.cpython-310.pyc | Bin 8108 -> 0 bytes .../__pycache__/certs.cpython-310.pyc | Bin 625 -> 0 bytes .../__pycache__/compat.cpython-310.pyc | Bin 1357 -> 0 bytes .../__pycache__/cookies.cpython-310.pyc | Bin 18683 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 5727 -> 0 bytes .../requests/__pycache__/help.cpython-310.pyc | Bin 2853 -> 0 bytes .../__pycache__/hooks.cpython-310.pyc | Bin 980 -> 0 bytes .../__pycache__/models.cpython-310.pyc | Bin 24253 -> 0 bytes .../__pycache__/packages.cpython-310.pyc | Bin 494 -> 0 bytes .../__pycache__/sessions.cpython-310.pyc | Bin 19572 -> 0 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 4659 -> 0 bytes .../__pycache__/structures.cpython-310.pyc | Bin 4424 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 24322 -> 0 bytes .../pip/_vendor/requests/__version__.py | 14 - .../pip/_vendor/requests/_internal_utils.py | 48 - .../pip/_vendor/requests/adapters.py | 584 -- .../site-packages/pip/_vendor/requests/api.py | 157 - .../pip/_vendor/requests/auth.py | 315 - .../pip/_vendor/requests/certs.py | 17 - .../pip/_vendor/requests/compat.py | 67 - .../pip/_vendor/requests/cookies.py | 561 -- .../pip/_vendor/requests/exceptions.py | 141 - .../pip/_vendor/requests/help.py | 131 - .../pip/_vendor/requests/hooks.py | 33 - .../pip/_vendor/requests/models.py | 1034 -- .../pip/_vendor/requests/packages.py | 16 - .../pip/_vendor/requests/sessions.py | 831 -- .../pip/_vendor/requests/status_codes.py | 128 - .../pip/_vendor/requests/structures.py | 99 - .../pip/_vendor/requests/utils.py | 1086 --- .../pip/_vendor/resolvelib/__init__.py | 26 - .../__pycache__/__init__.cpython-310.pyc | Bin 592 -> 0 bytes .../__pycache__/providers.cpython-310.pyc | Bin 6643 -> 0 bytes .../__pycache__/reporters.cpython-310.pyc | Bin 2563 -> 0 bytes .../__pycache__/resolvers.cpython-310.pyc | Bin 15116 -> 0 bytes .../__pycache__/structs.cpython-310.pyc | Bin 7149 -> 0 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 187 -> 0 bytes .../collections_abc.cpython-310.pyc | Bin 363 -> 0 bytes .../resolvelib/compat/collections_abc.py | 6 - .../pip/_vendor/resolvelib/providers.py | 133 - .../pip/_vendor/resolvelib/reporters.py | 43 - .../pip/_vendor/resolvelib/resolvers.py | 482 - .../pip/_vendor/resolvelib/structs.py | 165 - .../pip/_vendor/rich/__init__.py | 176 - .../pip/_vendor/rich/__main__.py | 282 - .../rich/__pycache__/__init__.cpython-310.pyc | Bin 5960 -> 0 bytes .../rich/__pycache__/__main__.cpython-310.pyc | Bin 7282 -> 0 bytes .../__pycache__/_cell_widths.cpython-310.pyc | Bin 7800 -> 0 bytes .../__pycache__/_emoji_codes.cpython-310.pyc | Bin 360040 -> 0 bytes .../_emoji_replace.cpython-310.pyc | Bin 1180 -> 0 bytes .../_export_format.cpython-310.pyc | Bin 2297 -> 0 bytes .../__pycache__/_extension.cpython-310.pyc | Bin 481 -> 0 bytes .../rich/__pycache__/_inspect.cpython-310.pyc | Bin 8658 -> 0 bytes .../__pycache__/_log_render.cpython-310.pyc | Bin 2626 -> 0 bytes .../rich/__pycache__/_loop.cpython-310.pyc | Bin 1278 -> 0 bytes .../__pycache__/_palettes.cpython-310.pyc | Bin 5083 -> 0 bytes .../rich/__pycache__/_pick.cpython-310.pyc | Bin 626 -> 0 bytes .../rich/__pycache__/_ratio.cpython-310.pyc | Bin 5145 -> 0 bytes .../__pycache__/_spinners.cpython-310.pyc | Bin 12257 -> 0 bytes .../rich/__pycache__/_stack.cpython-310.pyc | Bin 824 -> 0 bytes .../rich/__pycache__/_timer.cpython-310.pyc | Bin 673 -> 0 bytes .../_win32_console.cpython-310.pyc | Bin 18993 -> 0 bytes .../rich/__pycache__/_windows.cpython-310.pyc | Bin 1775 -> 0 bytes .../_windows_renderer.cpython-310.pyc | Bin 2029 -> 0 bytes .../rich/__pycache__/_wrap.cpython-310.pyc | Bin 1537 -> 0 bytes .../rich/__pycache__/abc.cpython-310.pyc | Bin 1300 -> 0 bytes .../rich/__pycache__/align.cpython-310.pyc | Bin 7935 -> 0 bytes .../rich/__pycache__/ansi.cpython-310.pyc | Bin 5942 -> 0 bytes .../rich/__pycache__/bar.cpython-310.pyc | Bin 2969 -> 0 bytes .../rich/__pycache__/box.cpython-310.pyc | Bin 8389 -> 0 bytes .../rich/__pycache__/cells.cpython-310.pyc | Bin 3959 -> 0 bytes .../rich/__pycache__/color.cpython-310.pyc | Bin 17447 -> 0 bytes .../__pycache__/color_triplet.cpython-310.pyc | Bin 1423 -> 0 bytes .../rich/__pycache__/columns.cpython-310.pyc | Bin 6183 -> 0 bytes .../rich/__pycache__/console.cpython-310.pyc | Bin 80943 -> 0 bytes .../__pycache__/constrain.cpython-310.pyc | Bin 1740 -> 0 bytes .../__pycache__/containers.cpython-310.pyc | Bin 6472 -> 0 bytes .../rich/__pycache__/control.cpython-310.pyc | Bin 8145 -> 0 bytes .../default_styles.cpython-310.pyc | Bin 6184 -> 0 bytes .../rich/__pycache__/diagnose.cpython-310.pyc | Bin 1207 -> 0 bytes .../rich/__pycache__/emoji.cpython-310.pyc | Bin 3253 -> 0 bytes .../rich/__pycache__/errors.cpython-310.pyc | Bin 1513 -> 0 bytes .../__pycache__/file_proxy.cpython-310.pyc | Bin 2246 -> 0 bytes .../rich/__pycache__/filesize.cpython-310.pyc | Bin 2602 -> 0 bytes .../__pycache__/highlighter.cpython-310.pyc | Bin 8046 -> 0 bytes .../rich/__pycache__/json.cpython-310.pyc | Bin 4733 -> 0 bytes .../rich/__pycache__/jupyter.cpython-310.pyc | Bin 3985 -> 0 bytes .../rich/__pycache__/layout.cpython-310.pyc | Bin 14672 -> 0 bytes .../rich/__pycache__/live.cpython-310.pyc | Bin 11610 -> 0 bytes .../__pycache__/live_render.cpython-310.pyc | Bin 3388 -> 0 bytes .../rich/__pycache__/logging.cpython-310.pyc | Bin 9759 -> 0 bytes .../rich/__pycache__/markup.cpython-310.pyc | Bin 5927 -> 0 bytes .../rich/__pycache__/measure.cpython-310.pyc | Bin 5062 -> 0 bytes .../rich/__pycache__/padding.cpython-310.pyc | Bin 4468 -> 0 bytes .../rich/__pycache__/pager.cpython-310.pyc | Bin 1462 -> 0 bytes .../rich/__pycache__/palette.cpython-310.pyc | Bin 3694 -> 0 bytes .../rich/__pycache__/panel.cpython-310.pyc | Bin 6405 -> 0 bytes .../rich/__pycache__/pretty.cpython-310.pyc | Bin 27389 -> 0 bytes .../rich/__pycache__/progress.cpython-310.pyc | Bin 53888 -> 0 bytes .../__pycache__/progress_bar.cpython-310.pyc | Bin 6893 -> 0 bytes .../rich/__pycache__/prompt.cpython-310.pyc | Bin 11287 -> 0 bytes .../rich/__pycache__/protocol.cpython-310.pyc | Bin 1338 -> 0 bytes .../rich/__pycache__/region.cpython-310.pyc | Bin 513 -> 0 bytes .../rich/__pycache__/repr.cpython-310.pyc | Bin 4101 -> 0 bytes .../rich/__pycache__/rule.cpython-310.pyc | Bin 4295 -> 0 bytes .../rich/__pycache__/scope.cpython-310.pyc | Bin 2974 -> 0 bytes .../rich/__pycache__/screen.cpython-310.pyc | Bin 1865 -> 0 bytes .../rich/__pycache__/segment.cpython-310.pyc | Bin 20743 -> 0 bytes .../rich/__pycache__/spinner.cpython-310.pyc | Bin 4403 -> 0 bytes .../rich/__pycache__/status.cpython-310.pyc | Bin 4579 -> 0 bytes .../rich/__pycache__/style.cpython-310.pyc | Bin 20775 -> 0 bytes .../rich/__pycache__/styled.cpython-310.pyc | Bin 1749 -> 0 bytes .../rich/__pycache__/syntax.cpython-310.pyc | Bin 25348 -> 0 bytes .../rich/__pycache__/table.cpython-310.pyc | Bin 29715 -> 0 bytes .../terminal_theme.cpython-310.pyc | Bin 3002 -> 0 bytes .../rich/__pycache__/text.cpython-310.pyc | Bin 39406 -> 0 bytes .../rich/__pycache__/theme.cpython-310.pyc | Bin 4686 -> 0 bytes .../rich/__pycache__/themes.cpython-310.pyc | Bin 279 -> 0 bytes .../__pycache__/traceback.cpython-310.pyc | Bin 19635 -> 0 bytes .../rich/__pycache__/tree.cpython-310.pyc | Bin 7320 -> 0 bytes .../pip/_vendor/rich/_cell_widths.py | 451 - .../pip/_vendor/rich/_emoji_codes.py | 3610 ------- .../pip/_vendor/rich/_emoji_replace.py | 32 - .../pip/_vendor/rich/_export_format.py | 78 - .../pip/_vendor/rich/_extension.py | 10 - .../pip/_vendor/rich/_inspect.py | 270 - .../pip/_vendor/rich/_log_render.py | 94 - .../site-packages/pip/_vendor/rich/_loop.py | 43 - .../pip/_vendor/rich/_palettes.py | 309 - .../site-packages/pip/_vendor/rich/_pick.py | 17 - .../site-packages/pip/_vendor/rich/_ratio.py | 160 - .../pip/_vendor/rich/_spinners.py | 482 - .../site-packages/pip/_vendor/rich/_stack.py | 16 - .../site-packages/pip/_vendor/rich/_timer.py | 19 - .../pip/_vendor/rich/_win32_console.py | 662 -- .../pip/_vendor/rich/_windows.py | 72 - .../pip/_vendor/rich/_windows_renderer.py | 56 - .../site-packages/pip/_vendor/rich/_wrap.py | 56 - .../Lib/site-packages/pip/_vendor/rich/abc.py | 33 - .../site-packages/pip/_vendor/rich/align.py | 311 - .../site-packages/pip/_vendor/rich/ansi.py | 237 - .../Lib/site-packages/pip/_vendor/rich/bar.py | 94 - .../Lib/site-packages/pip/_vendor/rich/box.py | 517 - .../site-packages/pip/_vendor/rich/cells.py | 154 - .../site-packages/pip/_vendor/rich/color.py | 615 -- .../pip/_vendor/rich/color_triplet.py | 38 - .../site-packages/pip/_vendor/rich/columns.py | 187 - .../site-packages/pip/_vendor/rich/console.py | 2572 ----- .../pip/_vendor/rich/constrain.py | 37 - .../pip/_vendor/rich/containers.py | 167 - .../site-packages/pip/_vendor/rich/control.py | 225 - .../pip/_vendor/rich/default_styles.py | 188 - .../pip/_vendor/rich/diagnose.py | 37 - .../site-packages/pip/_vendor/rich/emoji.py | 96 - .../site-packages/pip/_vendor/rich/errors.py | 34 - .../pip/_vendor/rich/file_proxy.py | 54 - .../pip/_vendor/rich/filesize.py | 89 - .../pip/_vendor/rich/highlighter.py | 232 - .../site-packages/pip/_vendor/rich/json.py | 140 - .../site-packages/pip/_vendor/rich/jupyter.py | 101 - .../site-packages/pip/_vendor/rich/layout.py | 445 - .../site-packages/pip/_vendor/rich/live.py | 373 - .../pip/_vendor/rich/live_render.py | 113 - .../site-packages/pip/_vendor/rich/logging.py | 280 - .../site-packages/pip/_vendor/rich/markup.py | 246 - .../site-packages/pip/_vendor/rich/measure.py | 151 - .../site-packages/pip/_vendor/rich/padding.py | 141 - .../site-packages/pip/_vendor/rich/pager.py | 34 - .../site-packages/pip/_vendor/rich/palette.py | 100 - .../site-packages/pip/_vendor/rich/panel.py | 251 - .../site-packages/pip/_vendor/rich/pretty.py | 1010 -- .../pip/_vendor/rich/progress.py | 1703 ---- .../pip/_vendor/rich/progress_bar.py | 224 - .../site-packages/pip/_vendor/rich/prompt.py | 376 - .../pip/_vendor/rich/protocol.py | 42 - .../site-packages/pip/_vendor/rich/region.py | 10 - .../site-packages/pip/_vendor/rich/repr.py | 152 - .../site-packages/pip/_vendor/rich/rule.py | 134 - .../site-packages/pip/_vendor/rich/scope.py | 86 - .../site-packages/pip/_vendor/rich/screen.py | 54 - .../site-packages/pip/_vendor/rich/segment.py | 739 -- .../site-packages/pip/_vendor/rich/spinner.py | 136 - .../site-packages/pip/_vendor/rich/status.py | 132 - .../site-packages/pip/_vendor/rich/style.py | 771 -- .../site-packages/pip/_vendor/rich/styled.py | 42 - .../site-packages/pip/_vendor/rich/syntax.py | 934 -- .../site-packages/pip/_vendor/rich/table.py | 996 -- .../pip/_vendor/rich/terminal_theme.py | 153 - .../site-packages/pip/_vendor/rich/text.py | 1286 --- .../site-packages/pip/_vendor/rich/theme.py | 112 - .../site-packages/pip/_vendor/rich/themes.py | 5 - .../pip/_vendor/rich/traceback.py | 679 -- .../site-packages/pip/_vendor/rich/tree.py | 251 - venv/Lib/site-packages/pip/_vendor/six.py | 998 -- .../pip/_vendor/tenacity/__init__.py | 517 - .../__pycache__/__init__.cpython-310.pyc | Bin 16360 -> 0 bytes .../__pycache__/_asyncio.cpython-310.pyc | Bin 2600 -> 0 bytes .../__pycache__/_utils.cpython-310.pyc | Bin 1213 -> 0 bytes .../__pycache__/after.cpython-310.pyc | Bin 1217 -> 0 bytes .../__pycache__/before.cpython-310.pyc | Bin 1095 -> 0 bytes .../__pycache__/before_sleep.cpython-310.pyc | Bin 1397 -> 0 bytes .../tenacity/__pycache__/nap.cpython-310.pyc | Bin 1185 -> 0 bytes .../__pycache__/retry.cpython-310.pyc | Bin 8415 -> 0 bytes .../tenacity/__pycache__/stop.cpython-310.pyc | Bin 4003 -> 0 bytes .../__pycache__/tornadoweb.cpython-310.pyc | Bin 1750 -> 0 bytes .../tenacity/__pycache__/wait.cpython-310.pyc | Bin 7947 -> 0 bytes .../pip/_vendor/tenacity/_asyncio.py | 92 - .../pip/_vendor/tenacity/_utils.py | 68 - .../pip/_vendor/tenacity/after.py | 46 - .../pip/_vendor/tenacity/before.py | 41 - .../pip/_vendor/tenacity/before_sleep.py | 58 - .../site-packages/pip/_vendor/tenacity/nap.py | 43 - .../pip/_vendor/tenacity/retry.py | 213 - .../pip/_vendor/tenacity/stop.py | 96 - .../pip/_vendor/tenacity/tornadoweb.py | 59 - .../pip/_vendor/tenacity/wait.py | 191 - .../pip/_vendor/tomli/__init__.py | 11 - .../__pycache__/__init__.cpython-310.pyc | Bin 341 -> 0 bytes .../tomli/__pycache__/_parser.cpython-310.pyc | Bin 17055 -> 0 bytes .../tomli/__pycache__/_re.cpython-310.pyc | Bin 2887 -> 0 bytes .../tomli/__pycache__/_types.cpython-310.pyc | Bin 311 -> 0 bytes .../pip/_vendor/tomli/_parser.py | 691 -- .../site-packages/pip/_vendor/tomli/_re.py | 107 - .../site-packages/pip/_vendor/tomli/_types.py | 10 - .../pip/_vendor/typing_extensions.py | 2069 ---- .../pip/_vendor/urllib3/__init__.py | 85 - .../__pycache__/__init__.cpython-310.pyc | Bin 2175 -> 0 bytes .../__pycache__/_collections.cpython-310.pyc | Bin 10849 -> 0 bytes .../__pycache__/_version.cpython-310.pyc | Bin 200 -> 0 bytes .../__pycache__/connection.cpython-310.pyc | Bin 13629 -> 0 bytes .../connectionpool.cpython-310.pyc | Bin 25391 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 10980 -> 0 bytes .../__pycache__/fields.cpython-310.pyc | Bin 8171 -> 0 bytes .../__pycache__/filepost.cpython-310.pyc | Bin 2736 -> 0 bytes .../__pycache__/poolmanager.cpython-310.pyc | Bin 15205 -> 0 bytes .../__pycache__/request.cpython-310.pyc | Bin 5612 -> 0 bytes .../__pycache__/response.cpython-310.pyc | Bin 20860 -> 0 bytes .../pip/_vendor/urllib3/_collections.py | 337 - .../pip/_vendor/urllib3/_version.py | 2 - .../pip/_vendor/urllib3/connection.py | 567 -- .../pip/_vendor/urllib3/connectionpool.py | 1110 --- .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 185 -> 0 bytes .../_appengine_environ.cpython-310.pyc | Bin 1365 -> 0 bytes .../__pycache__/appengine.cpython-310.pyc | Bin 8181 -> 0 bytes .../__pycache__/ntlmpool.cpython-310.pyc | Bin 3620 -> 0 bytes .../__pycache__/pyopenssl.cpython-310.pyc | Bin 15524 -> 0 bytes .../securetransport.cpython-310.pyc | Bin 21927 -> 0 bytes .../contrib/__pycache__/socks.cpython-310.pyc | Bin 5587 -> 0 bytes .../urllib3/contrib/_appengine_environ.py | 36 - .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 202 -> 0 bytes .../__pycache__/bindings.cpython-310.pyc | Bin 10698 -> 0 bytes .../__pycache__/low_level.cpython-310.pyc | Bin 9085 -> 0 bytes .../contrib/_securetransport/bindings.py | 519 - .../contrib/_securetransport/low_level.py | 397 - .../pip/_vendor/urllib3/contrib/appengine.py | 314 - .../pip/_vendor/urllib3/contrib/ntlmpool.py | 130 - .../pip/_vendor/urllib3/contrib/pyopenssl.py | 510 - .../urllib3/contrib/securetransport.py | 921 -- .../pip/_vendor/urllib3/contrib/socks.py | 216 - .../pip/_vendor/urllib3/exceptions.py | 323 - .../pip/_vendor/urllib3/fields.py | 274 - .../pip/_vendor/urllib3/filepost.py | 98 - .../pip/_vendor/urllib3/packages/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 186 -> 0 bytes .../packages/__pycache__/six.cpython-310.pyc | Bin 27646 -> 0 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 196 -> 0 bytes .../__pycache__/makefile.cpython-310.pyc | Bin 1296 -> 0 bytes .../urllib3/packages/backports/makefile.py | 51 - .../pip/_vendor/urllib3/packages/six.py | 1076 -- .../pip/_vendor/urllib3/poolmanager.py | 537 - .../pip/_vendor/urllib3/request.py | 170 - .../pip/_vendor/urllib3/response.py | 818 -- .../pip/_vendor/urllib3/util/__init__.py | 49 - .../util/__pycache__/__init__.cpython-310.pyc | Bin 1095 -> 0 bytes .../__pycache__/connection.cpython-310.pyc | Bin 3423 -> 0 bytes .../util/__pycache__/proxy.cpython-310.pyc | Bin 1330 -> 0 bytes .../util/__pycache__/queue.cpython-310.pyc | Bin 1050 -> 0 bytes .../util/__pycache__/request.cpython-310.pyc | Bin 3357 -> 0 bytes .../util/__pycache__/response.cpython-310.pyc | Bin 2343 -> 0 bytes .../util/__pycache__/retry.cpython-310.pyc | Bin 16128 -> 0 bytes .../util/__pycache__/ssl_.cpython-310.pyc | Bin 11297 -> 0 bytes .../ssl_match_hostname.cpython-310.pyc | Bin 3247 -> 0 bytes .../__pycache__/ssltransport.cpython-310.pyc | Bin 7385 -> 0 bytes .../util/__pycache__/timeout.cpython-310.pyc | Bin 8927 -> 0 bytes .../util/__pycache__/url.cpython-310.pyc | Bin 10683 -> 0 bytes .../util/__pycache__/wait.cpython-310.pyc | Bin 3079 -> 0 bytes .../pip/_vendor/urllib3/util/connection.py | 149 - .../pip/_vendor/urllib3/util/proxy.py | 57 - .../pip/_vendor/urllib3/util/queue.py | 22 - .../pip/_vendor/urllib3/util/request.py | 137 - .../pip/_vendor/urllib3/util/response.py | 107 - .../pip/_vendor/urllib3/util/retry.py | 620 -- .../pip/_vendor/urllib3/util/ssl_.py | 495 - .../urllib3/util/ssl_match_hostname.py | 159 - .../pip/_vendor/urllib3/util/ssltransport.py | 221 - .../pip/_vendor/urllib3/util/timeout.py | 268 - .../pip/_vendor/urllib3/util/url.py | 435 - .../pip/_vendor/urllib3/util/wait.py | 152 - venv/Lib/site-packages/pip/_vendor/vendor.txt | 23 - .../pip/_vendor/webencodings/__init__.py | 342 - .../__pycache__/__init__.cpython-310.pyc | Bin 9732 -> 0 bytes .../__pycache__/labels.cpython-310.pyc | Bin 5222 -> 0 bytes .../__pycache__/mklabels.cpython-310.pyc | Bin 1927 -> 0 bytes .../__pycache__/tests.cpython-310.pyc | Bin 5029 -> 0 bytes .../x_user_defined.cpython-310.pyc | Bin 2578 -> 0 bytes .../pip/_vendor/webencodings/labels.py | 231 - .../pip/_vendor/webencodings/mklabels.py | 59 - .../pip/_vendor/webencodings/tests.py | 153 - .../_vendor/webencodings/x_user_defined.py | 325 - venv/Lib/site-packages/pip/py.typed | 4 - .../site-packages/pkg_resources/__init__.py | 3296 ------- .../__pycache__/__init__.cpython-310.pyc | Bin 100561 -> 0 bytes .../pkg_resources/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 179 -> 0 bytes .../__pycache__/appdirs.cpython-310.pyc | Bin 20240 -> 0 bytes .../_vendor/__pycache__/zipp.cpython-310.pyc | Bin 10222 -> 0 bytes .../pkg_resources/_vendor/appdirs.py | 608 -- .../_vendor/importlib_resources/__init__.py | 36 - .../__pycache__/__init__.cpython-310.pyc | Bin 634 -> 0 bytes .../__pycache__/_adapters.cpython-310.pyc | Bin 7342 -> 0 bytes .../__pycache__/_common.cpython-310.pyc | Bin 2632 -> 0 bytes .../__pycache__/_compat.cpython-310.pyc | Bin 3492 -> 0 bytes .../__pycache__/_itertools.cpython-310.pyc | Bin 879 -> 0 bytes .../__pycache__/_legacy.cpython-310.pyc | Bin 4215 -> 0 bytes .../__pycache__/abc.cpython-310.pyc | Bin 5368 -> 0 bytes .../__pycache__/readers.cpython-310.pyc | Bin 5452 -> 0 bytes .../__pycache__/simple.cpython-310.pyc | Bin 4720 -> 0 bytes .../_vendor/importlib_resources/_adapters.py | 170 - .../_vendor/importlib_resources/_common.py | 104 - .../_vendor/importlib_resources/_compat.py | 98 - .../_vendor/importlib_resources/_itertools.py | 35 - .../_vendor/importlib_resources/_legacy.py | 121 - .../_vendor/importlib_resources/abc.py | 137 - .../_vendor/importlib_resources/readers.py | 122 - .../_vendor/importlib_resources/simple.py | 116 - .../pkg_resources/_vendor/jaraco/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 186 -> 0 bytes .../__pycache__/context.cpython-310.pyc | Bin 6318 -> 0 bytes .../__pycache__/functools.cpython-310.pyc | Bin 15610 -> 0 bytes .../pkg_resources/_vendor/jaraco/context.py | 213 - .../pkg_resources/_vendor/jaraco/functools.py | 525 - .../_vendor/jaraco/text/__init__.py | 599 -- .../text/__pycache__/__init__.cpython-310.pyc | Bin 19655 -> 0 bytes .../_vendor/more_itertools/__init__.py | 4 - .../__pycache__/__init__.cpython-310.pyc | Bin 261 -> 0 bytes .../__pycache__/more.cpython-310.pyc | Bin 123046 -> 0 bytes .../__pycache__/recipes.cpython-310.pyc | Bin 20322 -> 0 bytes .../_vendor/more_itertools/more.py | 4316 -------- .../_vendor/more_itertools/recipes.py | 698 -- .../_vendor/packaging/__about__.py | 26 - .../_vendor/packaging/__init__.py | 25 - .../__pycache__/__about__.cpython-310.pyc | Bin 586 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 442 -> 0 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 7296 -> 0 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 4608 -> 0 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 2701 -> 0 bytes .../__pycache__/markers.cpython-310.pyc | Bin 9294 -> 0 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 3980 -> 0 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 21523 -> 0 bytes .../__pycache__/tags.cpython-310.pyc | Bin 12192 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 3571 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 12921 -> 0 bytes .../_vendor/packaging/_manylinux.py | 301 - .../_vendor/packaging/_musllinux.py | 136 - .../_vendor/packaging/_structures.py | 61 - .../_vendor/packaging/markers.py | 304 - .../_vendor/packaging/requirements.py | 146 - .../_vendor/packaging/specifiers.py | 802 -- .../pkg_resources/_vendor/packaging/tags.py | 487 - .../pkg_resources/_vendor/packaging/utils.py | 136 - .../_vendor/packaging/version.py | 504 - .../_vendor/pyparsing/__init__.py | 331 - .../__pycache__/__init__.cpython-310.pyc | Bin 7113 -> 0 bytes .../__pycache__/actions.cpython-310.pyc | Bin 7178 -> 0 bytes .../__pycache__/common.cpython-310.pyc | Bin 10101 -> 0 bytes .../__pycache__/core.cpython-310.pyc | Bin 176390 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 9068 -> 0 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 35245 -> 0 bytes .../__pycache__/results.cpython-310.pyc | Bin 24795 -> 0 bytes .../__pycache__/testing.cpython-310.pyc | Bin 12098 -> 0 bytes .../__pycache__/unicode.cpython-310.pyc | Bin 9810 -> 0 bytes .../__pycache__/util.cpython-310.pyc | Bin 8601 -> 0 bytes .../_vendor/pyparsing/actions.py | 207 - .../pkg_resources/_vendor/pyparsing/common.py | 424 - .../pkg_resources/_vendor/pyparsing/core.py | 5812 ----------- .../_vendor/pyparsing/diagram/__init__.py | 611 -- .../__pycache__/__init__.cpython-310.pyc | Bin 16059 -> 0 bytes .../_vendor/pyparsing/exceptions.py | 267 - .../_vendor/pyparsing/helpers.py | 1083 -- .../_vendor/pyparsing/results.py | 760 -- .../_vendor/pyparsing/testing.py | 331 - .../_vendor/pyparsing/unicode.py | 332 - .../pkg_resources/_vendor/pyparsing/util.py | 235 - .../pkg_resources/_vendor/zipp.py | 329 - .../pkg_resources/extern/__init__.py | 76 - .../__pycache__/__init__.cpython-310.pyc | Bin 2932 -> 0 bytes .../pymongo-4.12.1.dist-info/INSTALLER | 1 - .../pymongo-4.12.1.dist-info/METADATA | 479 - .../pymongo-4.12.1.dist-info/RECORD | 303 - .../pymongo-4.12.1.dist-info/REQUESTED | 0 .../pymongo-4.12.1.dist-info/WHEEL | 4 - .../pymongo-4.12.1.dist-info/licenses/LICENSE | 201 - venv/Lib/site-packages/pymongo/__init__.py | 178 - .../__pycache__/__init__.cpython-310.pyc | Bin 4035 -> 0 bytes .../__pycache__/_asyncio_lock.cpython-310.pyc | Bin 9741 -> 0 bytes .../__pycache__/_asyncio_task.cpython-310.pyc | Bin 1836 -> 0 bytes .../_azure_helpers.cpython-310.pyc | Bin 1509 -> 0 bytes .../_client_bulk_shared.cpython-310.pyc | Bin 2308 -> 0 bytes .../pymongo/__pycache__/_csot.cpython-310.pyc | Bin 5586 -> 0 bytes .../__pycache__/_gcp_helpers.cpython-310.pyc | Bin 1127 -> 0 bytes .../__pycache__/_version.cpython-310.pyc | Bin 1285 -> 0 bytes .../pymongo/__pycache__/auth.cpython-310.pyc | Bin 389 -> 0 bytes .../__pycache__/auth_oidc.cpython-310.pyc | Bin 497 -> 0 bytes .../auth_oidc_shared.cpython-310.pyc | Bin 5165 -> 0 bytes .../__pycache__/auth_shared.cpython-310.pyc | Bin 6729 -> 0 bytes .../__pycache__/bulk_shared.cpython-310.pyc | Bin 3820 -> 0 bytes .../__pycache__/change_stream.cpython-310.pyc | Bin 486 -> 0 bytes .../client_options.cpython-310.pyc | Bin 11566 -> 0 bytes .../client_session.cpython-310.pyc | Bin 459 -> 0 bytes .../__pycache__/collation.cpython-310.pyc | Bin 7122 -> 0 bytes .../__pycache__/collection.cpython-310.pyc | Bin 427 -> 0 bytes .../command_cursor.cpython-310.pyc | Bin 444 -> 0 bytes .../__pycache__/common.cpython-310.pyc | Bin 31633 -> 0 bytes .../compression_support.cpython-310.pyc | Bin 4721 -> 0 bytes .../__pycache__/cursor.cpython-310.pyc | Bin 454 -> 0 bytes .../__pycache__/cursor_shared.cpython-310.pyc | Bin 1043 -> 0 bytes .../__pycache__/daemon.cpython-310.pyc | Bin 3176 -> 0 bytes .../__pycache__/database.cpython-310.pyc | Bin 397 -> 0 bytes .../database_shared.cpython-310.pyc | Bin 855 -> 0 bytes .../__pycache__/driver_info.cpython-310.pyc | Bin 1594 -> 0 bytes .../__pycache__/encryption.cpython-310.pyc | Bin 462 -> 0 bytes .../encryption_options.cpython-310.pyc | Bin 13434 -> 0 bytes .../__pycache__/errors.cpython-310.pyc | Bin 17357 -> 0 bytes .../__pycache__/event_loggers.cpython-310.pyc | Bin 9947 -> 0 bytes .../pymongo/__pycache__/hello.cpython-310.pyc | Bin 7394 -> 0 bytes .../helpers_shared.cpython-310.pyc | Bin 7343 -> 0 bytes .../pymongo/__pycache__/lock.cpython-310.pyc | Bin 2392 -> 0 bytes .../__pycache__/logger.cpython-310.pyc | Bin 6808 -> 0 bytes .../max_staleness_selectors.cpython-310.pyc | Bin 2773 -> 0 bytes .../__pycache__/message.cpython-310.pyc | Bin 43064 -> 0 bytes .../__pycache__/mongo_client.cpython-310.pyc | Bin 411 -> 0 bytes .../__pycache__/monitoring.cpython-310.pyc | Bin 64148 -> 0 bytes .../__pycache__/network_layer.cpython-310.pyc | Bin 20625 -> 0 bytes .../__pycache__/ocsp_cache.cpython-310.pyc | Bin 3437 -> 0 bytes .../__pycache__/ocsp_support.cpython-310.pyc | Bin 11428 -> 0 bytes .../__pycache__/operations.cpython-310.pyc | Bin 27386 -> 0 bytes .../periodic_executor.cpython-310.pyc | Bin 7599 -> 0 bytes .../pymongo/__pycache__/pool.cpython-310.pyc | Bin 388 -> 0 bytes .../__pycache__/pool_options.cpython-310.pyc | Bin 13558 -> 0 bytes .../__pycache__/pool_shared.cpython-310.pyc | Bin 11129 -> 0 bytes .../pyopenssl_context.cpython-310.pyc | Bin 13203 -> 0 bytes .../__pycache__/read_concern.cpython-310.pyc | Bin 2628 -> 0 bytes .../read_preferences.cpython-310.pyc | Bin 21915 -> 0 bytes .../__pycache__/response.cpython-310.pyc | Bin 4450 -> 0 bytes .../__pycache__/results.cpython-310.pyc | Bin 14031 -> 0 bytes .../__pycache__/saslprep.cpython-310.pyc | Bin 2527 -> 0 bytes .../__pycache__/server_api.cpython-310.pyc | Bin 5802 -> 0 bytes .../server_description.cpython-310.pyc | Bin 9536 -> 0 bytes .../server_selectors.cpython-310.pyc | Bin 6499 -> 0 bytes .../__pycache__/server_type.cpython-310.pyc | Bin 712 -> 0 bytes .../socket_checker.cpython-310.pyc | Bin 2400 -> 0 bytes .../__pycache__/ssl_context.cpython-310.pyc | Bin 802 -> 0 bytes .../__pycache__/ssl_support.cpython-310.pyc | Bin 3378 -> 0 bytes .../topology_description.cpython-310.pyc | Bin 18718 -> 0 bytes .../__pycache__/typings.cpython-310.pyc | Bin 1989 -> 0 bytes .../__pycache__/uri_parser.cpython-310.pyc | Bin 790 -> 0 bytes .../uri_parser_shared.cpython-310.pyc | Bin 14740 -> 0 bytes .../__pycache__/write_concern.cpython-310.pyc | Bin 5207 -> 0 bytes .../site-packages/pymongo/_asyncio_lock.py | 309 - .../site-packages/pymongo/_asyncio_task.py | 49 - .../site-packages/pymongo/_azure_helpers.py | 57 - .../pymongo/_client_bulk_shared.py | 79 - .../pymongo/_cmessage.cp310-win_amd64.pyd | Bin 56832 -> 0 bytes .../pymongo/_cmessage.cp39-win_amd64.pyd | Bin 56832 -> 0 bytes .../site-packages/pymongo/_cmessagemodule.c | 1049 -- venv/Lib/site-packages/pymongo/_csot.py | 161 - .../Lib/site-packages/pymongo/_gcp_helpers.py | 40 - venv/Lib/site-packages/pymongo/_version.py | 43 - .../pymongo/asynchronous/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 178 -> 0 bytes .../__pycache__/aggregation.cpython-310.pyc | Bin 7952 -> 0 bytes .../__pycache__/auth.cpython-310.pyc | Bin 11256 -> 0 bytes .../__pycache__/auth_aws.cpython-310.pyc | Bin 2995 -> 0 bytes .../__pycache__/auth_oidc.cpython-310.pyc | Bin 7690 -> 0 bytes .../__pycache__/bulk.cpython-310.pyc | Bin 16217 -> 0 bytes .../__pycache__/change_stream.cpython-310.pyc | Bin 16594 -> 0 bytes .../__pycache__/client_bulk.cpython-310.pyc | Bin 16602 -> 0 bytes .../client_session.cpython-310.pyc | Bin 40280 -> 0 bytes .../__pycache__/collection.cpython-310.pyc | Bin 126694 -> 0 bytes .../command_cursor.cpython-310.pyc | Bin 14849 -> 0 bytes .../__pycache__/cursor.cpython-310.pyc | Bin 41943 -> 0 bytes .../__pycache__/database.cpython-310.pyc | Bin 50005 -> 0 bytes .../__pycache__/encryption.cpython-310.pyc | Bin 42218 -> 0 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 2304 -> 0 bytes .../__pycache__/mongo_client.cpython-310.pyc | Bin 106438 -> 0 bytes .../__pycache__/monitor.cpython-310.pyc | Bin 15118 -> 0 bytes .../__pycache__/network.cpython-310.pyc | Bin 7557 -> 0 bytes .../__pycache__/pool.cpython-310.pyc | Bin 39116 -> 0 bytes .../__pycache__/server.cpython-310.pyc | Bin 9228 -> 0 bytes .../__pycache__/settings.cpython-310.pyc | Bin 6475 -> 0 bytes .../__pycache__/srv_resolver.cpython-310.pyc | Bin 5022 -> 0 bytes .../__pycache__/topology.cpython-310.pyc | Bin 29268 -> 0 bytes .../__pycache__/uri_parser.cpython-310.pyc | Bin 4852 -> 0 bytes .../pymongo/asynchronous/aggregation.py | 257 - .../pymongo/asynchronous/auth.py | 455 - .../pymongo/asynchronous/auth_aws.py | 100 - .../pymongo/asynchronous/auth_oidc.py | 296 - .../pymongo/asynchronous/bulk.py | 753 -- .../pymongo/asynchronous/change_stream.py | 499 - .../pymongo/asynchronous/client_bulk.py | 755 -- .../pymongo/asynchronous/client_session.py | 1175 --- .../pymongo/asynchronous/collection.py | 3617 ------- .../pymongo/asynchronous/command_cursor.py | 472 - .../pymongo/asynchronous/cursor.py | 1370 --- .../pymongo/asynchronous/database.py | 1454 --- .../pymongo/asynchronous/encryption.py | 1236 --- .../pymongo/asynchronous/helpers.py | 102 - .../pymongo/asynchronous/mongo_client.py | 2949 ------ .../pymongo/asynchronous/monitor.py | 544 -- .../pymongo/asynchronous/network.py | 298 - .../pymongo/asynchronous/pool.py | 1477 --- .../pymongo/asynchronous/server.py | 383 - .../pymongo/asynchronous/settings.py | 175 - .../pymongo/asynchronous/srv_resolver.py | 164 - .../pymongo/asynchronous/topology.py | 1127 --- .../pymongo/asynchronous/uri_parser.py | 188 - venv/Lib/site-packages/pymongo/auth.py | 22 - venv/Lib/site-packages/pymongo/auth_oidc.py | 23 - .../site-packages/pymongo/auth_oidc_shared.py | 132 - venv/Lib/site-packages/pymongo/auth_shared.py | 254 - venv/Lib/site-packages/pymongo/bulk_shared.py | 131 - .../site-packages/pymongo/change_stream.py | 22 - .../site-packages/pymongo/client_options.py | 348 - .../site-packages/pymongo/client_session.py | 22 - venv/Lib/site-packages/pymongo/collation.py | 226 - venv/Lib/site-packages/pymongo/collection.py | 25 - .../site-packages/pymongo/command_cursor.py | 22 - venv/Lib/site-packages/pymongo/common.py | 1094 --- .../pymongo/compression_support.py | 175 - venv/Lib/site-packages/pymongo/cursor.py | 23 - .../site-packages/pymongo/cursor_shared.py | 94 - venv/Lib/site-packages/pymongo/daemon.py | 148 - venv/Lib/site-packages/pymongo/database.py | 22 - .../site-packages/pymongo/database_shared.py | 34 - venv/Lib/site-packages/pymongo/driver_info.py | 45 - venv/Lib/site-packages/pymongo/encryption.py | 22 - .../pymongo/encryption_options.py | 297 - venv/Lib/site-packages/pymongo/errors.py | 436 - .../site-packages/pymongo/event_loggers.py | 226 - venv/Lib/site-packages/pymongo/hello.py | 224 - .../site-packages/pymongo/helpers_shared.py | 330 - venv/Lib/site-packages/pymongo/lock.py | 92 - venv/Lib/site-packages/pymongo/logger.py | 189 - .../pymongo/max_staleness_selectors.py | 124 - venv/Lib/site-packages/pymongo/message.py | 1900 ---- .../Lib/site-packages/pymongo/mongo_client.py | 22 - venv/Lib/site-packages/pymongo/monitoring.py | 1905 ---- .../site-packages/pymongo/network_layer.py | 777 -- venv/Lib/site-packages/pymongo/ocsp_cache.py | 131 - .../Lib/site-packages/pymongo/ocsp_support.py | 438 - venv/Lib/site-packages/pymongo/operations.py | 853 -- .../pymongo/periodic_executor.py | 293 - venv/Lib/site-packages/pymongo/pool.py | 22 - .../Lib/site-packages/pymongo/pool_options.py | 524 - venv/Lib/site-packages/pymongo/pool_shared.py | 539 - venv/Lib/site-packages/pymongo/py.typed | 2 - .../pymongo/pyopenssl_context.py | 428 - .../Lib/site-packages/pymongo/read_concern.py | 79 - .../site-packages/pymongo/read_preferences.py | 637 -- venv/Lib/site-packages/pymongo/response.py | 130 - venv/Lib/site-packages/pymongo/results.py | 367 - venv/Lib/site-packages/pymongo/saslprep.py | 116 - venv/Lib/site-packages/pymongo/server_api.py | 173 - .../pymongo/server_description.py | 302 - .../site-packages/pymongo/server_selectors.py | 174 - venv/Lib/site-packages/pymongo/server_type.py | 33 - .../site-packages/pymongo/socket_checker.py | 105 - venv/Lib/site-packages/pymongo/ssl_context.py | 42 - venv/Lib/site-packages/pymongo/ssl_support.py | 141 - .../pymongo/synchronous/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 177 -> 0 bytes .../__pycache__/aggregation.cpython-310.pyc | Bin 7825 -> 0 bytes .../__pycache__/auth.cpython-310.pyc | Bin 11075 -> 0 bytes .../__pycache__/auth_aws.cpython-310.pyc | Bin 2972 -> 0 bytes .../__pycache__/auth_oidc.cpython-310.pyc | Bin 7540 -> 0 bytes .../__pycache__/bulk.cpython-310.pyc | Bin 15886 -> 0 bytes .../__pycache__/change_stream.cpython-310.pyc | Bin 15984 -> 0 bytes .../__pycache__/client_bulk.cpython-310.pyc | Bin 16258 -> 0 bytes .../client_session.cpython-310.pyc | Bin 39375 -> 0 bytes .../__pycache__/collection.cpython-310.pyc | Bin 123380 -> 0 bytes .../command_cursor.cpython-310.pyc | Bin 14310 -> 0 bytes .../__pycache__/cursor.cpython-310.pyc | Bin 40891 -> 0 bytes .../__pycache__/database.cpython-310.pyc | Bin 48623 -> 0 bytes .../__pycache__/encryption.cpython-310.pyc | Bin 41498 -> 0 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 2243 -> 0 bytes .../__pycache__/mongo_client.cpython-310.pyc | Bin 103655 -> 0 bytes .../__pycache__/monitor.cpython-310.pyc | Bin 14703 -> 0 bytes .../__pycache__/network.cpython-310.pyc | Bin 7463 -> 0 bytes .../__pycache__/pool.cpython-310.pyc | Bin 37683 -> 0 bytes .../__pycache__/server.cpython-310.pyc | Bin 9102 -> 0 bytes .../__pycache__/settings.cpython-310.pyc | Bin 6472 -> 0 bytes .../__pycache__/srv_resolver.cpython-310.pyc | Bin 4956 -> 0 bytes .../__pycache__/topology.cpython-310.pyc | Bin 28640 -> 0 bytes .../__pycache__/uri_parser.cpython-310.pyc | Bin 4823 -> 0 bytes .../pymongo/synchronous/aggregation.py | 257 - .../site-packages/pymongo/synchronous/auth.py | 450 - .../pymongo/synchronous/auth_aws.py | 100 - .../pymongo/synchronous/auth_oidc.py | 294 - .../site-packages/pymongo/synchronous/bulk.py | 751 -- .../pymongo/synchronous/change_stream.py | 497 - .../pymongo/synchronous/client_bulk.py | 753 -- .../pymongo/synchronous/client_session.py | 1170 --- .../pymongo/synchronous/collection.py | 3610 ------- .../pymongo/synchronous/command_cursor.py | 472 - .../pymongo/synchronous/cursor.py | 1366 --- .../pymongo/synchronous/database.py | 1447 --- .../pymongo/synchronous/encryption.py | 1229 --- .../pymongo/synchronous/helpers.py | 102 - .../pymongo/synchronous/mongo_client.py | 2935 ------ .../pymongo/synchronous/monitor.py | 542 - .../pymongo/synchronous/network.py | 298 - .../site-packages/pymongo/synchronous/pool.py | 1473 --- .../pymongo/synchronous/server.py | 383 - .../pymongo/synchronous/settings.py | 175 - .../pymongo/synchronous/srv_resolver.py | 164 - .../pymongo/synchronous/topology.py | 1125 --- .../pymongo/synchronous/uri_parser.py | 188 - .../pymongo/topology_description.py | 689 -- venv/Lib/site-packages/pymongo/typings.py | 78 - venv/Lib/site-packages/pymongo/uri_parser.py | 44 - .../pymongo/uri_parser_shared.py | 552 -- .../site-packages/pymongo/write_concern.py | 144 - .../python_dotenv-1.1.0.dist-info/INSTALLER | 1 - .../python_dotenv-1.1.0.dist-info/METADATA | 720 -- .../python_dotenv-1.1.0.dist-info/RECORD | 26 - .../python_dotenv-1.1.0.dist-info/REQUESTED | 0 .../python_dotenv-1.1.0.dist-info/WHEEL | 5 - .../entry_points.txt | 2 - .../licenses/LICENSE | 27 - .../top_level.txt | 1 - .../pytz-2025.2.dist-info/INSTALLER | 1 - .../pytz-2025.2.dist-info/LICENSE.txt | 19 - .../pytz-2025.2.dist-info/METADATA | 648 -- .../pytz-2025.2.dist-info/RECORD | 623 -- .../site-packages/pytz-2025.2.dist-info/WHEEL | 6 - .../pytz-2025.2.dist-info/top_level.txt | 1 - .../pytz-2025.2.dist-info/zip-safe | 1 - venv/Lib/site-packages/pytz/__init__.py | 1556 --- .../pytz/__pycache__/__init__.cpython-310.pyc | Bin 26237 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 2096 -> 0 bytes .../pytz/__pycache__/lazy.cpython-310.pyc | Bin 4711 -> 0 bytes .../__pycache__/reference.cpython-310.pyc | Bin 3844 -> 0 bytes .../pytz/__pycache__/tzfile.cpython-310.pyc | Bin 3129 -> 0 bytes .../pytz/__pycache__/tzinfo.cpython-310.pyc | Bin 14774 -> 0 bytes venv/Lib/site-packages/pytz/exceptions.py | 59 - venv/Lib/site-packages/pytz/lazy.py | 172 - venv/Lib/site-packages/pytz/reference.py | 140 - venv/Lib/site-packages/pytz/tzfile.py | 133 - venv/Lib/site-packages/pytz/tzinfo.py | 580 -- .../pytz/zoneinfo/Africa/Abidjan | Bin 148 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Accra | Bin 148 -> 0 bytes .../pytz/zoneinfo/Africa/Addis_Ababa | Bin 265 -> 0 bytes .../pytz/zoneinfo/Africa/Algiers | Bin 735 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Asmara | Bin 265 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Asmera | Bin 265 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Bamako | Bin 148 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Bangui | Bin 235 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Banjul | Bin 148 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Bissau | Bin 194 -> 0 bytes .../pytz/zoneinfo/Africa/Blantyre | Bin 149 -> 0 bytes .../pytz/zoneinfo/Africa/Brazzaville | Bin 235 -> 0 bytes .../pytz/zoneinfo/Africa/Bujumbura | Bin 149 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Cairo | Bin 2399 -> 0 bytes .../pytz/zoneinfo/Africa/Casablanca | Bin 2429 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Ceuta | Bin 2052 -> 0 bytes .../pytz/zoneinfo/Africa/Conakry | Bin 148 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Dakar | Bin 148 -> 0 bytes .../pytz/zoneinfo/Africa/Dar_es_Salaam | Bin 265 -> 0 bytes .../pytz/zoneinfo/Africa/Djibouti | Bin 265 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Douala | Bin 235 -> 0 bytes .../pytz/zoneinfo/Africa/El_Aaiun | Bin 2295 -> 0 bytes .../pytz/zoneinfo/Africa/Freetown | Bin 148 -> 0 bytes .../pytz/zoneinfo/Africa/Gaborone | Bin 149 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Harare | Bin 149 -> 0 bytes .../pytz/zoneinfo/Africa/Johannesburg | Bin 246 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Juba | Bin 679 -> 0 bytes .../pytz/zoneinfo/Africa/Kampala | Bin 265 -> 0 bytes .../pytz/zoneinfo/Africa/Khartoum | Bin 679 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Kigali | Bin 149 -> 0 bytes .../pytz/zoneinfo/Africa/Kinshasa | Bin 235 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Lagos | Bin 235 -> 0 bytes .../pytz/zoneinfo/Africa/Libreville | Bin 235 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Lome | Bin 148 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Luanda | Bin 235 -> 0 bytes .../pytz/zoneinfo/Africa/Lubumbashi | Bin 149 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Lusaka | Bin 149 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Malabo | Bin 235 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Maputo | Bin 149 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Maseru | Bin 246 -> 0 bytes .../pytz/zoneinfo/Africa/Mbabane | Bin 246 -> 0 bytes .../pytz/zoneinfo/Africa/Mogadishu | Bin 265 -> 0 bytes .../pytz/zoneinfo/Africa/Monrovia | Bin 208 -> 0 bytes .../pytz/zoneinfo/Africa/Nairobi | Bin 265 -> 0 bytes .../pytz/zoneinfo/Africa/Ndjamena | Bin 199 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Niamey | Bin 235 -> 0 bytes .../pytz/zoneinfo/Africa/Nouakchott | Bin 148 -> 0 bytes .../pytz/zoneinfo/Africa/Ouagadougou | Bin 148 -> 0 bytes .../pytz/zoneinfo/Africa/Porto-Novo | Bin 235 -> 0 bytes .../pytz/zoneinfo/Africa/Sao_Tome | Bin 254 -> 0 bytes .../pytz/zoneinfo/Africa/Timbuktu | Bin 148 -> 0 bytes .../pytz/zoneinfo/Africa/Tripoli | Bin 625 -> 0 bytes .../site-packages/pytz/zoneinfo/Africa/Tunis | Bin 689 -> 0 bytes .../pytz/zoneinfo/Africa/Windhoek | Bin 955 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Adak | Bin 2356 -> 0 bytes .../pytz/zoneinfo/America/Anchorage | Bin 2371 -> 0 bytes .../pytz/zoneinfo/America/Anguilla | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Antigua | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Araguaina | Bin 870 -> 0 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Catamarca | Bin 1062 -> 0 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Cordoba | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Jujuy | Bin 1034 -> 0 bytes .../pytz/zoneinfo/America/Argentina/La_Rioja | Bin 1076 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Mendoza | Bin 1062 -> 0 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Salta | Bin 1034 -> 0 bytes .../pytz/zoneinfo/America/Argentina/San_Juan | Bin 1076 -> 0 bytes .../pytz/zoneinfo/America/Argentina/San_Luis | Bin 1088 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Tucuman | Bin 1090 -> 0 bytes .../pytz/zoneinfo/America/Argentina/Ushuaia | Bin 1062 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Aruba | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Asuncion | Bin 1644 -> 0 bytes .../pytz/zoneinfo/America/Atikokan | Bin 182 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Atka | Bin 2356 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Bahia | Bin 1010 -> 0 bytes .../pytz/zoneinfo/America/Bahia_Banderas | Bin 1100 -> 0 bytes .../pytz/zoneinfo/America/Barbados | Bin 436 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Belem | Bin 562 -> 0 bytes .../pytz/zoneinfo/America/Belize | Bin 1614 -> 0 bytes .../pytz/zoneinfo/America/Blanc-Sablon | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Boa_Vista | Bin 618 -> 0 bytes .../pytz/zoneinfo/America/Bogota | Bin 232 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Boise | Bin 2410 -> 0 bytes .../pytz/zoneinfo/America/Buenos_Aires | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Cambridge_Bay | Bin 2254 -> 0 bytes .../pytz/zoneinfo/America/Campo_Grande | Bin 1430 -> 0 bytes .../pytz/zoneinfo/America/Cancun | Bin 864 -> 0 bytes .../pytz/zoneinfo/America/Caracas | Bin 250 -> 0 bytes .../pytz/zoneinfo/America/Catamarca | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Cayenne | Bin 184 -> 0 bytes .../pytz/zoneinfo/America/Cayman | Bin 182 -> 0 bytes .../pytz/zoneinfo/America/Chicago | Bin 3592 -> 0 bytes .../pytz/zoneinfo/America/Chihuahua | Bin 1102 -> 0 bytes .../pytz/zoneinfo/America/Ciudad_Juarez | Bin 1538 -> 0 bytes .../pytz/zoneinfo/America/Coral_Harbour | Bin 182 -> 0 bytes .../pytz/zoneinfo/America/Cordoba | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Costa_Rica | Bin 316 -> 0 bytes .../pytz/zoneinfo/America/Coyhaique | Bin 2126 -> 0 bytes .../pytz/zoneinfo/America/Creston | Bin 360 -> 0 bytes .../pytz/zoneinfo/America/Cuiaba | Bin 1402 -> 0 bytes .../pytz/zoneinfo/America/Curacao | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Danmarkshavn | Bin 698 -> 0 bytes .../pytz/zoneinfo/America/Dawson | Bin 1614 -> 0 bytes .../pytz/zoneinfo/America/Dawson_Creek | Bin 1050 -> 0 bytes .../pytz/zoneinfo/America/Denver | Bin 2460 -> 0 bytes .../pytz/zoneinfo/America/Detroit | Bin 2230 -> 0 bytes .../pytz/zoneinfo/America/Dominica | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Edmonton | Bin 2332 -> 0 bytes .../pytz/zoneinfo/America/Eirunepe | Bin 642 -> 0 bytes .../pytz/zoneinfo/America/El_Salvador | Bin 224 -> 0 bytes .../pytz/zoneinfo/America/Ensenada | Bin 2458 -> 0 bytes .../pytz/zoneinfo/America/Fort_Nelson | Bin 2240 -> 0 bytes .../pytz/zoneinfo/America/Fort_Wayne | Bin 1682 -> 0 bytes .../pytz/zoneinfo/America/Fortaleza | Bin 702 -> 0 bytes .../pytz/zoneinfo/America/Glace_Bay | Bin 2192 -> 0 bytes .../pytz/zoneinfo/America/Godthab | Bin 1889 -> 0 bytes .../pytz/zoneinfo/America/Goose_Bay | Bin 3210 -> 0 bytes .../pytz/zoneinfo/America/Grand_Turk | Bin 1834 -> 0 bytes .../pytz/zoneinfo/America/Grenada | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Guadeloupe | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Guatemala | Bin 280 -> 0 bytes .../pytz/zoneinfo/America/Guayaquil | Bin 232 -> 0 bytes .../pytz/zoneinfo/America/Guyana | Bin 248 -> 0 bytes .../pytz/zoneinfo/America/Halifax | Bin 3424 -> 0 bytes .../pytz/zoneinfo/America/Havana | Bin 2416 -> 0 bytes .../pytz/zoneinfo/America/Hermosillo | Bin 388 -> 0 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 1682 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Knox | Bin 2444 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Marengo | Bin 1738 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Petersburg | Bin 1920 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Tell_City | Bin 1700 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Vevay | Bin 1430 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Vincennes | Bin 1710 -> 0 bytes .../pytz/zoneinfo/America/Indiana/Winamac | Bin 1794 -> 0 bytes .../pytz/zoneinfo/America/Indianapolis | Bin 1682 -> 0 bytes .../pytz/zoneinfo/America/Inuvik | Bin 2074 -> 0 bytes .../pytz/zoneinfo/America/Iqaluit | Bin 2202 -> 0 bytes .../pytz/zoneinfo/America/Jamaica | Bin 482 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Jujuy | Bin 1034 -> 0 bytes .../pytz/zoneinfo/America/Juneau | Bin 2353 -> 0 bytes .../pytz/zoneinfo/America/Kentucky/Louisville | Bin 2788 -> 0 bytes .../pytz/zoneinfo/America/Kentucky/Monticello | Bin 2368 -> 0 bytes .../pytz/zoneinfo/America/Knox_IN | Bin 2444 -> 0 bytes .../pytz/zoneinfo/America/Kralendijk | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/La_Paz | Bin 218 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Lima | Bin 392 -> 0 bytes .../pytz/zoneinfo/America/Los_Angeles | Bin 2852 -> 0 bytes .../pytz/zoneinfo/America/Louisville | Bin 2788 -> 0 bytes .../pytz/zoneinfo/America/Lower_Princes | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Maceio | Bin 730 -> 0 bytes .../pytz/zoneinfo/America/Managua | Bin 430 -> 0 bytes .../pytz/zoneinfo/America/Manaus | Bin 590 -> 0 bytes .../pytz/zoneinfo/America/Marigot | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Martinique | Bin 232 -> 0 bytes .../pytz/zoneinfo/America/Matamoros | Bin 1418 -> 0 bytes .../pytz/zoneinfo/America/Mazatlan | Bin 1060 -> 0 bytes .../pytz/zoneinfo/America/Mendoza | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Menominee | Bin 2274 -> 0 bytes .../pytz/zoneinfo/America/Merida | Bin 1004 -> 0 bytes .../pytz/zoneinfo/America/Metlakatla | Bin 1423 -> 0 bytes .../pytz/zoneinfo/America/Mexico_City | Bin 1222 -> 0 bytes .../pytz/zoneinfo/America/Miquelon | Bin 1652 -> 0 bytes .../pytz/zoneinfo/America/Moncton | Bin 3154 -> 0 bytes .../pytz/zoneinfo/America/Monterrey | Bin 1114 -> 0 bytes .../pytz/zoneinfo/America/Montevideo | Bin 1496 -> 0 bytes .../pytz/zoneinfo/America/Montreal | Bin 3494 -> 0 bytes .../pytz/zoneinfo/America/Montserrat | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Nassau | Bin 3494 -> 0 bytes .../pytz/zoneinfo/America/New_York | Bin 3552 -> 0 bytes .../pytz/zoneinfo/America/Nipigon | Bin 3494 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Nome | Bin 2367 -> 0 bytes .../pytz/zoneinfo/America/Noronha | Bin 702 -> 0 bytes .../pytz/zoneinfo/America/North_Dakota/Beulah | Bin 2396 -> 0 bytes .../pytz/zoneinfo/America/North_Dakota/Center | Bin 2396 -> 0 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 2396 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Nuuk | Bin 1889 -> 0 bytes .../pytz/zoneinfo/America/Ojinaga | Bin 1524 -> 0 bytes .../pytz/zoneinfo/America/Panama | Bin 182 -> 0 bytes .../pytz/zoneinfo/America/Pangnirtung | Bin 2202 -> 0 bytes .../pytz/zoneinfo/America/Paramaribo | Bin 248 -> 0 bytes .../pytz/zoneinfo/America/Phoenix | Bin 360 -> 0 bytes .../pytz/zoneinfo/America/Port-au-Prince | Bin 1434 -> 0 bytes .../pytz/zoneinfo/America/Port_of_Spain | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Porto_Acre | Bin 614 -> 0 bytes .../pytz/zoneinfo/America/Porto_Velho | Bin 562 -> 0 bytes .../pytz/zoneinfo/America/Puerto_Rico | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Punta_Arenas | Bin 1902 -> 0 bytes .../pytz/zoneinfo/America/Rainy_River | Bin 2868 -> 0 bytes .../pytz/zoneinfo/America/Rankin_Inlet | Bin 2066 -> 0 bytes .../pytz/zoneinfo/America/Recife | Bin 702 -> 0 bytes .../pytz/zoneinfo/America/Regina | Bin 980 -> 0 bytes .../pytz/zoneinfo/America/Resolute | Bin 2066 -> 0 bytes .../pytz/zoneinfo/America/Rio_Branco | Bin 614 -> 0 bytes .../pytz/zoneinfo/America/Rosario | Bin 1062 -> 0 bytes .../pytz/zoneinfo/America/Santa_Isabel | Bin 2458 -> 0 bytes .../pytz/zoneinfo/America/Santarem | Bin 588 -> 0 bytes .../pytz/zoneinfo/America/Santiago | Bin 2515 -> 0 bytes .../pytz/zoneinfo/America/Santo_Domingo | Bin 458 -> 0 bytes .../pytz/zoneinfo/America/Sao_Paulo | Bin 1430 -> 0 bytes .../pytz/zoneinfo/America/Scoresbysund | Bin 1935 -> 0 bytes .../pytz/zoneinfo/America/Shiprock | Bin 2460 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Sitka | Bin 2329 -> 0 bytes .../pytz/zoneinfo/America/St_Barthelemy | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/St_Johns | Bin 3655 -> 0 bytes .../pytz/zoneinfo/America/St_Kitts | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/St_Lucia | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/St_Thomas | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/St_Vincent | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Swift_Current | Bin 560 -> 0 bytes .../pytz/zoneinfo/America/Tegucigalpa | Bin 252 -> 0 bytes .../site-packages/pytz/zoneinfo/America/Thule | Bin 1502 -> 0 bytes .../pytz/zoneinfo/America/Thunder_Bay | Bin 3494 -> 0 bytes .../pytz/zoneinfo/America/Tijuana | Bin 2458 -> 0 bytes .../pytz/zoneinfo/America/Toronto | Bin 3494 -> 0 bytes .../pytz/zoneinfo/America/Tortola | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Vancouver | Bin 2892 -> 0 bytes .../pytz/zoneinfo/America/Virgin | Bin 246 -> 0 bytes .../pytz/zoneinfo/America/Whitehorse | Bin 1614 -> 0 bytes .../pytz/zoneinfo/America/Winnipeg | Bin 2868 -> 0 bytes .../pytz/zoneinfo/America/Yakutat | Bin 2305 -> 0 bytes .../pytz/zoneinfo/America/Yellowknife | Bin 2332 -> 0 bytes .../pytz/zoneinfo/Antarctica/Casey | Bin 423 -> 0 bytes .../pytz/zoneinfo/Antarctica/Davis | Bin 283 -> 0 bytes .../pytz/zoneinfo/Antarctica/DumontDUrville | Bin 172 -> 0 bytes .../pytz/zoneinfo/Antarctica/Macquarie | Bin 2260 -> 0 bytes .../pytz/zoneinfo/Antarctica/Mawson | Bin 185 -> 0 bytes .../pytz/zoneinfo/Antarctica/McMurdo | Bin 2437 -> 0 bytes .../pytz/zoneinfo/Antarctica/Palmer | Bin 1404 -> 0 bytes .../pytz/zoneinfo/Antarctica/Rothera | Bin 150 -> 0 bytes .../pytz/zoneinfo/Antarctica/South_Pole | Bin 2437 -> 0 bytes .../pytz/zoneinfo/Antarctica/Syowa | Bin 151 -> 0 bytes .../pytz/zoneinfo/Antarctica/Troll | Bin 1148 -> 0 bytes .../pytz/zoneinfo/Antarctica/Vostok | Bin 213 -> 0 bytes .../pytz/zoneinfo/Arctic/Longyearbyen | Bin 2298 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Aden | Bin 151 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Almaty | Bin 983 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Amman | Bin 1433 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Anadyr | Bin 1174 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Aqtau | Bin 969 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Aqtobe | Bin 997 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Ashgabat | Bin 605 -> 0 bytes .../pytz/zoneinfo/Asia/Ashkhabad | Bin 605 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Atyrau | Bin 977 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Baghdad | Bin 969 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Bahrain | Bin 185 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Baku | Bin 1213 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Bangkok | Bin 185 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Barnaul | Bin 1207 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Beirut | Bin 2154 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Bishkek | Bin 969 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Brunei | Bin 469 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Calcutta | Bin 285 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Chita | Bin 1207 -> 0 bytes .../pytz/zoneinfo/Asia/Choibalsan | Bin 877 -> 0 bytes .../pytz/zoneinfo/Asia/Chongqing | Bin 561 -> 0 bytes .../pytz/zoneinfo/Asia/Chungking | Bin 561 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Colombo | Bin 358 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Dacca | Bin 323 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Damascus | Bin 1873 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Dhaka | Bin 323 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Dili | Bin 257 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Dubai | Bin 151 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Dushanbe | Bin 577 -> 0 bytes .../pytz/zoneinfo/Asia/Famagusta | Bin 2028 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Gaza | Bin 3844 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Harbin | Bin 561 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Hebron | Bin 3872 -> 0 bytes .../pytz/zoneinfo/Asia/Ho_Chi_Minh | Bin 337 -> 0 bytes .../pytz/zoneinfo/Asia/Hong_Kong | Bin 1233 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Hovd | Bin 877 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Irkutsk | Bin 1229 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Istanbul | Bin 1933 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Jakarta | Bin 383 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Jayapura | Bin 221 -> 0 bytes .../pytz/zoneinfo/Asia/Jerusalem | Bin 2388 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Kabul | Bin 194 -> 0 bytes .../pytz/zoneinfo/Asia/Kamchatka | Bin 1152 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Karachi | Bin 379 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Kashgar | Bin 151 -> 0 bytes .../pytz/zoneinfo/Asia/Kathmandu | Bin 198 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Katmandu | Bin 198 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Khandyga | Bin 1257 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Kolkata | Bin 285 -> 0 bytes .../pytz/zoneinfo/Asia/Krasnoyarsk | Bin 1193 -> 0 bytes .../pytz/zoneinfo/Asia/Kuala_Lumpur | Bin 401 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Kuching | Bin 469 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Kuwait | Bin 151 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Macao | Bin 1227 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Macau | Bin 1227 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Magadan | Bin 1208 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Makassar | Bin 254 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Manila | Bin 422 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Muscat | Bin 151 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Nicosia | Bin 2002 -> 0 bytes .../pytz/zoneinfo/Asia/Novokuznetsk | Bin 1151 -> 0 bytes .../pytz/zoneinfo/Asia/Novosibirsk | Bin 1207 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Omsk | Bin 1193 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Asia/Oral | Bin 991 -> 0 bytes .../pytz/zoneinfo/Asia/Phnom_Penh | Bin 185 -> 0 bytes .../pytz/zoneinfo/Asia/Pontianak | Bin 353 -> 0 bytes .../pytz/zoneinfo/Asia/Pyongyang | Bin 237 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Qatar | Bin 185 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Qostanay | Bin 1025 -> 0 bytes .../pytz/zoneinfo/Asia/Qyzylorda | Bin 1011 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Rangoon | Bin 254 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Riyadh | Bin 151 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Saigon | Bin 337 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Sakhalin | Bin 1188 -> 0 bytes .../pytz/zoneinfo/Asia/Samarkand | Bin 563 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Seoul | Bin 617 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Shanghai | Bin 561 -> 0 bytes .../pytz/zoneinfo/Asia/Singapore | Bin 401 -> 0 bytes .../pytz/zoneinfo/Asia/Srednekolymsk | Bin 1194 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Taipei | Bin 761 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Tashkent | Bin 577 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Tbilisi | Bin 1021 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Tehran | Bin 1248 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Tel_Aviv | Bin 2388 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Thimbu | Bin 189 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Thimphu | Bin 189 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Tokyo | Bin 309 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Tomsk | Bin 1207 -> 0 bytes .../pytz/zoneinfo/Asia/Ujung_Pandang | Bin 254 -> 0 bytes .../pytz/zoneinfo/Asia/Ulaanbaatar | Bin 877 -> 0 bytes .../pytz/zoneinfo/Asia/Ulan_Bator | Bin 877 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Urumqi | Bin 151 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Ust-Nera | Bin 1238 -> 0 bytes .../pytz/zoneinfo/Asia/Vientiane | Bin 185 -> 0 bytes .../pytz/zoneinfo/Asia/Vladivostok | Bin 1194 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Yakutsk | Bin 1193 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Yangon | Bin 254 -> 0 bytes .../pytz/zoneinfo/Asia/Yekaterinburg | Bin 1229 -> 0 bytes .../site-packages/pytz/zoneinfo/Asia/Yerevan | Bin 1137 -> 0 bytes .../pytz/zoneinfo/Atlantic/Azores | Bin 3442 -> 0 bytes .../pytz/zoneinfo/Atlantic/Bermuda | Bin 2396 -> 0 bytes .../pytz/zoneinfo/Atlantic/Canary | Bin 1897 -> 0 bytes .../pytz/zoneinfo/Atlantic/Cape_Verde | Bin 256 -> 0 bytes .../pytz/zoneinfo/Atlantic/Faeroe | Bin 1815 -> 0 bytes .../pytz/zoneinfo/Atlantic/Faroe | Bin 1815 -> 0 bytes .../pytz/zoneinfo/Atlantic/Jan_Mayen | Bin 2298 -> 0 bytes .../pytz/zoneinfo/Atlantic/Madeira | Bin 3377 -> 0 bytes .../pytz/zoneinfo/Atlantic/Reykjavik | Bin 148 -> 0 bytes .../pytz/zoneinfo/Atlantic/South_Georgia | Bin 150 -> 0 bytes .../pytz/zoneinfo/Atlantic/St_Helena | Bin 148 -> 0 bytes .../pytz/zoneinfo/Atlantic/Stanley | Bin 1200 -> 0 bytes .../site-packages/pytz/zoneinfo/Australia/ACT | Bin 2190 -> 0 bytes .../pytz/zoneinfo/Australia/Adelaide | Bin 2208 -> 0 bytes .../pytz/zoneinfo/Australia/Brisbane | Bin 419 -> 0 bytes .../pytz/zoneinfo/Australia/Broken_Hill | Bin 2229 -> 0 bytes .../pytz/zoneinfo/Australia/Canberra | Bin 2190 -> 0 bytes .../pytz/zoneinfo/Australia/Currie | Bin 2358 -> 0 bytes .../pytz/zoneinfo/Australia/Darwin | Bin 325 -> 0 bytes .../pytz/zoneinfo/Australia/Eucla | Bin 456 -> 0 bytes .../pytz/zoneinfo/Australia/Hobart | Bin 2358 -> 0 bytes .../site-packages/pytz/zoneinfo/Australia/LHI | Bin 1846 -> 0 bytes .../pytz/zoneinfo/Australia/Lindeman | Bin 475 -> 0 bytes .../pytz/zoneinfo/Australia/Lord_Howe | Bin 1846 -> 0 bytes .../pytz/zoneinfo/Australia/Melbourne | Bin 2190 -> 0 bytes .../site-packages/pytz/zoneinfo/Australia/NSW | Bin 2190 -> 0 bytes .../pytz/zoneinfo/Australia/North | Bin 325 -> 0 bytes .../pytz/zoneinfo/Australia/Perth | Bin 446 -> 0 bytes .../pytz/zoneinfo/Australia/Queensland | Bin 419 -> 0 bytes .../pytz/zoneinfo/Australia/South | Bin 2208 -> 0 bytes .../pytz/zoneinfo/Australia/Sydney | Bin 2190 -> 0 bytes .../pytz/zoneinfo/Australia/Tasmania | Bin 2358 -> 0 bytes .../pytz/zoneinfo/Australia/Victoria | Bin 2190 -> 0 bytes .../pytz/zoneinfo/Australia/West | Bin 446 -> 0 bytes .../pytz/zoneinfo/Australia/Yancowinna | Bin 2229 -> 0 bytes .../site-packages/pytz/zoneinfo/Brazil/Acre | Bin 614 -> 0 bytes .../pytz/zoneinfo/Brazil/DeNoronha | Bin 702 -> 0 bytes .../site-packages/pytz/zoneinfo/Brazil/East | Bin 1430 -> 0 bytes .../site-packages/pytz/zoneinfo/Brazil/West | Bin 590 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/CET | Bin 2933 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/CST6CDT | Bin 3592 -> 0 bytes .../pytz/zoneinfo/Canada/Atlantic | Bin 3424 -> 0 bytes .../pytz/zoneinfo/Canada/Central | Bin 2868 -> 0 bytes .../pytz/zoneinfo/Canada/Eastern | Bin 3494 -> 0 bytes .../pytz/zoneinfo/Canada/Mountain | Bin 2332 -> 0 bytes .../pytz/zoneinfo/Canada/Newfoundland | Bin 3655 -> 0 bytes .../pytz/zoneinfo/Canada/Pacific | Bin 2892 -> 0 bytes .../pytz/zoneinfo/Canada/Saskatchewan | Bin 980 -> 0 bytes .../site-packages/pytz/zoneinfo/Canada/Yukon | Bin 1614 -> 0 bytes .../pytz/zoneinfo/Chile/Continental | Bin 2515 -> 0 bytes .../pytz/zoneinfo/Chile/EasterIsland | Bin 2219 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Cuba | Bin 2416 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/EET | Bin 2262 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/EST | Bin 182 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/EST5EDT | Bin 3552 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Egypt | Bin 2399 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Eire | Bin 3492 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT | Bin 114 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+0 | Bin 114 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+1 | Bin 116 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+10 | Bin 117 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+11 | Bin 117 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT+12 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+2 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+3 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+4 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+5 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+6 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+7 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+8 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT+9 | Bin 116 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-0 | Bin 114 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-1 | Bin 117 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-10 | Bin 118 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-11 | Bin 118 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-12 | Bin 118 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-13 | Bin 118 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/GMT-14 | Bin 118 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-2 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-3 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-4 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-5 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-6 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-7 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-8 | Bin 117 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Etc/GMT-9 | Bin 117 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT0 | Bin 114 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/Greenwich | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Etc/UCT | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Etc/UTC | Bin 114 -> 0 bytes .../site-packages/pytz/zoneinfo/Etc/Universal | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Etc/Zulu | Bin 114 -> 0 bytes .../pytz/zoneinfo/Europe/Amsterdam | Bin 2933 -> 0 bytes .../pytz/zoneinfo/Europe/Andorra | Bin 1742 -> 0 bytes .../pytz/zoneinfo/Europe/Astrakhan | Bin 1151 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Athens | Bin 2262 -> 0 bytes .../pytz/zoneinfo/Europe/Belfast | Bin 3664 -> 0 bytes .../pytz/zoneinfo/Europe/Belgrade | Bin 1920 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Berlin | Bin 2298 -> 0 bytes .../pytz/zoneinfo/Europe/Bratislava | Bin 2301 -> 0 bytes .../pytz/zoneinfo/Europe/Brussels | Bin 2933 -> 0 bytes .../pytz/zoneinfo/Europe/Bucharest | Bin 2184 -> 0 bytes .../pytz/zoneinfo/Europe/Budapest | Bin 2368 -> 0 bytes .../pytz/zoneinfo/Europe/Busingen | Bin 1909 -> 0 bytes .../pytz/zoneinfo/Europe/Chisinau | Bin 2390 -> 0 bytes .../pytz/zoneinfo/Europe/Copenhagen | Bin 2298 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Dublin | Bin 3492 -> 0 bytes .../pytz/zoneinfo/Europe/Gibraltar | Bin 3068 -> 0 bytes .../pytz/zoneinfo/Europe/Guernsey | Bin 3664 -> 0 bytes .../pytz/zoneinfo/Europe/Helsinki | Bin 1900 -> 0 bytes .../pytz/zoneinfo/Europe/Isle_of_Man | Bin 3664 -> 0 bytes .../pytz/zoneinfo/Europe/Istanbul | Bin 1933 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Jersey | Bin 3664 -> 0 bytes .../pytz/zoneinfo/Europe/Kaliningrad | Bin 1493 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Kiev | Bin 2120 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Kirov | Bin 1185 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Kyiv | Bin 2120 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Lisbon | Bin 3527 -> 0 bytes .../pytz/zoneinfo/Europe/Ljubljana | Bin 1920 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/London | Bin 3664 -> 0 bytes .../pytz/zoneinfo/Europe/Luxembourg | Bin 2933 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Madrid | Bin 2614 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Malta | Bin 2620 -> 0 bytes .../pytz/zoneinfo/Europe/Mariehamn | Bin 1900 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Minsk | Bin 1307 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Monaco | Bin 2962 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Moscow | Bin 1535 -> 0 bytes .../pytz/zoneinfo/Europe/Nicosia | Bin 2002 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Oslo | Bin 2298 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Paris | Bin 2962 -> 0 bytes .../pytz/zoneinfo/Europe/Podgorica | Bin 1920 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Prague | Bin 2301 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Riga | Bin 2198 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Rome | Bin 2641 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Samara | Bin 1201 -> 0 bytes .../pytz/zoneinfo/Europe/San_Marino | Bin 2641 -> 0 bytes .../pytz/zoneinfo/Europe/Sarajevo | Bin 1920 -> 0 bytes .../pytz/zoneinfo/Europe/Saratov | Bin 1169 -> 0 bytes .../pytz/zoneinfo/Europe/Simferopol | Bin 1469 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Skopje | Bin 1920 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Sofia | Bin 2077 -> 0 bytes .../pytz/zoneinfo/Europe/Stockholm | Bin 2298 -> 0 bytes .../pytz/zoneinfo/Europe/Tallinn | Bin 2148 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Tirane | Bin 2084 -> 0 bytes .../pytz/zoneinfo/Europe/Tiraspol | Bin 2390 -> 0 bytes .../pytz/zoneinfo/Europe/Ulyanovsk | Bin 1253 -> 0 bytes .../pytz/zoneinfo/Europe/Uzhgorod | Bin 2120 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Vaduz | Bin 1909 -> 0 bytes .../pytz/zoneinfo/Europe/Vatican | Bin 2641 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Vienna | Bin 2200 -> 0 bytes .../pytz/zoneinfo/Europe/Vilnius | Bin 2162 -> 0 bytes .../pytz/zoneinfo/Europe/Volgograd | Bin 1193 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Warsaw | Bin 2654 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Zagreb | Bin 1920 -> 0 bytes .../pytz/zoneinfo/Europe/Zaporozhye | Bin 2120 -> 0 bytes .../site-packages/pytz/zoneinfo/Europe/Zurich | Bin 1909 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Factory | Bin 116 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/GB | Bin 3664 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/GB-Eire | Bin 3664 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/GMT | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/GMT+0 | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/GMT-0 | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/GMT0 | Bin 114 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Greenwich | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/HST | Bin 329 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Hongkong | Bin 1233 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Iceland | Bin 148 -> 0 bytes .../pytz/zoneinfo/Indian/Antananarivo | Bin 265 -> 0 bytes .../site-packages/pytz/zoneinfo/Indian/Chagos | Bin 185 -> 0 bytes .../pytz/zoneinfo/Indian/Christmas | Bin 185 -> 0 bytes .../site-packages/pytz/zoneinfo/Indian/Cocos | Bin 254 -> 0 bytes .../site-packages/pytz/zoneinfo/Indian/Comoro | Bin 265 -> 0 bytes .../pytz/zoneinfo/Indian/Kerguelen | Bin 185 -> 0 bytes .../site-packages/pytz/zoneinfo/Indian/Mahe | Bin 151 -> 0 bytes .../pytz/zoneinfo/Indian/Maldives | Bin 185 -> 0 bytes .../pytz/zoneinfo/Indian/Mauritius | Bin 227 -> 0 bytes .../pytz/zoneinfo/Indian/Mayotte | Bin 265 -> 0 bytes .../pytz/zoneinfo/Indian/Reunion | Bin 151 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Iran | Bin 1248 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Israel | Bin 2388 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Jamaica | Bin 482 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Japan | Bin 309 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Kwajalein | Bin 302 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Libya | Bin 625 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/MET | Bin 2933 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/MST | Bin 360 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/MST7MDT | Bin 2460 -> 0 bytes .../pytz/zoneinfo/Mexico/BajaNorte | Bin 2458 -> 0 bytes .../pytz/zoneinfo/Mexico/BajaSur | Bin 1060 -> 0 bytes .../pytz/zoneinfo/Mexico/General | Bin 1222 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/NZ | Bin 2437 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/NZ-CHAT | Bin 2054 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Navajo | Bin 2460 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/PRC | Bin 561 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/PST8PDT | Bin 2852 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Apia | Bin 598 -> 0 bytes .../pytz/zoneinfo/Pacific/Auckland | Bin 2437 -> 0 bytes .../pytz/zoneinfo/Pacific/Bougainville | Bin 254 -> 0 bytes .../pytz/zoneinfo/Pacific/Chatham | Bin 2054 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Chuuk | Bin 172 -> 0 bytes .../pytz/zoneinfo/Pacific/Easter | Bin 2219 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Efate | Bin 524 -> 0 bytes .../pytz/zoneinfo/Pacific/Enderbury | Bin 220 -> 0 bytes .../pytz/zoneinfo/Pacific/Fakaofo | Bin 186 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Fiji | Bin 564 -> 0 bytes .../pytz/zoneinfo/Pacific/Funafuti | Bin 152 -> 0 bytes .../pytz/zoneinfo/Pacific/Galapagos | Bin 224 -> 0 bytes .../pytz/zoneinfo/Pacific/Gambier | Bin 150 -> 0 bytes .../pytz/zoneinfo/Pacific/Guadalcanal | Bin 152 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Guam | Bin 494 -> 0 bytes .../pytz/zoneinfo/Pacific/Honolulu | Bin 329 -> 0 bytes .../pytz/zoneinfo/Pacific/Johnston | Bin 329 -> 0 bytes .../pytz/zoneinfo/Pacific/Kanton | Bin 220 -> 0 bytes .../pytz/zoneinfo/Pacific/Kiritimati | Bin 224 -> 0 bytes .../pytz/zoneinfo/Pacific/Kosrae | Bin 337 -> 0 bytes .../pytz/zoneinfo/Pacific/Kwajalein | Bin 302 -> 0 bytes .../pytz/zoneinfo/Pacific/Majuro | Bin 152 -> 0 bytes .../pytz/zoneinfo/Pacific/Marquesas | Bin 159 -> 0 bytes .../pytz/zoneinfo/Pacific/Midway | Bin 175 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Nauru | Bin 238 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Niue | Bin 189 -> 0 bytes .../pytz/zoneinfo/Pacific/Norfolk | Bin 866 -> 0 bytes .../pytz/zoneinfo/Pacific/Noumea | Bin 290 -> 0 bytes .../pytz/zoneinfo/Pacific/Pago_Pago | Bin 175 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Palau | Bin 166 -> 0 bytes .../pytz/zoneinfo/Pacific/Pitcairn | Bin 188 -> 0 bytes .../pytz/zoneinfo/Pacific/Pohnpei | Bin 152 -> 0 bytes .../pytz/zoneinfo/Pacific/Ponape | Bin 152 -> 0 bytes .../pytz/zoneinfo/Pacific/Port_Moresby | Bin 172 -> 0 bytes .../pytz/zoneinfo/Pacific/Rarotonga | Bin 589 -> 0 bytes .../pytz/zoneinfo/Pacific/Saipan | Bin 494 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Samoa | Bin 175 -> 0 bytes .../pytz/zoneinfo/Pacific/Tahiti | Bin 151 -> 0 bytes .../pytz/zoneinfo/Pacific/Tarawa | Bin 152 -> 0 bytes .../pytz/zoneinfo/Pacific/Tongatapu | Bin 358 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Truk | Bin 172 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Wake | Bin 152 -> 0 bytes .../pytz/zoneinfo/Pacific/Wallis | Bin 152 -> 0 bytes .../site-packages/pytz/zoneinfo/Pacific/Yap | Bin 172 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Poland | Bin 2654 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Portugal | Bin 3527 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/ROC | Bin 761 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/ROK | Bin 617 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Singapore | Bin 401 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Turkey | Bin 1933 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/UCT | Bin 114 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/US/Alaska | Bin 2371 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Aleutian | Bin 2356 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Arizona | Bin 360 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Central | Bin 3592 -> 0 bytes .../pytz/zoneinfo/US/East-Indiana | Bin 1682 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Eastern | Bin 3552 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/US/Hawaii | Bin 329 -> 0 bytes .../pytz/zoneinfo/US/Indiana-Starke | Bin 2444 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Michigan | Bin 2230 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Mountain | Bin 2460 -> 0 bytes .../site-packages/pytz/zoneinfo/US/Pacific | Bin 2852 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/US/Samoa | Bin 175 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/UTC | Bin 114 -> 0 bytes .../Lib/site-packages/pytz/zoneinfo/Universal | Bin 114 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/W-SU | Bin 1535 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/WET | Bin 3527 -> 0 bytes venv/Lib/site-packages/pytz/zoneinfo/Zulu | Bin 114 -> 0 bytes .../site-packages/pytz/zoneinfo/iso3166.tab | 279 - .../site-packages/pytz/zoneinfo/leapseconds | 79 - .../Lib/site-packages/pytz/zoneinfo/tzdata.zi | 4300 -------- venv/Lib/site-packages/pytz/zoneinfo/zone.tab | 448 - .../site-packages/pytz/zoneinfo/zone1970.tab | 375 - .../site-packages/pytz/zoneinfo/zonenow.tab | 296 - .../requests-2.32.3.dist-info/INSTALLER | 1 - .../requests-2.32.3.dist-info/LICENSE | 175 - .../requests-2.32.3.dist-info/METADATA | 119 - .../requests-2.32.3.dist-info/RECORD | 43 - .../requests-2.32.3.dist-info/REQUESTED | 0 .../requests-2.32.3.dist-info/WHEEL | 5 - .../requests-2.32.3.dist-info/top_level.txt | 1 - venv/Lib/site-packages/requests/__init__.py | 184 - .../__pycache__/__init__.cpython-310.pyc | Bin 3910 -> 0 bytes .../__pycache__/__version__.cpython-310.pyc | Bin 524 -> 0 bytes .../_internal_utils.cpython-310.pyc | Bin 1600 -> 0 bytes .../__pycache__/adapters.cpython-310.pyc | Bin 22014 -> 0 bytes .../requests/__pycache__/api.cpython-310.pyc | Bin 6700 -> 0 bytes .../requests/__pycache__/auth.cpython-310.pyc | Bin 8096 -> 0 bytes .../__pycache__/certs.cpython-310.pyc | Bin 601 -> 0 bytes .../__pycache__/compat.cpython-310.pyc | Bin 1752 -> 0 bytes .../__pycache__/cookies.cpython-310.pyc | Bin 18701 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 6203 -> 0 bytes .../requests/__pycache__/help.cpython-310.pyc | Bin 2823 -> 0 bytes .../__pycache__/hooks.cpython-310.pyc | Bin 968 -> 0 bytes .../__pycache__/models.cpython-310.pyc | Bin 24192 -> 0 bytes .../__pycache__/packages.cpython-310.pyc | Bin 605 -> 0 bytes .../__pycache__/sessions.cpython-310.pyc | Bin 19710 -> 0 bytes .../__pycache__/status_codes.cpython-310.pyc | Bin 4718 -> 0 bytes .../__pycache__/structures.cpython-310.pyc | Bin 4412 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 24600 -> 0 bytes .../Lib/site-packages/requests/__version__.py | 14 - .../site-packages/requests/_internal_utils.py | 50 - venv/Lib/site-packages/requests/adapters.py | 719 -- venv/Lib/site-packages/requests/api.py | 157 - venv/Lib/site-packages/requests/auth.py | 314 - venv/Lib/site-packages/requests/certs.py | 17 - venv/Lib/site-packages/requests/compat.py | 94 - venv/Lib/site-packages/requests/cookies.py | 561 -- venv/Lib/site-packages/requests/exceptions.py | 151 - venv/Lib/site-packages/requests/help.py | 134 - venv/Lib/site-packages/requests/hooks.py | 33 - venv/Lib/site-packages/requests/models.py | 1037 -- venv/Lib/site-packages/requests/packages.py | 23 - venv/Lib/site-packages/requests/sessions.py | 831 -- .../site-packages/requests/status_codes.py | 128 - venv/Lib/site-packages/requests/structures.py | 99 - venv/Lib/site-packages/requests/utils.py | 1096 --- .../setuptools-63.2.0.dist-info/INSTALLER | 1 - .../setuptools-63.2.0.dist-info/LICENSE | 19 - .../setuptools-63.2.0.dist-info/METADATA | 140 - .../setuptools-63.2.0.dist-info/RECORD | 468 - .../setuptools-63.2.0.dist-info/REQUESTED | 0 .../setuptools-63.2.0.dist-info/WHEEL | 5 - .../entry_points.txt | 56 - .../setuptools-63.2.0.dist-info/top_level.txt | 3 - venv/Lib/site-packages/setuptools/__init__.py | 189 - .../__pycache__/__init__.cpython-310.pyc | Bin 6568 -> 0 bytes .../_deprecation_warning.cpython-310.pyc | Bin 540 -> 0 bytes .../__pycache__/_entry_points.cpython-310.pyc | Bin 3003 -> 0 bytes .../__pycache__/_imp.cpython-310.pyc | Bin 2066 -> 0 bytes .../__pycache__/_importlib.cpython-310.pyc | Bin 1336 -> 0 bytes .../__pycache__/_itertools.cpython-310.pyc | Bin 904 -> 0 bytes .../__pycache__/_path.cpython-310.pyc | Bin 416 -> 0 bytes .../__pycache__/_reqs.cpython-310.pyc | Bin 819 -> 0 bytes .../__pycache__/archive_util.cpython-310.pyc | Bin 6170 -> 0 bytes .../__pycache__/build_meta.cpython-310.pyc | Bin 9854 -> 0 bytes .../__pycache__/dep_util.cpython-310.pyc | Bin 847 -> 0 bytes .../__pycache__/depends.cpython-310.pyc | Bin 5286 -> 0 bytes .../__pycache__/discovery.cpython-310.pyc | Bin 20565 -> 0 bytes .../__pycache__/dist.cpython-310.pyc | Bin 38394 -> 0 bytes .../__pycache__/errors.cpython-310.pyc | Bin 2474 -> 0 bytes .../__pycache__/extension.cpython-310.pyc | Bin 5566 -> 0 bytes .../__pycache__/glob.cpython-310.pyc | Bin 3725 -> 0 bytes .../__pycache__/installer.cpython-310.pyc | Bin 2971 -> 0 bytes .../__pycache__/launch.cpython-310.pyc | Bin 897 -> 0 bytes .../__pycache__/logging.cpython-310.pyc | Bin 1200 -> 0 bytes .../__pycache__/monkey.cpython-310.pyc | Bin 4625 -> 0 bytes .../__pycache__/msvc.cpython-310.pyc | Bin 42629 -> 0 bytes .../__pycache__/namespaces.cpython-310.pyc | Bin 3608 -> 0 bytes .../__pycache__/package_index.cpython-310.pyc | Bin 32677 -> 0 bytes .../__pycache__/py34compat.cpython-310.pyc | Bin 472 -> 0 bytes .../__pycache__/sandbox.cpython-310.pyc | Bin 15748 -> 0 bytes .../__pycache__/unicode_utils.cpython-310.pyc | Bin 1102 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 314 -> 0 bytes .../__pycache__/wheel.cpython-310.pyc | Bin 7364 -> 0 bytes .../windows_support.cpython-310.pyc | Bin 1020 -> 0 bytes .../setuptools/_deprecation_warning.py | 7 - .../setuptools/_distutils/__init__.py | 24 - .../__pycache__/__init__.cpython-310.pyc | Bin 548 -> 0 bytes .../__pycache__/_collections.cpython-310.pyc | Bin 2049 -> 0 bytes .../__pycache__/_functools.cpython-310.pyc | Bin 679 -> 0 bytes .../__pycache__/_macos_compat.cpython-310.pyc | Bin 443 -> 0 bytes .../__pycache__/_msvccompiler.cpython-310.pyc | Bin 13849 -> 0 bytes .../__pycache__/archive_util.cpython-310.pyc | Bin 6559 -> 0 bytes .../__pycache__/bcppcompiler.cpython-310.pyc | Bin 6569 -> 0 bytes .../__pycache__/ccompiler.cpython-310.pyc | Bin 33354 -> 0 bytes .../__pycache__/cmd.cpython-310.pyc | Bin 13952 -> 0 bytes .../__pycache__/config.cpython-310.pyc | Bin 3574 -> 0 bytes .../__pycache__/core.cpython-310.pyc | Bin 7076 -> 0 bytes .../cygwinccompiler.cpython-310.pyc | Bin 8324 -> 0 bytes .../__pycache__/debug.cpython-310.pyc | Bin 242 -> 0 bytes .../__pycache__/dep_util.cpython-310.pyc | Bin 2759 -> 0 bytes .../__pycache__/dir_util.cpython-310.pyc | Bin 5908 -> 0 bytes .../__pycache__/dist.cpython-310.pyc | Bin 34114 -> 0 bytes .../__pycache__/errors.cpython-310.pyc | Bin 4984 -> 0 bytes .../__pycache__/extension.cpython-310.pyc | Bin 7000 -> 0 bytes .../__pycache__/fancy_getopt.cpython-310.pyc | Bin 10630 -> 0 bytes .../__pycache__/file_util.cpython-310.pyc | Bin 5954 -> 0 bytes .../__pycache__/filelist.cpython-310.pyc | Bin 10790 -> 0 bytes .../__pycache__/log.cpython-310.pyc | Bin 2299 -> 0 bytes .../__pycache__/msvc9compiler.cpython-310.pyc | Bin 17521 -> 0 bytes .../__pycache__/msvccompiler.cpython-310.pyc | Bin 14781 -> 0 bytes .../__pycache__/py38compat.cpython-310.pyc | Bin 415 -> 0 bytes .../__pycache__/py39compat.cpython-310.pyc | Bin 724 -> 0 bytes .../__pycache__/spawn.cpython-310.pyc | Bin 2844 -> 0 bytes .../__pycache__/sysconfig.cpython-310.pyc | Bin 12568 -> 0 bytes .../__pycache__/text_file.cpython-310.pyc | Bin 8245 -> 0 bytes .../__pycache__/unixccompiler.cpython-310.pyc | Bin 8636 -> 0 bytes .../__pycache__/util.cpython-310.pyc | Bin 13496 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 7817 -> 0 bytes .../versionpredicate.cpython-310.pyc | Bin 5317 -> 0 bytes .../setuptools/_distutils/_collections.py | 56 - .../setuptools/_distutils/_functools.py | 20 - .../setuptools/_distutils/_macos_compat.py | 12 - .../setuptools/_distutils/_msvccompiler.py | 591 -- .../setuptools/_distutils/archive_util.py | 280 - .../setuptools/_distutils/bcppcompiler.py | 398 - .../setuptools/_distutils/ccompiler.py | 1193 --- .../setuptools/_distutils/cmd.py | 434 - .../setuptools/_distutils/command/__init__.py | 32 - .../__pycache__/__init__.cpython-310.pyc | Bin 521 -> 0 bytes .../_framework_compat.cpython-310.pyc | Bin 1913 -> 0 bytes .../command/__pycache__/bdist.cpython-310.pyc | Bin 3636 -> 0 bytes .../__pycache__/bdist_dumb.cpython-310.pyc | Bin 3630 -> 0 bytes .../__pycache__/bdist_msi.cpython-310.pyc | Bin 20185 -> 0 bytes .../__pycache__/bdist_rpm.cpython-310.pyc | Bin 12263 -> 0 bytes .../__pycache__/bdist_wininst.cpython-310.pyc | Bin 8603 -> 0 bytes .../command/__pycache__/build.cpython-310.pyc | Bin 3887 -> 0 bytes .../__pycache__/build_clib.cpython-310.pyc | Bin 4852 -> 0 bytes .../__pycache__/build_ext.cpython-310.pyc | Bin 16216 -> 0 bytes .../__pycache__/build_py.cpython-310.pyc | Bin 9789 -> 0 bytes .../__pycache__/build_scripts.cpython-310.pyc | Bin 4590 -> 0 bytes .../command/__pycache__/check.cpython-310.pyc | Bin 4543 -> 0 bytes .../command/__pycache__/clean.cpython-310.pyc | Bin 2122 -> 0 bytes .../__pycache__/config.cpython-310.pyc | Bin 10352 -> 0 bytes .../__pycache__/install.cpython-310.pyc | Bin 17208 -> 0 bytes .../__pycache__/install_data.cpython-310.pyc | Bin 2343 -> 0 bytes .../install_egg_info.cpython-310.pyc | Bin 3302 -> 0 bytes .../install_headers.cpython-310.pyc | Bin 1758 -> 0 bytes .../__pycache__/install_lib.cpython-310.pyc | Bin 5186 -> 0 bytes .../install_scripts.cpython-310.pyc | Bin 2191 -> 0 bytes .../__pycache__/py37compat.cpython-310.pyc | Bin 1034 -> 0 bytes .../__pycache__/register.cpython-310.pyc | Bin 8558 -> 0 bytes .../command/__pycache__/sdist.cpython-310.pyc | Bin 14495 -> 0 bytes .../__pycache__/upload.cpython-310.pyc | Bin 5345 -> 0 bytes .../_distutils/command/_framework_compat.py | 55 - .../setuptools/_distutils/command/bdist.py | 155 - .../_distutils/command/bdist_dumb.py | 142 - .../_distutils/command/bdist_msi.py | 1114 --- .../_distutils/command/bdist_rpm.py | 607 -- .../_distutils/command/bdist_wininst.py | 418 - .../setuptools/_distutils/command/build.py | 152 - .../_distutils/command/build_clib.py | 208 - .../_distutils/command/build_ext.py | 780 -- .../setuptools/_distutils/command/build_py.py | 408 - .../_distutils/command/build_scripts.py | 173 - .../setuptools/_distutils/command/check.py | 153 - .../setuptools/_distutils/command/clean.py | 76 - .../setuptools/_distutils/command/config.py | 376 - .../setuptools/_distutils/command/install.py | 811 -- .../_distutils/command/install_data.py | 84 - .../_distutils/command/install_egg_info.py | 87 - .../_distutils/command/install_headers.py | 45 - .../_distutils/command/install_lib.py | 238 - .../_distutils/command/install_scripts.py | 61 - .../_distutils/command/py37compat.py | 31 - .../setuptools/_distutils/command/register.py | 319 - .../setuptools/_distutils/command/sdist.py | 531 - .../setuptools/_distutils/command/upload.py | 205 - .../setuptools/_distutils/config.py | 139 - .../setuptools/_distutils/core.py | 283 - .../setuptools/_distutils/cygwinccompiler.py | 414 - .../setuptools/_distutils/debug.py | 5 - .../setuptools/_distutils/dep_util.py | 96 - .../setuptools/_distutils/dir_util.py | 239 - .../setuptools/_distutils/dist.py | 1286 --- .../setuptools/_distutils/errors.py | 127 - .../setuptools/_distutils/extension.py | 248 - .../setuptools/_distutils/fancy_getopt.py | 468 - .../setuptools/_distutils/file_util.py | 245 - .../setuptools/_distutils/filelist.py | 371 - .../setuptools/_distutils/log.py | 80 - .../setuptools/_distutils/msvc9compiler.py | 820 -- .../setuptools/_distutils/msvccompiler.py | 683 -- .../setuptools/_distutils/py38compat.py | 8 - .../setuptools/_distutils/py39compat.py | 22 - .../setuptools/_distutils/spawn.py | 107 - .../setuptools/_distutils/sysconfig.py | 549 -- .../setuptools/_distutils/text_file.py | 287 - .../setuptools/_distutils/unixccompiler.py | 382 - .../setuptools/_distutils/util.py | 520 - .../setuptools/_distutils/version.py | 358 - .../setuptools/_distutils/versionpredicate.py | 175 - .../site-packages/setuptools/_entry_points.py | 86 - venv/Lib/site-packages/setuptools/_imp.py | 82 - .../site-packages/setuptools/_importlib.py | 47 - .../site-packages/setuptools/_itertools.py | 23 - venv/Lib/site-packages/setuptools/_path.py | 7 - venv/Lib/site-packages/setuptools/_reqs.py | 19 - .../setuptools/_vendor/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 176 -> 0 bytes .../__pycache__/ordered_set.cpython-310.pyc | Bin 16312 -> 0 bytes .../typing_extensions.cpython-310.pyc | Bin 66590 -> 0 bytes .../_vendor/__pycache__/zipp.cpython-310.pyc | Bin 10219 -> 0 bytes .../_vendor/importlib_metadata/__init__.py | 1047 -- .../__pycache__/__init__.cpython-310.pyc | Bin 37411 -> 0 bytes .../__pycache__/_adapters.cpython-310.pyc | Bin 2396 -> 0 bytes .../__pycache__/_collections.cpython-310.pyc | Bin 1571 -> 0 bytes .../__pycache__/_compat.cpython-310.pyc | Bin 2060 -> 0 bytes .../__pycache__/_functools.cpython-310.pyc | Bin 3161 -> 0 bytes .../__pycache__/_itertools.cpython-310.pyc | Bin 2042 -> 0 bytes .../__pycache__/_meta.cpython-310.pyc | Bin 2350 -> 0 bytes .../__pycache__/_text.cpython-310.pyc | Bin 3094 -> 0 bytes .../_vendor/importlib_metadata/_adapters.py | 68 - .../importlib_metadata/_collections.py | 30 - .../_vendor/importlib_metadata/_compat.py | 71 - .../_vendor/importlib_metadata/_functools.py | 104 - .../_vendor/importlib_metadata/_itertools.py | 73 - .../_vendor/importlib_metadata/_meta.py | 48 - .../_vendor/importlib_metadata/_text.py | 99 - .../_vendor/importlib_resources/__init__.py | 36 - .../__pycache__/__init__.cpython-310.pyc | Bin 631 -> 0 bytes .../__pycache__/_adapters.cpython-310.pyc | Bin 7339 -> 0 bytes .../__pycache__/_common.cpython-310.pyc | Bin 2629 -> 0 bytes .../__pycache__/_compat.cpython-310.pyc | Bin 3489 -> 0 bytes .../__pycache__/_itertools.cpython-310.pyc | Bin 876 -> 0 bytes .../__pycache__/_legacy.cpython-310.pyc | Bin 4212 -> 0 bytes .../__pycache__/abc.cpython-310.pyc | Bin 5365 -> 0 bytes .../__pycache__/readers.cpython-310.pyc | Bin 5449 -> 0 bytes .../__pycache__/simple.cpython-310.pyc | Bin 4717 -> 0 bytes .../_vendor/importlib_resources/_adapters.py | 170 - .../_vendor/importlib_resources/_common.py | 104 - .../_vendor/importlib_resources/_compat.py | 98 - .../_vendor/importlib_resources/_itertools.py | 35 - .../_vendor/importlib_resources/_legacy.py | 121 - .../_vendor/importlib_resources/abc.py | 137 - .../_vendor/importlib_resources/readers.py | 122 - .../_vendor/importlib_resources/simple.py | 116 - .../setuptools/_vendor/jaraco/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 183 -> 0 bytes .../__pycache__/context.cpython-310.pyc | Bin 6315 -> 0 bytes .../__pycache__/functools.cpython-310.pyc | Bin 15601 -> 0 bytes .../setuptools/_vendor/jaraco/context.py | 213 - .../setuptools/_vendor/jaraco/functools.py | 525 - .../_vendor/jaraco/text/__init__.py | 599 -- .../text/__pycache__/__init__.cpython-310.pyc | Bin 19643 -> 0 bytes .../_vendor/more_itertools/__init__.py | 4 - .../__pycache__/__init__.cpython-310.pyc | Bin 257 -> 0 bytes .../__pycache__/more.cpython-310.pyc | Bin 109990 -> 0 bytes .../__pycache__/recipes.cpython-310.pyc | Bin 17957 -> 0 bytes .../setuptools/_vendor/more_itertools/more.py | 3824 -------- .../_vendor/more_itertools/recipes.py | 620 -- .../setuptools/_vendor/ordered_set.py | 488 - .../setuptools/_vendor/packaging/__about__.py | 26 - .../setuptools/_vendor/packaging/__init__.py | 25 - .../__pycache__/__about__.cpython-310.pyc | Bin 583 -> 0 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 439 -> 0 bytes .../__pycache__/_manylinux.cpython-310.pyc | Bin 7293 -> 0 bytes .../__pycache__/_musllinux.cpython-310.pyc | Bin 4605 -> 0 bytes .../__pycache__/_structures.cpython-310.pyc | Bin 2698 -> 0 bytes .../__pycache__/markers.cpython-310.pyc | Bin 9288 -> 0 bytes .../__pycache__/requirements.cpython-310.pyc | Bin 3974 -> 0 bytes .../__pycache__/specifiers.cpython-310.pyc | Bin 21520 -> 0 bytes .../__pycache__/tags.cpython-310.pyc | Bin 12189 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 3568 -> 0 bytes .../__pycache__/version.cpython-310.pyc | Bin 12918 -> 0 bytes .../_vendor/packaging/_manylinux.py | 301 - .../_vendor/packaging/_musllinux.py | 136 - .../_vendor/packaging/_structures.py | 61 - .../setuptools/_vendor/packaging/markers.py | 304 - .../_vendor/packaging/requirements.py | 146 - .../_vendor/packaging/specifiers.py | 802 -- .../setuptools/_vendor/packaging/tags.py | 487 - .../setuptools/_vendor/packaging/utils.py | 136 - .../setuptools/_vendor/packaging/version.py | 504 - .../setuptools/_vendor/pyparsing/__init__.py | 331 - .../__pycache__/__init__.cpython-310.pyc | Bin 7110 -> 0 bytes .../__pycache__/actions.cpython-310.pyc | Bin 7175 -> 0 bytes .../__pycache__/common.cpython-310.pyc | Bin 10098 -> 0 bytes .../__pycache__/core.cpython-310.pyc | Bin 176387 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 9065 -> 0 bytes .../__pycache__/helpers.cpython-310.pyc | Bin 35242 -> 0 bytes .../__pycache__/results.cpython-310.pyc | Bin 24792 -> 0 bytes .../__pycache__/testing.cpython-310.pyc | Bin 12095 -> 0 bytes .../__pycache__/unicode.cpython-310.pyc | Bin 9807 -> 0 bytes .../__pycache__/util.cpython-310.pyc | Bin 8598 -> 0 bytes .../setuptools/_vendor/pyparsing/actions.py | 207 - .../setuptools/_vendor/pyparsing/common.py | 424 - .../setuptools/_vendor/pyparsing/core.py | 5812 ----------- .../_vendor/pyparsing/diagram/__init__.py | 611 -- .../__pycache__/__init__.cpython-310.pyc | Bin 16056 -> 0 bytes .../_vendor/pyparsing/exceptions.py | 267 - .../setuptools/_vendor/pyparsing/helpers.py | 1083 -- .../setuptools/_vendor/pyparsing/results.py | 760 -- .../setuptools/_vendor/pyparsing/testing.py | 331 - .../setuptools/_vendor/pyparsing/unicode.py | 332 - .../setuptools/_vendor/pyparsing/util.py | 235 - .../setuptools/_vendor/tomli/__init__.py | 11 - .../__pycache__/__init__.cpython-310.pyc | Bin 348 -> 0 bytes .../tomli/__pycache__/_parser.cpython-310.pyc | Bin 17062 -> 0 bytes .../tomli/__pycache__/_re.cpython-310.pyc | Bin 2894 -> 0 bytes .../tomli/__pycache__/_types.cpython-310.pyc | Bin 318 -> 0 bytes .../setuptools/_vendor/tomli/_parser.py | 691 -- .../setuptools/_vendor/tomli/_re.py | 107 - .../setuptools/_vendor/tomli/_types.py | 10 - .../setuptools/_vendor/typing_extensions.py | 2296 ----- .../site-packages/setuptools/_vendor/zipp.py | 329 - .../site-packages/setuptools/archive_util.py | 213 - .../site-packages/setuptools/build_meta.py | 304 - venv/Lib/site-packages/setuptools/cli-32.exe | Bin 65536 -> 0 bytes venv/Lib/site-packages/setuptools/cli-64.exe | Bin 74752 -> 0 bytes .../site-packages/setuptools/cli-arm64.exe | Bin 137216 -> 0 bytes venv/Lib/site-packages/setuptools/cli.exe | Bin 65536 -> 0 bytes .../setuptools/command/__init__.py | 8 - .../__pycache__/__init__.cpython-310.pyc | Bin 365 -> 0 bytes .../command/__pycache__/alias.cpython-310.pyc | Bin 2367 -> 0 bytes .../__pycache__/bdist_egg.cpython-310.pyc | Bin 13117 -> 0 bytes .../__pycache__/bdist_rpm.cpython-310.pyc | Bin 1580 -> 0 bytes .../command/__pycache__/build.cpython-310.pyc | Bin 1210 -> 0 bytes .../__pycache__/build_clib.cpython-310.pyc | Bin 2456 -> 0 bytes .../__pycache__/build_ext.cpython-310.pyc | Bin 9883 -> 0 bytes .../__pycache__/build_py.cpython-310.pyc | Bin 10662 -> 0 bytes .../__pycache__/develop.cpython-310.pyc | Bin 6143 -> 0 bytes .../__pycache__/dist_info.cpython-310.pyc | Bin 2624 -> 0 bytes .../__pycache__/easy_install.cpython-310.pyc | Bin 64416 -> 0 bytes .../__pycache__/egg_info.cpython-310.pyc | Bin 22885 -> 0 bytes .../__pycache__/install.cpython-310.pyc | Bin 4276 -> 0 bytes .../install_egg_info.cpython-310.pyc | Bin 2450 -> 0 bytes .../__pycache__/install_lib.cpython-310.pyc | Bin 4162 -> 0 bytes .../install_scripts.cpython-310.pyc | Bin 2444 -> 0 bytes .../__pycache__/py36compat.cpython-310.pyc | Bin 4527 -> 0 bytes .../__pycache__/register.cpython-310.pyc | Bin 831 -> 0 bytes .../__pycache__/rotate.cpython-310.pyc | Bin 2498 -> 0 bytes .../__pycache__/saveopts.cpython-310.pyc | Bin 917 -> 0 bytes .../command/__pycache__/sdist.cpython-310.pyc | Bin 6975 -> 0 bytes .../__pycache__/setopt.cpython-310.pyc | Bin 4679 -> 0 bytes .../command/__pycache__/test.cpython-310.pyc | Bin 8221 -> 0 bytes .../__pycache__/upload.cpython-310.pyc | Bin 804 -> 0 bytes .../__pycache__/upload_docs.cpython-310.pyc | Bin 6394 -> 0 bytes .../site-packages/setuptools/command/alias.py | 78 - .../setuptools/command/bdist_egg.py | 457 - .../setuptools/command/bdist_rpm.py | 40 - .../site-packages/setuptools/command/build.py | 24 - .../setuptools/command/build_clib.py | 101 - .../setuptools/command/build_ext.py | 328 - .../setuptools/command/build_py.py | 298 - .../setuptools/command/develop.py | 193 - .../setuptools/command/dist_info.py | 69 - .../setuptools/command/easy_install.py | 2312 ----- .../setuptools/command/egg_info.py | 752 -- .../setuptools/command/install.py | 139 - .../setuptools/command/install_egg_info.py | 63 - .../setuptools/command/install_lib.py | 122 - .../setuptools/command/install_scripts.py | 70 - .../setuptools/command/launcher manifest.xml | 15 - .../setuptools/command/py36compat.py | 134 - .../setuptools/command/register.py | 18 - .../setuptools/command/rotate.py | 64 - .../setuptools/command/saveopts.py | 22 - .../site-packages/setuptools/command/sdist.py | 196 - .../setuptools/command/setopt.py | 149 - .../site-packages/setuptools/command/test.py | 251 - .../setuptools/command/upload.py | 17 - .../setuptools/command/upload_docs.py | 212 - .../setuptools/config/__init__.py | 35 - .../__pycache__/__init__.cpython-310.pyc | Bin 1433 -> 0 bytes .../_apply_pyprojecttoml.cpython-310.pyc | Bin 13516 -> 0 bytes .../config/__pycache__/expand.cpython-310.pyc | Bin 18083 -> 0 bytes .../__pycache__/pyprojecttoml.cpython-310.pyc | Bin 16146 -> 0 bytes .../__pycache__/setupcfg.cpython-310.pyc | Bin 19665 -> 0 bytes .../setuptools/config/_apply_pyprojecttoml.py | 377 - .../config/_validate_pyproject/__init__.py | 34 - .../__pycache__/__init__.cpython-310.pyc | Bin 1508 -> 0 bytes .../error_reporting.cpython-310.pyc | Bin 11569 -> 0 bytes .../extra_validations.cpython-310.pyc | Bin 1422 -> 0 bytes .../fastjsonschema_exceptions.cpython-310.pyc | Bin 2440 -> 0 bytes ...fastjsonschema_validations.cpython-310.pyc | Bin 68681 -> 0 bytes .../__pycache__/formats.cpython-310.pyc | Bin 8488 -> 0 bytes .../_validate_pyproject/error_reporting.py | 318 - .../_validate_pyproject/extra_validations.py | 36 - .../fastjsonschema_exceptions.py | 51 - .../fastjsonschema_validations.py | 1035 -- .../config/_validate_pyproject/formats.py | 257 - .../site-packages/setuptools/config/expand.py | 479 - .../setuptools/config/pyprojecttoml.py | 484 - .../setuptools/config/setupcfg.py | 713 -- venv/Lib/site-packages/setuptools/dep_util.py | 25 - venv/Lib/site-packages/setuptools/depends.py | 176 - .../Lib/site-packages/setuptools/discovery.py | 588 -- venv/Lib/site-packages/setuptools/dist.py | 1222 --- venv/Lib/site-packages/setuptools/errors.py | 58 - .../Lib/site-packages/setuptools/extension.py | 140 - .../setuptools/extern/__init__.py | 76 - .../__pycache__/__init__.cpython-310.pyc | Bin 3007 -> 0 bytes venv/Lib/site-packages/setuptools/glob.py | 167 - venv/Lib/site-packages/setuptools/gui-32.exe | Bin 65536 -> 0 bytes venv/Lib/site-packages/setuptools/gui-64.exe | Bin 75264 -> 0 bytes .../site-packages/setuptools/gui-arm64.exe | Bin 137728 -> 0 bytes venv/Lib/site-packages/setuptools/gui.exe | Bin 65536 -> 0 bytes .../Lib/site-packages/setuptools/installer.py | 104 - venv/Lib/site-packages/setuptools/launch.py | 36 - venv/Lib/site-packages/setuptools/logging.py | 36 - venv/Lib/site-packages/setuptools/monkey.py | 177 - venv/Lib/site-packages/setuptools/msvc.py | 1805 ---- .../site-packages/setuptools/namespaces.py | 107 - .../site-packages/setuptools/package_index.py | 1126 --- .../site-packages/setuptools/py34compat.py | 13 - venv/Lib/site-packages/setuptools/sandbox.py | 530 - .../setuptools/script (dev).tmpl | 6 - venv/Lib/site-packages/setuptools/script.tmpl | 3 - .../site-packages/setuptools/unicode_utils.py | 42 - venv/Lib/site-packages/setuptools/version.py | 6 - venv/Lib/site-packages/setuptools/wheel.py | 213 - .../setuptools/windows_support.py | 29 - .../PKG-INFO | 41 - .../SOURCES.txt | 9 - .../dependency_links.txt | 1 - .../installed-files.txt | 7 - .../requires.txt | 1 - .../top_level.txt | 1 - venv/Lib/site-packages/statistics/__init__.py | 597 -- .../__pycache__/__init__.cpython-310.pyc | Bin 15251 -> 0 bytes .../tzdata-2025.2.dist-info/INSTALLER | 1 - .../tzdata-2025.2.dist-info/METADATA | 34 - .../tzdata-2025.2.dist-info/RECORD | 657 -- .../tzdata-2025.2.dist-info/REQUESTED | 0 .../tzdata-2025.2.dist-info/WHEEL | 6 - .../tzdata-2025.2.dist-info/licenses/LICENSE | 15 - .../licenses/licenses/LICENSE_APACHE | 201 - .../tzdata-2025.2.dist-info/top_level.txt | 1 - venv/Lib/site-packages/tzdata/__init__.py | 6 - .../__pycache__/__init__.cpython-310.pyc | Bin 213 -> 0 bytes .../tzdata/zoneinfo/Africa/Abidjan | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Accra | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Addis_Ababa | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Algiers | Bin 470 -> 0 bytes .../tzdata/zoneinfo/Africa/Asmara | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Asmera | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Bamako | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Bangui | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Banjul | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Bissau | Bin 149 -> 0 bytes .../tzdata/zoneinfo/Africa/Blantyre | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Brazzaville | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Bujumbura | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Cairo | Bin 1309 -> 0 bytes .../tzdata/zoneinfo/Africa/Casablanca | Bin 1919 -> 0 bytes .../tzdata/zoneinfo/Africa/Ceuta | Bin 562 -> 0 bytes .../tzdata/zoneinfo/Africa/Conakry | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Dakar | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Dar_es_Salaam | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Djibouti | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Douala | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/El_Aaiun | Bin 1830 -> 0 bytes .../tzdata/zoneinfo/Africa/Freetown | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Gaborone | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Harare | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Johannesburg | Bin 190 -> 0 bytes .../site-packages/tzdata/zoneinfo/Africa/Juba | Bin 458 -> 0 bytes .../tzdata/zoneinfo/Africa/Kampala | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Khartoum | Bin 458 -> 0 bytes .../tzdata/zoneinfo/Africa/Kigali | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Kinshasa | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Lagos | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Libreville | Bin 180 -> 0 bytes .../site-packages/tzdata/zoneinfo/Africa/Lome | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Luanda | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Lubumbashi | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Lusaka | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Malabo | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Maputo | Bin 131 -> 0 bytes .../tzdata/zoneinfo/Africa/Maseru | Bin 190 -> 0 bytes .../tzdata/zoneinfo/Africa/Mbabane | Bin 190 -> 0 bytes .../tzdata/zoneinfo/Africa/Mogadishu | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Monrovia | Bin 164 -> 0 bytes .../tzdata/zoneinfo/Africa/Nairobi | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Africa/Ndjamena | Bin 160 -> 0 bytes .../tzdata/zoneinfo/Africa/Niamey | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Nouakchott | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Ouagadougou | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Porto-Novo | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Africa/Sao_Tome | Bin 173 -> 0 bytes .../tzdata/zoneinfo/Africa/Timbuktu | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Africa/Tripoli | Bin 431 -> 0 bytes .../tzdata/zoneinfo/Africa/Tunis | Bin 449 -> 0 bytes .../tzdata/zoneinfo/Africa/Windhoek | Bin 638 -> 0 bytes .../tzdata/zoneinfo/Africa/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes .../tzdata/zoneinfo/America/Adak | Bin 969 -> 0 bytes .../tzdata/zoneinfo/America/Anchorage | Bin 977 -> 0 bytes .../tzdata/zoneinfo/America/Anguilla | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Antigua | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Araguaina | Bin 592 -> 0 bytes .../zoneinfo/America/Argentina/Buenos_Aires | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/Catamarca | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/ComodRivadavia | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Argentina/Cordoba | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Argentina/Jujuy | Bin 690 -> 0 bytes .../zoneinfo/America/Argentina/La_Rioja | Bin 717 -> 0 bytes .../tzdata/zoneinfo/America/Argentina/Mendoza | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/Rio_Gallegos | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Argentina/Salta | Bin 690 -> 0 bytes .../zoneinfo/America/Argentina/San_Juan | Bin 717 -> 0 bytes .../zoneinfo/America/Argentina/San_Luis | Bin 717 -> 0 bytes .../tzdata/zoneinfo/America/Argentina/Tucuman | Bin 726 -> 0 bytes .../tzdata/zoneinfo/America/Argentina/Ushuaia | Bin 708 -> 0 bytes .../zoneinfo/America/Argentina/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 191 -> 0 bytes .../tzdata/zoneinfo/America/Aruba | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Asuncion | Bin 1085 -> 0 bytes .../tzdata/zoneinfo/America/Atikokan | Bin 149 -> 0 bytes .../tzdata/zoneinfo/America/Atka | Bin 969 -> 0 bytes .../tzdata/zoneinfo/America/Bahia | Bin 682 -> 0 bytes .../tzdata/zoneinfo/America/Bahia_Banderas | Bin 700 -> 0 bytes .../tzdata/zoneinfo/America/Barbados | Bin 278 -> 0 bytes .../tzdata/zoneinfo/America/Belem | Bin 394 -> 0 bytes .../tzdata/zoneinfo/America/Belize | Bin 1045 -> 0 bytes .../tzdata/zoneinfo/America/Blanc-Sablon | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Boa_Vista | Bin 430 -> 0 bytes .../tzdata/zoneinfo/America/Bogota | Bin 179 -> 0 bytes .../tzdata/zoneinfo/America/Boise | Bin 999 -> 0 bytes .../tzdata/zoneinfo/America/Buenos_Aires | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Cambridge_Bay | Bin 883 -> 0 bytes .../tzdata/zoneinfo/America/Campo_Grande | Bin 952 -> 0 bytes .../tzdata/zoneinfo/America/Cancun | Bin 538 -> 0 bytes .../tzdata/zoneinfo/America/Caracas | Bin 190 -> 0 bytes .../tzdata/zoneinfo/America/Catamarca | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Cayenne | Bin 151 -> 0 bytes .../tzdata/zoneinfo/America/Cayman | Bin 149 -> 0 bytes .../tzdata/zoneinfo/America/Chicago | Bin 1754 -> 0 bytes .../tzdata/zoneinfo/America/Chihuahua | Bin 691 -> 0 bytes .../tzdata/zoneinfo/America/Ciudad_Juarez | Bin 718 -> 0 bytes .../tzdata/zoneinfo/America/Coral_Harbour | Bin 149 -> 0 bytes .../tzdata/zoneinfo/America/Cordoba | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Costa_Rica | Bin 232 -> 0 bytes .../tzdata/zoneinfo/America/Coyhaique | Bin 1362 -> 0 bytes .../tzdata/zoneinfo/America/Creston | Bin 240 -> 0 bytes .../tzdata/zoneinfo/America/Cuiaba | Bin 934 -> 0 bytes .../tzdata/zoneinfo/America/Curacao | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Danmarkshavn | Bin 447 -> 0 bytes .../tzdata/zoneinfo/America/Dawson | Bin 1029 -> 0 bytes .../tzdata/zoneinfo/America/Dawson_Creek | Bin 683 -> 0 bytes .../tzdata/zoneinfo/America/Denver | Bin 1042 -> 0 bytes .../tzdata/zoneinfo/America/Detroit | Bin 899 -> 0 bytes .../tzdata/zoneinfo/America/Dominica | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Edmonton | Bin 970 -> 0 bytes .../tzdata/zoneinfo/America/Eirunepe | Bin 436 -> 0 bytes .../tzdata/zoneinfo/America/El_Salvador | Bin 176 -> 0 bytes .../tzdata/zoneinfo/America/Ensenada | Bin 1079 -> 0 bytes .../tzdata/zoneinfo/America/Fort_Nelson | Bin 1448 -> 0 bytes .../tzdata/zoneinfo/America/Fort_Wayne | Bin 531 -> 0 bytes .../tzdata/zoneinfo/America/Fortaleza | Bin 484 -> 0 bytes .../tzdata/zoneinfo/America/Glace_Bay | Bin 880 -> 0 bytes .../tzdata/zoneinfo/America/Godthab | Bin 965 -> 0 bytes .../tzdata/zoneinfo/America/Goose_Bay | Bin 1580 -> 0 bytes .../tzdata/zoneinfo/America/Grand_Turk | Bin 853 -> 0 bytes .../tzdata/zoneinfo/America/Grenada | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Guadeloupe | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Guatemala | Bin 212 -> 0 bytes .../tzdata/zoneinfo/America/Guayaquil | Bin 179 -> 0 bytes .../tzdata/zoneinfo/America/Guyana | Bin 181 -> 0 bytes .../tzdata/zoneinfo/America/Halifax | Bin 1672 -> 0 bytes .../tzdata/zoneinfo/America/Havana | Bin 1117 -> 0 bytes .../tzdata/zoneinfo/America/Hermosillo | Bin 258 -> 0 bytes .../zoneinfo/America/Indiana/Indianapolis | Bin 531 -> 0 bytes .../tzdata/zoneinfo/America/Indiana/Knox | Bin 1016 -> 0 bytes .../tzdata/zoneinfo/America/Indiana/Marengo | Bin 567 -> 0 bytes .../zoneinfo/America/Indiana/Petersburg | Bin 683 -> 0 bytes .../tzdata/zoneinfo/America/Indiana/Tell_City | Bin 522 -> 0 bytes .../tzdata/zoneinfo/America/Indiana/Vevay | Bin 369 -> 0 bytes .../tzdata/zoneinfo/America/Indiana/Vincennes | Bin 558 -> 0 bytes .../tzdata/zoneinfo/America/Indiana/Winamac | Bin 603 -> 0 bytes .../zoneinfo/America/Indiana/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 189 -> 0 bytes .../tzdata/zoneinfo/America/Indianapolis | Bin 531 -> 0 bytes .../tzdata/zoneinfo/America/Inuvik | Bin 817 -> 0 bytes .../tzdata/zoneinfo/America/Iqaluit | Bin 855 -> 0 bytes .../tzdata/zoneinfo/America/Jamaica | Bin 339 -> 0 bytes .../tzdata/zoneinfo/America/Jujuy | Bin 690 -> 0 bytes .../tzdata/zoneinfo/America/Juneau | Bin 966 -> 0 bytes .../zoneinfo/America/Kentucky/Louisville | Bin 1242 -> 0 bytes .../zoneinfo/America/Kentucky/Monticello | Bin 972 -> 0 bytes .../zoneinfo/America/Kentucky/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 190 -> 0 bytes .../tzdata/zoneinfo/America/Knox_IN | Bin 1016 -> 0 bytes .../tzdata/zoneinfo/America/Kralendijk | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/La_Paz | Bin 170 -> 0 bytes .../tzdata/zoneinfo/America/Lima | Bin 283 -> 0 bytes .../tzdata/zoneinfo/America/Los_Angeles | Bin 1294 -> 0 bytes .../tzdata/zoneinfo/America/Louisville | Bin 1242 -> 0 bytes .../tzdata/zoneinfo/America/Lower_Princes | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Maceio | Bin 502 -> 0 bytes .../tzdata/zoneinfo/America/Managua | Bin 295 -> 0 bytes .../tzdata/zoneinfo/America/Manaus | Bin 412 -> 0 bytes .../tzdata/zoneinfo/America/Marigot | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Martinique | Bin 178 -> 0 bytes .../tzdata/zoneinfo/America/Matamoros | Bin 437 -> 0 bytes .../tzdata/zoneinfo/America/Mazatlan | Bin 690 -> 0 bytes .../tzdata/zoneinfo/America/Mendoza | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Menominee | Bin 917 -> 0 bytes .../tzdata/zoneinfo/America/Merida | Bin 654 -> 0 bytes .../tzdata/zoneinfo/America/Metlakatla | Bin 586 -> 0 bytes .../tzdata/zoneinfo/America/Mexico_City | Bin 773 -> 0 bytes .../tzdata/zoneinfo/America/Miquelon | Bin 550 -> 0 bytes .../tzdata/zoneinfo/America/Moncton | Bin 1493 -> 0 bytes .../tzdata/zoneinfo/America/Monterrey | Bin 709 -> 0 bytes .../tzdata/zoneinfo/America/Montevideo | Bin 969 -> 0 bytes .../tzdata/zoneinfo/America/Montreal | Bin 1717 -> 0 bytes .../tzdata/zoneinfo/America/Montserrat | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Nassau | Bin 1717 -> 0 bytes .../tzdata/zoneinfo/America/New_York | Bin 1744 -> 0 bytes .../tzdata/zoneinfo/America/Nipigon | Bin 1717 -> 0 bytes .../tzdata/zoneinfo/America/Nome | Bin 975 -> 0 bytes .../tzdata/zoneinfo/America/Noronha | Bin 484 -> 0 bytes .../zoneinfo/America/North_Dakota/Beulah | Bin 1043 -> 0 bytes .../zoneinfo/America/North_Dakota/Center | Bin 990 -> 0 bytes .../zoneinfo/America/North_Dakota/New_Salem | Bin 990 -> 0 bytes .../zoneinfo/America/North_Dakota/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 194 -> 0 bytes .../tzdata/zoneinfo/America/Nuuk | Bin 965 -> 0 bytes .../tzdata/zoneinfo/America/Ojinaga | Bin 718 -> 0 bytes .../tzdata/zoneinfo/America/Panama | Bin 149 -> 0 bytes .../tzdata/zoneinfo/America/Pangnirtung | Bin 855 -> 0 bytes .../tzdata/zoneinfo/America/Paramaribo | Bin 187 -> 0 bytes .../tzdata/zoneinfo/America/Phoenix | Bin 240 -> 0 bytes .../tzdata/zoneinfo/America/Port-au-Prince | Bin 565 -> 0 bytes .../tzdata/zoneinfo/America/Port_of_Spain | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Porto_Acre | Bin 418 -> 0 bytes .../tzdata/zoneinfo/America/Porto_Velho | Bin 394 -> 0 bytes .../tzdata/zoneinfo/America/Puerto_Rico | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Punta_Arenas | Bin 1218 -> 0 bytes .../tzdata/zoneinfo/America/Rainy_River | Bin 1294 -> 0 bytes .../tzdata/zoneinfo/America/Rankin_Inlet | Bin 807 -> 0 bytes .../tzdata/zoneinfo/America/Recife | Bin 484 -> 0 bytes .../tzdata/zoneinfo/America/Regina | Bin 638 -> 0 bytes .../tzdata/zoneinfo/America/Resolute | Bin 807 -> 0 bytes .../tzdata/zoneinfo/America/Rio_Branco | Bin 418 -> 0 bytes .../tzdata/zoneinfo/America/Rosario | Bin 708 -> 0 bytes .../tzdata/zoneinfo/America/Santa_Isabel | Bin 1079 -> 0 bytes .../tzdata/zoneinfo/America/Santarem | Bin 409 -> 0 bytes .../tzdata/zoneinfo/America/Santiago | Bin 1354 -> 0 bytes .../tzdata/zoneinfo/America/Santo_Domingo | Bin 317 -> 0 bytes .../tzdata/zoneinfo/America/Sao_Paulo | Bin 952 -> 0 bytes .../tzdata/zoneinfo/America/Scoresbysund | Bin 984 -> 0 bytes .../tzdata/zoneinfo/America/Shiprock | Bin 1042 -> 0 bytes .../tzdata/zoneinfo/America/Sitka | Bin 956 -> 0 bytes .../tzdata/zoneinfo/America/St_Barthelemy | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/St_Johns | Bin 1878 -> 0 bytes .../tzdata/zoneinfo/America/St_Kitts | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/St_Lucia | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/St_Thomas | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/St_Vincent | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Swift_Current | Bin 368 -> 0 bytes .../tzdata/zoneinfo/America/Tegucigalpa | Bin 194 -> 0 bytes .../tzdata/zoneinfo/America/Thule | Bin 455 -> 0 bytes .../tzdata/zoneinfo/America/Thunder_Bay | Bin 1717 -> 0 bytes .../tzdata/zoneinfo/America/Tijuana | Bin 1079 -> 0 bytes .../tzdata/zoneinfo/America/Toronto | Bin 1717 -> 0 bytes .../tzdata/zoneinfo/America/Tortola | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Vancouver | Bin 1330 -> 0 bytes .../tzdata/zoneinfo/America/Virgin | Bin 177 -> 0 bytes .../tzdata/zoneinfo/America/Whitehorse | Bin 1029 -> 0 bytes .../tzdata/zoneinfo/America/Winnipeg | Bin 1294 -> 0 bytes .../tzdata/zoneinfo/America/Yakutat | Bin 946 -> 0 bytes .../tzdata/zoneinfo/America/Yellowknife | Bin 970 -> 0 bytes .../tzdata/zoneinfo/America/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 181 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Casey | Bin 287 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Davis | Bin 197 -> 0 bytes .../tzdata/zoneinfo/Antarctica/DumontDUrville | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Macquarie | Bin 976 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Mawson | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Antarctica/McMurdo | Bin 1043 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Palmer | Bin 887 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Rothera | Bin 132 -> 0 bytes .../tzdata/zoneinfo/Antarctica/South_Pole | Bin 1043 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Syowa | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Troll | Bin 158 -> 0 bytes .../tzdata/zoneinfo/Antarctica/Vostok | Bin 170 -> 0 bytes .../tzdata/zoneinfo/Antarctica/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 184 -> 0 bytes .../tzdata/zoneinfo/Arctic/Longyearbyen | Bin 705 -> 0 bytes .../tzdata/zoneinfo/Arctic/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Aden | Bin 133 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Almaty | Bin 618 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Amman | Bin 928 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Anadyr | Bin 743 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Aqtau | Bin 606 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Aqtobe | Bin 615 -> 0 bytes .../tzdata/zoneinfo/Asia/Ashgabat | Bin 375 -> 0 bytes .../tzdata/zoneinfo/Asia/Ashkhabad | Bin 375 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Atyrau | Bin 616 -> 0 bytes .../tzdata/zoneinfo/Asia/Baghdad | Bin 630 -> 0 bytes .../tzdata/zoneinfo/Asia/Bahrain | Bin 152 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Baku | Bin 744 -> 0 bytes .../tzdata/zoneinfo/Asia/Bangkok | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Asia/Barnaul | Bin 753 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Beirut | Bin 732 -> 0 bytes .../tzdata/zoneinfo/Asia/Bishkek | Bin 618 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Brunei | Bin 320 -> 0 bytes .../tzdata/zoneinfo/Asia/Calcutta | Bin 220 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Chita | Bin 750 -> 0 bytes .../tzdata/zoneinfo/Asia/Choibalsan | Bin 594 -> 0 bytes .../tzdata/zoneinfo/Asia/Chongqing | Bin 393 -> 0 bytes .../tzdata/zoneinfo/Asia/Chungking | Bin 393 -> 0 bytes .../tzdata/zoneinfo/Asia/Colombo | Bin 247 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Dacca | Bin 231 -> 0 bytes .../tzdata/zoneinfo/Asia/Damascus | Bin 1234 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Dhaka | Bin 231 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Dili | Bin 170 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Dubai | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Asia/Dushanbe | Bin 366 -> 0 bytes .../tzdata/zoneinfo/Asia/Famagusta | Bin 940 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Gaza | Bin 2950 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Harbin | Bin 393 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Hebron | Bin 2968 -> 0 bytes .../tzdata/zoneinfo/Asia/Ho_Chi_Minh | Bin 236 -> 0 bytes .../tzdata/zoneinfo/Asia/Hong_Kong | Bin 775 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Hovd | Bin 594 -> 0 bytes .../tzdata/zoneinfo/Asia/Irkutsk | Bin 760 -> 0 bytes .../tzdata/zoneinfo/Asia/Istanbul | Bin 1200 -> 0 bytes .../tzdata/zoneinfo/Asia/Jakarta | Bin 248 -> 0 bytes .../tzdata/zoneinfo/Asia/Jayapura | Bin 171 -> 0 bytes .../tzdata/zoneinfo/Asia/Jerusalem | Bin 1074 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Kabul | Bin 159 -> 0 bytes .../tzdata/zoneinfo/Asia/Kamchatka | Bin 727 -> 0 bytes .../tzdata/zoneinfo/Asia/Karachi | Bin 266 -> 0 bytes .../tzdata/zoneinfo/Asia/Kashgar | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Asia/Kathmandu | Bin 161 -> 0 bytes .../tzdata/zoneinfo/Asia/Katmandu | Bin 161 -> 0 bytes .../tzdata/zoneinfo/Asia/Khandyga | Bin 775 -> 0 bytes .../tzdata/zoneinfo/Asia/Kolkata | Bin 220 -> 0 bytes .../tzdata/zoneinfo/Asia/Krasnoyarsk | Bin 741 -> 0 bytes .../tzdata/zoneinfo/Asia/Kuala_Lumpur | Bin 256 -> 0 bytes .../tzdata/zoneinfo/Asia/Kuching | Bin 320 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Kuwait | Bin 133 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Macao | Bin 791 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Macau | Bin 791 -> 0 bytes .../tzdata/zoneinfo/Asia/Magadan | Bin 751 -> 0 bytes .../tzdata/zoneinfo/Asia/Makassar | Bin 190 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Manila | Bin 274 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Muscat | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Asia/Nicosia | Bin 597 -> 0 bytes .../tzdata/zoneinfo/Asia/Novokuznetsk | Bin 726 -> 0 bytes .../tzdata/zoneinfo/Asia/Novosibirsk | Bin 753 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Omsk | Bin 741 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Oral | Bin 625 -> 0 bytes .../tzdata/zoneinfo/Asia/Phnom_Penh | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Asia/Pontianak | Bin 247 -> 0 bytes .../tzdata/zoneinfo/Asia/Pyongyang | Bin 183 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Qatar | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Asia/Qostanay | Bin 624 -> 0 bytes .../tzdata/zoneinfo/Asia/Qyzylorda | Bin 624 -> 0 bytes .../tzdata/zoneinfo/Asia/Rangoon | Bin 187 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Riyadh | Bin 133 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Saigon | Bin 236 -> 0 bytes .../tzdata/zoneinfo/Asia/Sakhalin | Bin 755 -> 0 bytes .../tzdata/zoneinfo/Asia/Samarkand | Bin 366 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Seoul | Bin 415 -> 0 bytes .../tzdata/zoneinfo/Asia/Shanghai | Bin 393 -> 0 bytes .../tzdata/zoneinfo/Asia/Singapore | Bin 256 -> 0 bytes .../tzdata/zoneinfo/Asia/Srednekolymsk | Bin 742 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Taipei | Bin 511 -> 0 bytes .../tzdata/zoneinfo/Asia/Tashkent | Bin 366 -> 0 bytes .../tzdata/zoneinfo/Asia/Tbilisi | Bin 629 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Tehran | Bin 812 -> 0 bytes .../tzdata/zoneinfo/Asia/Tel_Aviv | Bin 1074 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Thimbu | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Asia/Thimphu | Bin 154 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Tokyo | Bin 213 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Tomsk | Bin 753 -> 0 bytes .../tzdata/zoneinfo/Asia/Ujung_Pandang | Bin 190 -> 0 bytes .../tzdata/zoneinfo/Asia/Ulaanbaatar | Bin 594 -> 0 bytes .../tzdata/zoneinfo/Asia/Ulan_Bator | Bin 594 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Urumqi | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Asia/Ust-Nera | Bin 771 -> 0 bytes .../tzdata/zoneinfo/Asia/Vientiane | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Asia/Vladivostok | Bin 742 -> 0 bytes .../tzdata/zoneinfo/Asia/Yakutsk | Bin 741 -> 0 bytes .../site-packages/tzdata/zoneinfo/Asia/Yangon | Bin 187 -> 0 bytes .../tzdata/zoneinfo/Asia/Yekaterinburg | Bin 760 -> 0 bytes .../tzdata/zoneinfo/Asia/Yerevan | Bin 708 -> 0 bytes .../tzdata/zoneinfo/Asia/__init__.py | 0 .../Asia/__pycache__/__init__.cpython-310.pyc | Bin 178 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Azores | Bin 1401 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Bermuda | Bin 1024 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Canary | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Cape_Verde | Bin 175 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Faeroe | Bin 441 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Faroe | Bin 441 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Jan_Mayen | Bin 705 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Madeira | Bin 1372 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Reykjavik | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Atlantic/South_Georgia | Bin 132 -> 0 bytes .../tzdata/zoneinfo/Atlantic/St_Helena | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Atlantic/Stanley | Bin 789 -> 0 bytes .../tzdata/zoneinfo/Atlantic/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 182 -> 0 bytes .../tzdata/zoneinfo/Australia/ACT | Bin 904 -> 0 bytes .../tzdata/zoneinfo/Australia/Adelaide | Bin 921 -> 0 bytes .../tzdata/zoneinfo/Australia/Brisbane | Bin 289 -> 0 bytes .../tzdata/zoneinfo/Australia/Broken_Hill | Bin 941 -> 0 bytes .../tzdata/zoneinfo/Australia/Canberra | Bin 904 -> 0 bytes .../tzdata/zoneinfo/Australia/Currie | Bin 1003 -> 0 bytes .../tzdata/zoneinfo/Australia/Darwin | Bin 234 -> 0 bytes .../tzdata/zoneinfo/Australia/Eucla | Bin 314 -> 0 bytes .../tzdata/zoneinfo/Australia/Hobart | Bin 1003 -> 0 bytes .../tzdata/zoneinfo/Australia/LHI | Bin 692 -> 0 bytes .../tzdata/zoneinfo/Australia/Lindeman | Bin 325 -> 0 bytes .../tzdata/zoneinfo/Australia/Lord_Howe | Bin 692 -> 0 bytes .../tzdata/zoneinfo/Australia/Melbourne | Bin 904 -> 0 bytes .../tzdata/zoneinfo/Australia/NSW | Bin 904 -> 0 bytes .../tzdata/zoneinfo/Australia/North | Bin 234 -> 0 bytes .../tzdata/zoneinfo/Australia/Perth | Bin 306 -> 0 bytes .../tzdata/zoneinfo/Australia/Queensland | Bin 289 -> 0 bytes .../tzdata/zoneinfo/Australia/South | Bin 921 -> 0 bytes .../tzdata/zoneinfo/Australia/Sydney | Bin 904 -> 0 bytes .../tzdata/zoneinfo/Australia/Tasmania | Bin 1003 -> 0 bytes .../tzdata/zoneinfo/Australia/Victoria | Bin 904 -> 0 bytes .../tzdata/zoneinfo/Australia/West | Bin 306 -> 0 bytes .../tzdata/zoneinfo/Australia/Yancowinna | Bin 941 -> 0 bytes .../tzdata/zoneinfo/Australia/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 183 -> 0 bytes .../site-packages/tzdata/zoneinfo/Brazil/Acre | Bin 418 -> 0 bytes .../tzdata/zoneinfo/Brazil/DeNoronha | Bin 484 -> 0 bytes .../site-packages/tzdata/zoneinfo/Brazil/East | Bin 952 -> 0 bytes .../site-packages/tzdata/zoneinfo/Brazil/West | Bin 412 -> 0 bytes .../tzdata/zoneinfo/Brazil/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/CET | Bin 1103 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/CST6CDT | Bin 1754 -> 0 bytes .../tzdata/zoneinfo/Canada/Atlantic | Bin 1672 -> 0 bytes .../tzdata/zoneinfo/Canada/Central | Bin 1294 -> 0 bytes .../tzdata/zoneinfo/Canada/Eastern | Bin 1717 -> 0 bytes .../tzdata/zoneinfo/Canada/Mountain | Bin 970 -> 0 bytes .../tzdata/zoneinfo/Canada/Newfoundland | Bin 1878 -> 0 bytes .../tzdata/zoneinfo/Canada/Pacific | Bin 1330 -> 0 bytes .../tzdata/zoneinfo/Canada/Saskatchewan | Bin 638 -> 0 bytes .../tzdata/zoneinfo/Canada/Yukon | Bin 1029 -> 0 bytes .../tzdata/zoneinfo/Canada/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes .../tzdata/zoneinfo/Chile/Continental | Bin 1354 -> 0 bytes .../tzdata/zoneinfo/Chile/EasterIsland | Bin 1174 -> 0 bytes .../tzdata/zoneinfo/Chile/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 179 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Cuba | Bin 1117 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/EET | Bin 682 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/EST | Bin 149 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/EST5EDT | Bin 1744 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Egypt | Bin 1309 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Eire | Bin 1496 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/GMT | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+0 | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+1 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+10 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+11 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+12 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+2 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+3 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+4 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+5 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+6 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+7 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+8 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT+9 | Bin 113 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-0 | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-1 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-10 | Bin 115 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-11 | Bin 115 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-12 | Bin 115 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-13 | Bin 115 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-14 | Bin 115 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-2 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-3 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-4 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-5 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-6 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-7 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-8 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT-9 | Bin 114 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/GMT0 | Bin 111 -> 0 bytes .../tzdata/zoneinfo/Etc/Greenwich | Bin 111 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/UCT | Bin 111 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/Etc/UTC | Bin 111 -> 0 bytes .../tzdata/zoneinfo/Etc/Universal | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/Etc/Zulu | Bin 111 -> 0 bytes .../tzdata/zoneinfo/Etc/__init__.py | 0 .../Etc/__pycache__/__init__.cpython-310.pyc | Bin 177 -> 0 bytes .../tzdata/zoneinfo/Europe/Amsterdam | Bin 1103 -> 0 bytes .../tzdata/zoneinfo/Europe/Andorra | Bin 389 -> 0 bytes .../tzdata/zoneinfo/Europe/Astrakhan | Bin 726 -> 0 bytes .../tzdata/zoneinfo/Europe/Athens | Bin 682 -> 0 bytes .../tzdata/zoneinfo/Europe/Belfast | Bin 1599 -> 0 bytes .../tzdata/zoneinfo/Europe/Belgrade | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Europe/Berlin | Bin 705 -> 0 bytes .../tzdata/zoneinfo/Europe/Bratislava | Bin 723 -> 0 bytes .../tzdata/zoneinfo/Europe/Brussels | Bin 1103 -> 0 bytes .../tzdata/zoneinfo/Europe/Bucharest | Bin 661 -> 0 bytes .../tzdata/zoneinfo/Europe/Budapest | Bin 766 -> 0 bytes .../tzdata/zoneinfo/Europe/Busingen | Bin 497 -> 0 bytes .../tzdata/zoneinfo/Europe/Chisinau | Bin 755 -> 0 bytes .../tzdata/zoneinfo/Europe/Copenhagen | Bin 705 -> 0 bytes .../tzdata/zoneinfo/Europe/Dublin | Bin 1496 -> 0 bytes .../tzdata/zoneinfo/Europe/Gibraltar | Bin 1220 -> 0 bytes .../tzdata/zoneinfo/Europe/Guernsey | Bin 1599 -> 0 bytes .../tzdata/zoneinfo/Europe/Helsinki | Bin 481 -> 0 bytes .../tzdata/zoneinfo/Europe/Isle_of_Man | Bin 1599 -> 0 bytes .../tzdata/zoneinfo/Europe/Istanbul | Bin 1200 -> 0 bytes .../tzdata/zoneinfo/Europe/Jersey | Bin 1599 -> 0 bytes .../tzdata/zoneinfo/Europe/Kaliningrad | Bin 904 -> 0 bytes .../site-packages/tzdata/zoneinfo/Europe/Kiev | Bin 558 -> 0 bytes .../tzdata/zoneinfo/Europe/Kirov | Bin 735 -> 0 bytes .../site-packages/tzdata/zoneinfo/Europe/Kyiv | Bin 558 -> 0 bytes .../tzdata/zoneinfo/Europe/Lisbon | Bin 1463 -> 0 bytes .../tzdata/zoneinfo/Europe/Ljubljana | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Europe/London | Bin 1599 -> 0 bytes .../tzdata/zoneinfo/Europe/Luxembourg | Bin 1103 -> 0 bytes .../tzdata/zoneinfo/Europe/Madrid | Bin 897 -> 0 bytes .../tzdata/zoneinfo/Europe/Malta | Bin 928 -> 0 bytes .../tzdata/zoneinfo/Europe/Mariehamn | Bin 481 -> 0 bytes .../tzdata/zoneinfo/Europe/Minsk | Bin 808 -> 0 bytes .../tzdata/zoneinfo/Europe/Monaco | Bin 1105 -> 0 bytes .../tzdata/zoneinfo/Europe/Moscow | Bin 908 -> 0 bytes .../tzdata/zoneinfo/Europe/Nicosia | Bin 597 -> 0 bytes .../site-packages/tzdata/zoneinfo/Europe/Oslo | Bin 705 -> 0 bytes .../tzdata/zoneinfo/Europe/Paris | Bin 1105 -> 0 bytes .../tzdata/zoneinfo/Europe/Podgorica | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Europe/Prague | Bin 723 -> 0 bytes .../site-packages/tzdata/zoneinfo/Europe/Riga | Bin 694 -> 0 bytes .../site-packages/tzdata/zoneinfo/Europe/Rome | Bin 947 -> 0 bytes .../tzdata/zoneinfo/Europe/Samara | Bin 732 -> 0 bytes .../tzdata/zoneinfo/Europe/San_Marino | Bin 947 -> 0 bytes .../tzdata/zoneinfo/Europe/Sarajevo | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Europe/Saratov | Bin 726 -> 0 bytes .../tzdata/zoneinfo/Europe/Simferopol | Bin 865 -> 0 bytes .../tzdata/zoneinfo/Europe/Skopje | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Europe/Sofia | Bin 592 -> 0 bytes .../tzdata/zoneinfo/Europe/Stockholm | Bin 705 -> 0 bytes .../tzdata/zoneinfo/Europe/Tallinn | Bin 675 -> 0 bytes .../tzdata/zoneinfo/Europe/Tirane | Bin 604 -> 0 bytes .../tzdata/zoneinfo/Europe/Tiraspol | Bin 755 -> 0 bytes .../tzdata/zoneinfo/Europe/Ulyanovsk | Bin 760 -> 0 bytes .../tzdata/zoneinfo/Europe/Uzhgorod | Bin 558 -> 0 bytes .../tzdata/zoneinfo/Europe/Vaduz | Bin 497 -> 0 bytes .../tzdata/zoneinfo/Europe/Vatican | Bin 947 -> 0 bytes .../tzdata/zoneinfo/Europe/Vienna | Bin 658 -> 0 bytes .../tzdata/zoneinfo/Europe/Vilnius | Bin 676 -> 0 bytes .../tzdata/zoneinfo/Europe/Volgograd | Bin 753 -> 0 bytes .../tzdata/zoneinfo/Europe/Warsaw | Bin 923 -> 0 bytes .../tzdata/zoneinfo/Europe/Zagreb | Bin 478 -> 0 bytes .../tzdata/zoneinfo/Europe/Zaporozhye | Bin 558 -> 0 bytes .../tzdata/zoneinfo/Europe/Zurich | Bin 497 -> 0 bytes .../tzdata/zoneinfo/Europe/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/Factory | Bin 113 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/GB | Bin 1599 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/GB-Eire | Bin 1599 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT | Bin 111 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT+0 | Bin 111 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT-0 | Bin 111 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/GMT0 | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/Greenwich | Bin 111 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/HST | Bin 221 -> 0 bytes .../site-packages/tzdata/zoneinfo/Hongkong | Bin 775 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/Iceland | Bin 130 -> 0 bytes .../tzdata/zoneinfo/Indian/Antananarivo | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Indian/Chagos | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Indian/Christmas | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Indian/Cocos | Bin 187 -> 0 bytes .../tzdata/zoneinfo/Indian/Comoro | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Indian/Kerguelen | Bin 152 -> 0 bytes .../site-packages/tzdata/zoneinfo/Indian/Mahe | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Indian/Maldives | Bin 152 -> 0 bytes .../tzdata/zoneinfo/Indian/Mauritius | Bin 179 -> 0 bytes .../tzdata/zoneinfo/Indian/Mayotte | Bin 191 -> 0 bytes .../tzdata/zoneinfo/Indian/Reunion | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Indian/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Iran | Bin 812 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Israel | Bin 1074 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/Jamaica | Bin 339 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Japan | Bin 213 -> 0 bytes .../site-packages/tzdata/zoneinfo/Kwajalein | Bin 219 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Libya | Bin 431 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/MET | Bin 1103 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/MST | Bin 240 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/MST7MDT | Bin 1042 -> 0 bytes .../tzdata/zoneinfo/Mexico/BajaNorte | Bin 1079 -> 0 bytes .../tzdata/zoneinfo/Mexico/BajaSur | Bin 690 -> 0 bytes .../tzdata/zoneinfo/Mexico/General | Bin 773 -> 0 bytes .../tzdata/zoneinfo/Mexico/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 180 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/NZ | Bin 1043 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/NZ-CHAT | Bin 808 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Navajo | Bin 1042 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/PRC | Bin 393 -> 0 bytes .../Lib/site-packages/tzdata/zoneinfo/PST8PDT | Bin 1294 -> 0 bytes .../tzdata/zoneinfo/Pacific/Apia | Bin 407 -> 0 bytes .../tzdata/zoneinfo/Pacific/Auckland | Bin 1043 -> 0 bytes .../tzdata/zoneinfo/Pacific/Bougainville | Bin 201 -> 0 bytes .../tzdata/zoneinfo/Pacific/Chatham | Bin 808 -> 0 bytes .../tzdata/zoneinfo/Pacific/Chuuk | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Pacific/Easter | Bin 1174 -> 0 bytes .../tzdata/zoneinfo/Pacific/Efate | Bin 342 -> 0 bytes .../tzdata/zoneinfo/Pacific/Enderbury | Bin 172 -> 0 bytes .../tzdata/zoneinfo/Pacific/Fakaofo | Bin 153 -> 0 bytes .../tzdata/zoneinfo/Pacific/Fiji | Bin 396 -> 0 bytes .../tzdata/zoneinfo/Pacific/Funafuti | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Galapagos | Bin 175 -> 0 bytes .../tzdata/zoneinfo/Pacific/Gambier | Bin 132 -> 0 bytes .../tzdata/zoneinfo/Pacific/Guadalcanal | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Guam | Bin 350 -> 0 bytes .../tzdata/zoneinfo/Pacific/Honolulu | Bin 221 -> 0 bytes .../tzdata/zoneinfo/Pacific/Johnston | Bin 221 -> 0 bytes .../tzdata/zoneinfo/Pacific/Kanton | Bin 172 -> 0 bytes .../tzdata/zoneinfo/Pacific/Kiritimati | Bin 174 -> 0 bytes .../tzdata/zoneinfo/Pacific/Kosrae | Bin 242 -> 0 bytes .../tzdata/zoneinfo/Pacific/Kwajalein | Bin 219 -> 0 bytes .../tzdata/zoneinfo/Pacific/Majuro | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Marquesas | Bin 139 -> 0 bytes .../tzdata/zoneinfo/Pacific/Midway | Bin 146 -> 0 bytes .../tzdata/zoneinfo/Pacific/Nauru | Bin 183 -> 0 bytes .../tzdata/zoneinfo/Pacific/Niue | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Pacific/Norfolk | Bin 237 -> 0 bytes .../tzdata/zoneinfo/Pacific/Noumea | Bin 198 -> 0 bytes .../tzdata/zoneinfo/Pacific/Pago_Pago | Bin 146 -> 0 bytes .../tzdata/zoneinfo/Pacific/Palau | Bin 148 -> 0 bytes .../tzdata/zoneinfo/Pacific/Pitcairn | Bin 153 -> 0 bytes .../tzdata/zoneinfo/Pacific/Pohnpei | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Ponape | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Port_Moresby | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Pacific/Rarotonga | Bin 406 -> 0 bytes .../tzdata/zoneinfo/Pacific/Saipan | Bin 350 -> 0 bytes .../tzdata/zoneinfo/Pacific/Samoa | Bin 146 -> 0 bytes .../tzdata/zoneinfo/Pacific/Tahiti | Bin 133 -> 0 bytes .../tzdata/zoneinfo/Pacific/Tarawa | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Tongatapu | Bin 237 -> 0 bytes .../tzdata/zoneinfo/Pacific/Truk | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Pacific/Wake | Bin 134 -> 0 bytes .../tzdata/zoneinfo/Pacific/Wallis | Bin 134 -> 0 bytes .../site-packages/tzdata/zoneinfo/Pacific/Yap | Bin 154 -> 0 bytes .../tzdata/zoneinfo/Pacific/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 181 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Poland | Bin 923 -> 0 bytes .../site-packages/tzdata/zoneinfo/Portugal | Bin 1463 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/ROC | Bin 511 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/ROK | Bin 415 -> 0 bytes .../site-packages/tzdata/zoneinfo/Singapore | Bin 256 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Turkey | Bin 1200 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/UCT | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Alaska | Bin 977 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Aleutian | Bin 969 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Arizona | Bin 240 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Central | Bin 1754 -> 0 bytes .../tzdata/zoneinfo/US/East-Indiana | Bin 531 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Eastern | Bin 1744 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Hawaii | Bin 221 -> 0 bytes .../tzdata/zoneinfo/US/Indiana-Starke | Bin 1016 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Michigan | Bin 899 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Mountain | Bin 1042 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Pacific | Bin 1294 -> 0 bytes .../site-packages/tzdata/zoneinfo/US/Samoa | Bin 146 -> 0 bytes .../tzdata/zoneinfo/US/__init__.py | 0 .../US/__pycache__/__init__.cpython-310.pyc | Bin 176 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/UTC | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/Universal | Bin 111 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/W-SU | Bin 908 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/WET | Bin 1463 -> 0 bytes venv/Lib/site-packages/tzdata/zoneinfo/Zulu | Bin 111 -> 0 bytes .../site-packages/tzdata/zoneinfo/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 173 -> 0 bytes .../site-packages/tzdata/zoneinfo/iso3166.tab | 279 - .../site-packages/tzdata/zoneinfo/leapseconds | 79 - .../site-packages/tzdata/zoneinfo/tzdata.zi | 4300 -------- .../site-packages/tzdata/zoneinfo/zone.tab | 448 - .../tzdata/zoneinfo/zone1970.tab | 375 - .../site-packages/tzdata/zoneinfo/zonenow.tab | 296 - venv/Lib/site-packages/tzdata/zones | 598 -- .../urllib3-2.4.0.dist-info/INSTALLER | 1 - .../urllib3-2.4.0.dist-info/METADATA | 154 - .../urllib3-2.4.0.dist-info/RECORD | 79 - .../urllib3-2.4.0.dist-info/WHEEL | 4 - .../licenses/LICENSE.txt | 21 - venv/Lib/site-packages/urllib3/__init__.py | 211 - .../__pycache__/__init__.cpython-310.pyc | Bin 6100 -> 0 bytes .../_base_connection.cpython-310.pyc | Bin 5673 -> 0 bytes .../__pycache__/_collections.cpython-310.pyc | Bin 16229 -> 0 bytes .../_request_methods.cpython-310.pyc | Bin 9082 -> 0 bytes .../__pycache__/_version.cpython-310.pyc | Bin 541 -> 0 bytes .../__pycache__/connection.cpython-310.pyc | Bin 24298 -> 0 bytes .../connectionpool.cpython-310.pyc | Bin 29205 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 13817 -> 0 bytes .../__pycache__/fields.cpython-310.pyc | Bin 9704 -> 0 bytes .../__pycache__/filepost.cpython-310.pyc | Bin 2338 -> 0 bytes .../__pycache__/poolmanager.cpython-310.pyc | Bin 18196 -> 0 bytes .../__pycache__/response.cpython-310.pyc | Bin 33928 -> 0 bytes .../site-packages/urllib3/_base_connection.py | 165 - .../Lib/site-packages/urllib3/_collections.py | 479 - .../site-packages/urllib3/_request_methods.py | 278 - venv/Lib/site-packages/urllib3/_version.py | 21 - venv/Lib/site-packages/urllib3/connection.py | 1044 -- .../site-packages/urllib3/connectionpool.py | 1178 --- .../site-packages/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 173 -> 0 bytes .../__pycache__/pyopenssl.cpython-310.pyc | Bin 17855 -> 0 bytes .../contrib/__pycache__/socks.cpython-310.pyc | Bin 6134 -> 0 bytes .../urllib3/contrib/emscripten/__init__.py | 16 - .../__pycache__/__init__.cpython-310.pyc | Bin 712 -> 0 bytes .../__pycache__/connection.cpython-310.pyc | Bin 7562 -> 0 bytes .../__pycache__/fetch.cpython-310.pyc | Bin 18649 -> 0 bytes .../__pycache__/request.cpython-310.pyc | Bin 1228 -> 0 bytes .../__pycache__/response.cpython-310.pyc | Bin 8074 -> 0 bytes .../urllib3/contrib/emscripten/connection.py | 255 - .../emscripten/emscripten_fetch_worker.js | 110 - .../urllib3/contrib/emscripten/fetch.py | 708 -- .../urllib3/contrib/emscripten/request.py | 22 - .../urllib3/contrib/emscripten/response.py | 277 - .../urllib3/contrib/pyopenssl.py | 564 -- .../site-packages/urllib3/contrib/socks.py | 228 - venv/Lib/site-packages/urllib3/exceptions.py | 335 - venv/Lib/site-packages/urllib3/fields.py | 341 - venv/Lib/site-packages/urllib3/filepost.py | 89 - .../site-packages/urllib3/http2/__init__.py | 53 - .../__pycache__/__init__.cpython-310.pyc | Bin 1410 -> 0 bytes .../__pycache__/connection.cpython-310.pyc | Bin 10893 -> 0 bytes .../http2/__pycache__/probe.cpython-310.pyc | Bin 2544 -> 0 bytes .../site-packages/urllib3/http2/connection.py | 356 - venv/Lib/site-packages/urllib3/http2/probe.py | 87 - venv/Lib/site-packages/urllib3/poolmanager.py | 637 -- venv/Lib/site-packages/urllib3/py.typed | 2 - venv/Lib/site-packages/urllib3/response.py | 1278 --- .../site-packages/urllib3/util/__init__.py | 42 - .../util/__pycache__/__init__.cpython-310.pyc | Bin 953 -> 0 bytes .../__pycache__/connection.cpython-310.pyc | Bin 3468 -> 0 bytes .../util/__pycache__/proxy.cpython-310.pyc | Bin 1085 -> 0 bytes .../util/__pycache__/request.cpython-310.pyc | Bin 6349 -> 0 bytes .../util/__pycache__/response.cpython-310.pyc | Bin 2339 -> 0 bytes .../util/__pycache__/retry.cpython-310.pyc | Bin 15752 -> 0 bytes .../util/__pycache__/ssl_.cpython-310.pyc | Bin 12817 -> 0 bytes .../ssl_match_hostname.cpython-310.pyc | Bin 3708 -> 0 bytes .../__pycache__/ssltransport.cpython-310.pyc | Bin 9422 -> 0 bytes .../util/__pycache__/timeout.cpython-310.pyc | Bin 9612 -> 0 bytes .../util/__pycache__/url.cpython-310.pyc | Bin 11248 -> 0 bytes .../util/__pycache__/util.cpython-310.pyc | Bin 1213 -> 0 bytes .../util/__pycache__/wait.cpython-310.pyc | Bin 2392 -> 0 bytes .../site-packages/urllib3/util/connection.py | 137 - venv/Lib/site-packages/urllib3/util/proxy.py | 43 - .../Lib/site-packages/urllib3/util/request.py | 258 - .../site-packages/urllib3/util/response.py | 101 - venv/Lib/site-packages/urllib3/util/retry.py | 533 - venv/Lib/site-packages/urllib3/util/ssl_.py | 524 - .../urllib3/util/ssl_match_hostname.py | 159 - .../urllib3/util/ssltransport.py | 271 - .../Lib/site-packages/urllib3/util/timeout.py | 275 - venv/Lib/site-packages/urllib3/util/url.py | 469 - venv/Lib/site-packages/urllib3/util/util.py | 42 - venv/Lib/site-packages/urllib3/util/wait.py | 124 - .../werkzeug-3.1.3.dist-info/INSTALLER | 1 - .../werkzeug-3.1.3.dist-info/LICENSE.txt | 28 - .../werkzeug-3.1.3.dist-info/METADATA | 99 - .../werkzeug-3.1.3.dist-info/RECORD | 116 - .../werkzeug-3.1.3.dist-info/WHEEL | 4 - venv/Lib/site-packages/werkzeug/__init__.py | 4 - .../__pycache__/__init__.cpython-310.pyc | Bin 314 -> 0 bytes .../__pycache__/_internal.cpython-310.pyc | Bin 7044 -> 0 bytes .../__pycache__/_reloader.cpython-310.pyc | Bin 12902 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 27668 -> 0 bytes .../__pycache__/formparser.cpython-310.pyc | Bin 12810 -> 0 bytes .../werkzeug/__pycache__/http.cpython-310.pyc | Bin 39399 -> 0 bytes .../__pycache__/local.cpython-310.pyc | Bin 21031 -> 0 bytes .../__pycache__/security.cpython-310.pyc | Bin 5500 -> 0 bytes .../__pycache__/serving.cpython-310.pyc | Bin 30650 -> 0 bytes .../werkzeug/__pycache__/test.cpython-310.pyc | Bin 43001 -> 0 bytes .../__pycache__/testapp.cpython-310.pyc | Bin 6595 -> 0 bytes .../werkzeug/__pycache__/urls.cpython-310.pyc | Bin 5814 -> 0 bytes .../__pycache__/user_agent.cpython-310.pyc | Bin 1852 -> 0 bytes .../__pycache__/utils.cpython-310.pyc | Bin 22305 -> 0 bytes .../werkzeug/__pycache__/wsgi.cpython-310.pyc | Bin 19944 -> 0 bytes venv/Lib/site-packages/werkzeug/_internal.py | 211 - venv/Lib/site-packages/werkzeug/_reloader.py | 471 - .../werkzeug/datastructures/__init__.py | 64 - .../__pycache__/__init__.cpython-310.pyc | Bin 2220 -> 0 bytes .../__pycache__/accept.cpython-310.pyc | Bin 12491 -> 0 bytes .../__pycache__/auth.cpython-310.pyc | Bin 10500 -> 0 bytes .../__pycache__/cache_control.cpython-310.pyc | Bin 10274 -> 0 bytes .../__pycache__/csp.cpython-310.pyc | Bin 4920 -> 0 bytes .../__pycache__/etag.cpython-310.pyc | Bin 4253 -> 0 bytes .../__pycache__/file_storage.cpython-310.pyc | Bin 6783 -> 0 bytes .../__pycache__/headers.cpython-310.pyc | Bin 23354 -> 0 bytes .../__pycache__/mixins.cpython-310.pyc | Bin 13218 -> 0 bytes .../__pycache__/range.cpython-310.pyc | Bin 7514 -> 0 bytes .../__pycache__/structures.cpython-310.pyc | Bin 44451 -> 0 bytes .../werkzeug/datastructures/accept.py | 350 - .../werkzeug/datastructures/auth.py | 317 - .../werkzeug/datastructures/cache_control.py | 273 - .../werkzeug/datastructures/csp.py | 100 - .../werkzeug/datastructures/etag.py | 106 - .../werkzeug/datastructures/file_storage.py | 209 - .../werkzeug/datastructures/headers.py | 662 -- .../werkzeug/datastructures/mixins.py | 317 - .../werkzeug/datastructures/range.py | 214 - .../werkzeug/datastructures/structures.py | 1239 --- .../site-packages/werkzeug/debug/__init__.py | 565 -- .../__pycache__/__init__.cpython-310.pyc | Bin 15002 -> 0 bytes .../debug/__pycache__/console.cpython-310.pyc | Bin 8338 -> 0 bytes .../debug/__pycache__/repr.cpython-310.pyc | Bin 9033 -> 0 bytes .../debug/__pycache__/tbtools.cpython-310.pyc | Bin 11934 -> 0 bytes .../site-packages/werkzeug/debug/console.py | 219 - venv/Lib/site-packages/werkzeug/debug/repr.py | 282 - .../werkzeug/debug/shared/ICON_LICENSE.md | 6 - .../werkzeug/debug/shared/console.png | Bin 507 -> 0 bytes .../werkzeug/debug/shared/debugger.js | 344 - .../werkzeug/debug/shared/less.png | Bin 191 -> 0 bytes .../werkzeug/debug/shared/more.png | Bin 200 -> 0 bytes .../werkzeug/debug/shared/style.css | 150 - .../site-packages/werkzeug/debug/tbtools.py | 450 - venv/Lib/site-packages/werkzeug/exceptions.py | 894 -- venv/Lib/site-packages/werkzeug/formparser.py | 430 - venv/Lib/site-packages/werkzeug/http.py | 1405 --- venv/Lib/site-packages/werkzeug/local.py | 653 -- .../werkzeug/middleware/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 177 -> 0 bytes .../__pycache__/dispatcher.cpython-310.pyc | Bin 2826 -> 0 bytes .../__pycache__/http_proxy.cpython-310.pyc | Bin 6921 -> 0 bytes .../__pycache__/lint.cpython-310.pyc | Bin 13070 -> 0 bytes .../__pycache__/profiler.cpython-310.pyc | Bin 5618 -> 0 bytes .../__pycache__/proxy_fix.cpython-310.pyc | Bin 6019 -> 0 bytes .../__pycache__/shared_data.cpython-310.pyc | Bin 9333 -> 0 bytes .../werkzeug/middleware/dispatcher.py | 81 - .../werkzeug/middleware/http_proxy.py | 236 - .../site-packages/werkzeug/middleware/lint.py | 439 - .../werkzeug/middleware/profiler.py | 155 - .../werkzeug/middleware/proxy_fix.py | 183 - .../werkzeug/middleware/shared_data.py | 283 - venv/Lib/site-packages/werkzeug/py.typed | 0 .../werkzeug/routing/__init__.py | 134 - .../__pycache__/__init__.cpython-310.pyc | Bin 4615 -> 0 bytes .../__pycache__/converters.cpython-310.pyc | Bin 9200 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 5667 -> 0 bytes .../routing/__pycache__/map.cpython-310.pyc | Bin 31250 -> 0 bytes .../__pycache__/matcher.cpython-310.pyc | Bin 5147 -> 0 bytes .../routing/__pycache__/rules.cpython-310.pyc | Bin 28072 -> 0 bytes .../werkzeug/routing/converters.py | 261 - .../werkzeug/routing/exceptions.py | 152 - .../Lib/site-packages/werkzeug/routing/map.py | 951 -- .../site-packages/werkzeug/routing/matcher.py | 202 - .../site-packages/werkzeug/routing/rules.py | 928 -- .../site-packages/werkzeug/sansio/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 173 -> 0 bytes .../sansio/__pycache__/http.cpython-310.pyc | Bin 4157 -> 0 bytes .../__pycache__/multipart.cpython-310.pyc | Bin 7487 -> 0 bytes .../__pycache__/request.cpython-310.pyc | Bin 17305 -> 0 bytes .../__pycache__/response.cpython-310.pyc | Bin 24862 -> 0 bytes .../sansio/__pycache__/utils.cpython-310.pyc | Bin 4746 -> 0 bytes .../Lib/site-packages/werkzeug/sansio/http.py | 170 - .../werkzeug/sansio/multipart.py | 323 - .../site-packages/werkzeug/sansio/request.py | 534 - .../site-packages/werkzeug/sansio/response.py | 763 -- .../site-packages/werkzeug/sansio/utils.py | 167 - venv/Lib/site-packages/werkzeug/security.py | 166 - venv/Lib/site-packages/werkzeug/serving.py | 1125 --- venv/Lib/site-packages/werkzeug/test.py | 1464 --- venv/Lib/site-packages/werkzeug/testapp.py | 194 - venv/Lib/site-packages/werkzeug/urls.py | 203 - venv/Lib/site-packages/werkzeug/user_agent.py | 47 - venv/Lib/site-packages/werkzeug/utils.py | 691 -- .../werkzeug/wrappers/__init__.py | 3 - .../__pycache__/__init__.cpython-310.pyc | Bin 292 -> 0 bytes .../__pycache__/request.cpython-310.pyc | Bin 21772 -> 0 bytes .../__pycache__/response.cpython-310.pyc | Bin 28350 -> 0 bytes .../werkzeug/wrappers/request.py | 650 -- .../werkzeug/wrappers/response.py | 831 -- venv/Lib/site-packages/werkzeug/wsgi.py | 595 -- .../zope.interface-7.2-py3.10-nspkg.pth | 1 - .../zope.interface-7.2.dist-info/INSTALLER | 1 - .../zope.interface-7.2.dist-info/LICENSE.txt | 44 - .../zope.interface-7.2.dist-info/METADATA | 1224 --- .../zope.interface-7.2.dist-info/RECORD | 110 - .../zope.interface-7.2.dist-info/WHEEL | 5 - .../namespace_packages.txt | 1 - .../top_level.txt | 1 - .../site-packages/zope/interface/__init__.py | 90 - .../__pycache__/__init__.cpython-310.pyc | Bin 2565 -> 0 bytes .../__pycache__/_compat.cpython-310.pyc | Bin 3802 -> 0 bytes .../__pycache__/_flatten.cpython-310.pyc | Bin 586 -> 0 bytes .../__pycache__/adapter.cpython-310.pyc | Bin 26112 -> 0 bytes .../__pycache__/advice.cpython-310.pyc | Bin 2622 -> 0 bytes .../__pycache__/declarations.cpython-310.pyc | Bin 27926 -> 0 bytes .../__pycache__/document.cpython-310.pyc | Bin 3189 -> 0 bytes .../__pycache__/exceptions.cpython-310.pyc | Bin 7069 -> 0 bytes .../__pycache__/interface.cpython-310.pyc | Bin 25369 -> 0 bytes .../__pycache__/interfaces.cpython-310.pyc | Bin 56203 -> 0 bytes .../__pycache__/registry.cpython-310.pyc | Bin 22261 -> 0 bytes .../interface/__pycache__/ro.cpython-310.pyc | Bin 19658 -> 0 bytes .../__pycache__/verify.cpython-310.pyc | Bin 3988 -> 0 bytes .../site-packages/zope/interface/_compat.py | 139 - .../site-packages/zope/interface/_flatten.py | 36 - .../_zope_interface_coptimizations.c | 2669 ----- ...terface_coptimizations.cp310-win_amd64.pyd | Bin 33280 -> 0 bytes .../site-packages/zope/interface/adapter.py | 1048 -- .../site-packages/zope/interface/advice.py | 121 - .../zope/interface/common/__init__.py | 291 - .../__pycache__/__init__.cpython-310.pyc | Bin 8780 -> 0 bytes .../__pycache__/builtins.cpython-310.pyc | Bin 3290 -> 0 bytes .../__pycache__/collections.cpython-310.pyc | Bin 7196 -> 0 bytes .../__pycache__/idatetime.cpython-310.pyc | Bin 24447 -> 0 bytes .../__pycache__/interfaces.cpython-310.pyc | Bin 7011 -> 0 bytes .../common/__pycache__/io.cpython-310.pyc | Bin 1151 -> 0 bytes .../__pycache__/mapping.cpython-310.pyc | Bin 6313 -> 0 bytes .../__pycache__/numbers.cpython-310.pyc | Bin 1649 -> 0 bytes .../__pycache__/sequence.cpython-310.pyc | Bin 7751 -> 0 bytes .../zope/interface/common/builtins.py | 124 - .../zope/interface/common/collections.py | 269 - .../zope/interface/common/idatetime.py | 622 -- .../zope/interface/common/interfaces.py | 281 - .../site-packages/zope/interface/common/io.py | 44 - .../zope/interface/common/mapping.py | 177 - .../zope/interface/common/numbers.py | 65 - .../zope/interface/common/sequence.py | 195 - .../zope/interface/common/tests/__init__.py | 146 - .../__pycache__/__init__.cpython-310.pyc | Bin 3896 -> 0 bytes .../__pycache__/basemapping.cpython-310.pyc | Bin 3330 -> 0 bytes .../__pycache__/test_builtins.cpython-310.pyc | Bin 1228 -> 0 bytes .../test_collections.cpython-310.pyc | Bin 4977 -> 0 bytes .../test_idatetime.cpython-310.pyc | Bin 1423 -> 0 bytes .../test_import_interfaces.cpython-310.pyc | Bin 659 -> 0 bytes .../tests/__pycache__/test_io.cpython-310.pyc | Bin 1625 -> 0 bytes .../__pycache__/test_numbers.cpython-310.pyc | Bin 1175 -> 0 bytes .../interface/common/tests/basemapping.py | 115 - .../interface/common/tests/test_builtins.py | 50 - .../common/tests/test_collections.py | 147 - .../interface/common/tests/test_idatetime.py | 48 - .../common/tests/test_import_interfaces.py | 21 - .../zope/interface/common/tests/test_io.py | 46 - .../interface/common/tests/test_numbers.py | 42 - .../zope/interface/declarations.py | 1219 --- .../site-packages/zope/interface/document.py | 133 - .../zope/interface/exceptions.py | 278 - .../site-packages/zope/interface/interface.py | 1185 --- .../zope/interface/interfaces.py | 1516 --- .../site-packages/zope/interface/registry.py | 750 -- venv/Lib/site-packages/zope/interface/ro.py | 722 -- .../zope/interface/tests/__init__.py | 130 - .../__pycache__/__init__.cpython-310.pyc | Bin 4361 -> 0 bytes .../advisory_testing.cpython-310.pyc | Bin 592 -> 0 bytes .../tests/__pycache__/dummy.cpython-310.pyc | Bin 453 -> 0 bytes .../tests/__pycache__/idummy.cpython-310.pyc | Bin 657 -> 0 bytes .../tests/__pycache__/m1.cpython-310.pyc | Bin 582 -> 0 bytes .../tests/__pycache__/odd.cpython-310.pyc | Bin 3318 -> 0 bytes .../__pycache__/test_adapter.cpython-310.pyc | Bin 72431 -> 0 bytes .../__pycache__/test_advice.cpython-310.pyc | Bin 9634 -> 0 bytes .../test_compile_flags.cpython-310.pyc | Bin 782 -> 0 bytes .../test_declarations.cpython-310.pyc | Bin 102276 -> 0 bytes .../__pycache__/test_document.cpython-310.pyc | Bin 19539 -> 0 bytes .../__pycache__/test_element.cpython-310.pyc | Bin 850 -> 0 bytes .../test_exceptions.cpython-310.pyc | Bin 6840 -> 0 bytes .../test_interface.cpython-310.pyc | Bin 111398 -> 0 bytes .../test_interfaces.cpython-310.pyc | Bin 6020 -> 0 bytes .../test_odd_declarations.cpython-310.pyc | Bin 9300 -> 0 bytes .../__pycache__/test_registry.cpython-310.pyc | Bin 116229 -> 0 bytes .../tests/__pycache__/test_ro.cpython-310.pyc | Bin 18321 -> 0 bytes .../__pycache__/test_sorting.cpython-310.pyc | Bin 2416 -> 0 bytes .../__pycache__/test_verify.cpython-310.pyc | Bin 30344 -> 0 bytes .../zope/interface/tests/advisory_testing.py | 29 - .../zope/interface/tests/dummy.py | 25 - .../zope/interface/tests/idummy.py | 24 - .../site-packages/zope/interface/tests/m1.py | 28 - .../site-packages/zope/interface/tests/odd.py | 130 - .../zope/interface/tests/test_adapter.py | 2315 ----- .../zope/interface/tests/test_advice.py | 217 - .../interface/tests/test_compile_flags.py | 29 - .../zope/interface/tests/test_declarations.py | 2685 ----- .../zope/interface/tests/test_document.py | 547 -- .../zope/interface/tests/test_element.py | 33 - .../zope/interface/tests/test_exceptions.py | 190 - .../zope/interface/tests/test_interface.py | 2871 ------ .../zope/interface/tests/test_interfaces.py | 130 - .../interface/tests/test_odd_declarations.py | 301 - .../zope/interface/tests/test_registry.py | 3391 ------- .../zope/interface/tests/test_ro.py | 487 - .../zope/interface/tests/test_sorting.py | 83 - .../zope/interface/tests/test_verify.py | 656 -- .../site-packages/zope/interface/verify.py | 209 - venv/Scripts/Activate.ps1 | 473 - venv/Scripts/activate | 69 - venv/Scripts/activate.bat | 34 - venv/Scripts/deactivate.bat | 22 - venv/Scripts/docutils.exe | Bin 107895 -> 0 bytes venv/Scripts/dotenv.exe | Bin 107891 -> 0 bytes venv/Scripts/flask.exe | Bin 107887 -> 0 bytes venv/Scripts/gunicorn.exe | Bin 107896 -> 0 bytes venv/Scripts/normalizer.exe | Bin 107905 -> 0 bytes venv/Scripts/pip.exe | Bin 107900 -> 0 bytes venv/Scripts/pip3.10.exe | Bin 107900 -> 0 bytes venv/Scripts/pip3.exe | Bin 107900 -> 0 bytes venv/Scripts/python.exe | Bin 266664 -> 0 bytes venv/Scripts/pythonw.exe | Bin 254888 -> 0 bytes venv/Scripts/rst2html.exe | Bin 107899 -> 0 bytes venv/Scripts/rst2html4.exe | Bin 107901 -> 0 bytes venv/Scripts/rst2html5.exe | Bin 107901 -> 0 bytes venv/Scripts/rst2latex.exe | Bin 107901 -> 0 bytes venv/Scripts/rst2man.exe | Bin 107897 -> 0 bytes venv/Scripts/rst2odt.exe | Bin 107897 -> 0 bytes venv/Scripts/rst2pseudoxml.exe | Bin 107909 -> 0 bytes venv/Scripts/rst2s5.exe | Bin 107895 -> 0 bytes venv/Scripts/rst2xetex.exe | Bin 107901 -> 0 bytes venv/Scripts/rst2xml.exe | Bin 107897 -> 0 bytes venv/pyvenv.cfg | 3 - 4560 files changed, 600603 deletions(-) delete mode 100644 .env delete mode 100644 API_calls/__pycache__/StudentDatafromLDRESTAPI.cpython-310.pyc delete mode 100644 API_calls/__pycache__/__init__.cpython-310.pyc delete mode 100644 API_calls/__pycache__/load_config_file.cpython-310.pyc delete mode 100644 API_calls/__pycache__/logger_setup.cpython-310.pyc delete mode 100644 API_calls/__pycache__/quality_model_config.cpython-310.pyc delete mode 100644 API_calls/__pycache__/quality_model_loader.cpython-310.pyc delete mode 100644 __pycache__/app.cpython-310.pyc delete mode 100644 __pycache__/app.cpython-311.pyc delete mode 100644 __pycache__/ld_refresh.cpython-310.pyc delete mode 100644 config/__pycache__/__init__.cpython-310.pyc delete mode 100644 config/__pycache__/load_config_file.cpython-310.pyc delete mode 100644 config/__pycache__/logger_config.cpython-310.pyc delete mode 100644 config/__pycache__/quality_model_config.cpython-310.pyc delete mode 100644 config/__pycache__/settings.cpython-310.pyc delete mode 100644 config_files/__pycache__/config_variables.cpython-310.pyc delete mode 100644 database/__pycache__/__init__.cpython-310.pyc delete mode 100644 database/__pycache__/mongo_client.cpython-310.pyc delete mode 100644 database/__pycache__/quality_model_loader.cpython-310.pyc delete mode 100644 logic/factors_logic/__pycache__/factor_event_mapping.cpython-310.pyc delete mode 100644 logic/factors_logic/__pycache__/factor_recalculation.cpython-310.pyc delete mode 100644 logic/factors_logic/__pycache__/store_factors_mongo.cpython-310.pyc delete mode 100644 logic/indicators_logic/__pycache__/indicator_event_mapping.cpython-310.pyc delete mode 100644 logic/indicators_logic/__pycache__/indicator_recalculation.cpython-310.pyc delete mode 100644 logic/indicators_logic/__pycache__/store_indicator_mongo.cpython-310.pyc delete mode 100644 logic/metrics_logic/__pycache__/metric_event_mapping.cpython-310.pyc delete mode 100644 logic/metrics_logic/__pycache__/metric_event_mapping.cpython-311.pyc delete mode 100644 logic/metrics_logic/__pycache__/metric_placeholder.cpython-310.pyc delete mode 100644 logic/metrics_logic/__pycache__/metric_placeholder.cpython-311.pyc delete mode 100644 logic/metrics_logic/__pycache__/metric_recalculation.cpython-310.pyc delete mode 100644 logic/metrics_logic/__pycache__/metric_recalculation.cpython-311.pyc delete mode 100644 logic/metrics_logic/__pycache__/metricsrelation.cpython-310.pyc delete mode 100644 logic/metrics_logic/__pycache__/run_mogo_query.cpython-310.pyc delete mode 100644 logic/metrics_logic/__pycache__/store_metric_mongo.cpython-310.pyc delete mode 100644 utils/__pycache__/__init__.cpython-310.pyc delete mode 100644 utils/__pycache__/evaluation_test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/DateTime-5.5.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/DateTime/DateTime.py delete mode 100644 venv/Lib/site-packages/DateTime/DateTime.txt delete mode 100644 venv/Lib/site-packages/DateTime/__init__.py delete mode 100644 venv/Lib/site-packages/DateTime/__pycache__/DateTime.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime/__pycache__/interfaces.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime/__pycache__/pytz_support.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime/interfaces.py delete mode 100644 venv/Lib/site-packages/DateTime/pytz.txt delete mode 100644 venv/Lib/site-packages/DateTime/pytz_support.py delete mode 100644 venv/Lib/site-packages/DateTime/tests/__init__.py delete mode 100644 venv/Lib/site-packages/DateTime/tests/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime/tests/__pycache__/test_datetime.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/DateTime/tests/julian_testdata.txt delete mode 100644 venv/Lib/site-packages/DateTime/tests/test_datetime.py delete mode 100644 venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/__pycache__/pathlib.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/_distutils_hack/__init__.py delete mode 100644 venv/Lib/site-packages/_distutils_hack/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/_distutils_hack/override.py delete mode 100644 venv/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/blinker-1.9.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/blinker/__init__.py delete mode 100644 venv/Lib/site-packages/blinker/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/blinker/__pycache__/_utilities.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/blinker/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/blinker/_utilities.py delete mode 100644 venv/Lib/site-packages/blinker/base.py delete mode 100644 venv/Lib/site-packages/blinker/py.typed delete mode 100644 venv/Lib/site-packages/bson/__init__.py delete mode 100644 venv/Lib/site-packages/bson/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/_helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/binary.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/code.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/codec_options.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/datetime_ms.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/dbref.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/decimal128.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/int64.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/json_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/max_key.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/min_key.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/objectid.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/raw_bson.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/regex.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/son.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/timestamp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/typings.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/__pycache__/tz_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/bson/_cbson.cp310-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/bson/_cbson.cp39-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/bson/_cbsonmodule.c delete mode 100644 venv/Lib/site-packages/bson/_cbsonmodule.h delete mode 100644 venv/Lib/site-packages/bson/_helpers.py delete mode 100644 venv/Lib/site-packages/bson/binary.py delete mode 100644 venv/Lib/site-packages/bson/bson-endian.h delete mode 100644 venv/Lib/site-packages/bson/buffer.c delete mode 100644 venv/Lib/site-packages/bson/buffer.h delete mode 100644 venv/Lib/site-packages/bson/code.py delete mode 100644 venv/Lib/site-packages/bson/codec_options.py delete mode 100644 venv/Lib/site-packages/bson/datetime_ms.py delete mode 100644 venv/Lib/site-packages/bson/dbref.py delete mode 100644 venv/Lib/site-packages/bson/decimal128.py delete mode 100644 venv/Lib/site-packages/bson/errors.py delete mode 100644 venv/Lib/site-packages/bson/int64.py delete mode 100644 venv/Lib/site-packages/bson/json_util.py delete mode 100644 venv/Lib/site-packages/bson/max_key.py delete mode 100644 venv/Lib/site-packages/bson/min_key.py delete mode 100644 venv/Lib/site-packages/bson/objectid.py delete mode 100644 venv/Lib/site-packages/bson/py.typed delete mode 100644 venv/Lib/site-packages/bson/raw_bson.py delete mode 100644 venv/Lib/site-packages/bson/regex.py delete mode 100644 venv/Lib/site-packages/bson/son.py delete mode 100644 venv/Lib/site-packages/bson/time64.c delete mode 100644 venv/Lib/site-packages/bson/time64.h delete mode 100644 venv/Lib/site-packages/bson/time64_config.h delete mode 100644 venv/Lib/site-packages/bson/time64_limits.h delete mode 100644 venv/Lib/site-packages/bson/timestamp.py delete mode 100644 venv/Lib/site-packages/bson/typings.py delete mode 100644 venv/Lib/site-packages/bson/tz_util.py delete mode 100644 venv/Lib/site-packages/certifi-2025.4.26.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/certifi-2025.4.26.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/certifi-2025.4.26.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/certifi-2025.4.26.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/certifi-2025.4.26.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/certifi-2025.4.26.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/certifi/__init__.py delete mode 100644 venv/Lib/site-packages/certifi/__main__.py delete mode 100644 venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/certifi/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/certifi/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/certifi/cacert.pem delete mode 100644 venv/Lib/site-packages/certifi/core.py delete mode 100644 venv/Lib/site-packages/certifi/py.typed delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/charset_normalizer/__init__.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/__main__.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/api.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/api.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/cd.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/cli/__init__.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/cli/__main__.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/charset_normalizer/constant.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/legacy.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/md.cp310-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/charset_normalizer/md.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/md__mypyc.cp310-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/charset_normalizer/models.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/py.typed delete mode 100644 venv/Lib/site-packages/charset_normalizer/utils.py delete mode 100644 venv/Lib/site-packages/charset_normalizer/version.py delete mode 100644 venv/Lib/site-packages/click-8.1.8.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/click-8.1.8.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/click-8.1.8.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/click-8.1.8.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/click/__init__.py delete mode 100644 venv/Lib/site-packages/click/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/_textwrap.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/decorators.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/formatting.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/globals.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/shell_completion.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/termui.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/types.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/click/_compat.py delete mode 100644 venv/Lib/site-packages/click/_termui_impl.py delete mode 100644 venv/Lib/site-packages/click/_textwrap.py delete mode 100644 venv/Lib/site-packages/click/_winconsole.py delete mode 100644 venv/Lib/site-packages/click/core.py delete mode 100644 venv/Lib/site-packages/click/decorators.py delete mode 100644 venv/Lib/site-packages/click/exceptions.py delete mode 100644 venv/Lib/site-packages/click/formatting.py delete mode 100644 venv/Lib/site-packages/click/globals.py delete mode 100644 venv/Lib/site-packages/click/parser.py delete mode 100644 venv/Lib/site-packages/click/py.typed delete mode 100644 venv/Lib/site-packages/click/shell_completion.py delete mode 100644 venv/Lib/site-packages/click/termui.py delete mode 100644 venv/Lib/site-packages/click/testing.py delete mode 100644 venv/Lib/site-packages/click/types.py delete mode 100644 venv/Lib/site-packages/click/utils.py delete mode 100644 venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt delete mode 100644 venv/Lib/site-packages/colorama/__init__.py delete mode 100644 venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/__pycache__/initialise.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/__pycache__/win32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/__pycache__/winterm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/ansi.py delete mode 100644 venv/Lib/site-packages/colorama/ansitowin32.py delete mode 100644 venv/Lib/site-packages/colorama/initialise.py delete mode 100644 venv/Lib/site-packages/colorama/tests/__init__.py delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/initialise_test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/colorama/tests/ansi_test.py delete mode 100644 venv/Lib/site-packages/colorama/tests/ansitowin32_test.py delete mode 100644 venv/Lib/site-packages/colorama/tests/initialise_test.py delete mode 100644 venv/Lib/site-packages/colorama/tests/isatty_test.py delete mode 100644 venv/Lib/site-packages/colorama/tests/utils.py delete mode 100644 venv/Lib/site-packages/colorama/tests/winterm_test.py delete mode 100644 venv/Lib/site-packages/colorama/win32.py delete mode 100644 venv/Lib/site-packages/colorama/winterm.py delete mode 100644 venv/Lib/site-packages/distutils-precedence.pth delete mode 100644 venv/Lib/site-packages/dns/__init__.py delete mode 100644 venv/Lib/site-packages/dns/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/_asyncbackend.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/_asyncio_backend.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/_ddr.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/_features.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/_immutable_ctx.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/_trio_backend.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/asyncbackend.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/asyncquery.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/asyncresolver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/dnssec.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/dnssectypes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/e164.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/edns.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/entropy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/enum.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/exception.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/flags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/grange.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/immutable.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/inet.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/ipv4.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/ipv6.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/message.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/name.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/namedict.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/nameserver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/node.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/opcode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/query.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/rcode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/rdata.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/rdataclass.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/rdataset.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/rdatatype.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/renderer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/resolver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/reversename.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/rrset.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/serial.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/set.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/tokenizer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/transaction.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/tsig.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/tsigkeyring.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/ttl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/update.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/versioned.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/win32util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/wire.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/xfr.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/zone.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/zonefile.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/__pycache__/zonetypes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/_asyncbackend.py delete mode 100644 venv/Lib/site-packages/dns/_asyncio_backend.py delete mode 100644 venv/Lib/site-packages/dns/_ddr.py delete mode 100644 venv/Lib/site-packages/dns/_features.py delete mode 100644 venv/Lib/site-packages/dns/_immutable_ctx.py delete mode 100644 venv/Lib/site-packages/dns/_trio_backend.py delete mode 100644 venv/Lib/site-packages/dns/asyncbackend.py delete mode 100644 venv/Lib/site-packages/dns/asyncquery.py delete mode 100644 venv/Lib/site-packages/dns/asyncresolver.py delete mode 100644 venv/Lib/site-packages/dns/dnssec.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__init__.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/cryptography.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/dsa.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/ecdsa.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/eddsa.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/__pycache__/rsa.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/base.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/cryptography.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/dsa.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/ecdsa.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/eddsa.py delete mode 100644 venv/Lib/site-packages/dns/dnssecalgs/rsa.py delete mode 100644 venv/Lib/site-packages/dns/dnssectypes.py delete mode 100644 venv/Lib/site-packages/dns/e164.py delete mode 100644 venv/Lib/site-packages/dns/edns.py delete mode 100644 venv/Lib/site-packages/dns/entropy.py delete mode 100644 venv/Lib/site-packages/dns/enum.py delete mode 100644 venv/Lib/site-packages/dns/exception.py delete mode 100644 venv/Lib/site-packages/dns/flags.py delete mode 100644 venv/Lib/site-packages/dns/grange.py delete mode 100644 venv/Lib/site-packages/dns/immutable.py delete mode 100644 venv/Lib/site-packages/dns/inet.py delete mode 100644 venv/Lib/site-packages/dns/ipv4.py delete mode 100644 venv/Lib/site-packages/dns/ipv6.py delete mode 100644 venv/Lib/site-packages/dns/message.py delete mode 100644 venv/Lib/site-packages/dns/name.py delete mode 100644 venv/Lib/site-packages/dns/namedict.py delete mode 100644 venv/Lib/site-packages/dns/nameserver.py delete mode 100644 venv/Lib/site-packages/dns/node.py delete mode 100644 venv/Lib/site-packages/dns/opcode.py delete mode 100644 venv/Lib/site-packages/dns/py.typed delete mode 100644 venv/Lib/site-packages/dns/query.py delete mode 100644 venv/Lib/site-packages/dns/quic/__init__.py delete mode 100644 venv/Lib/site-packages/dns/quic/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/quic/__pycache__/_asyncio.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/quic/__pycache__/_common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/quic/__pycache__/_sync.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/quic/__pycache__/_trio.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/quic/_asyncio.py delete mode 100644 venv/Lib/site-packages/dns/quic/_common.py delete mode 100644 venv/Lib/site-packages/dns/quic/_sync.py delete mode 100644 venv/Lib/site-packages/dns/quic/_trio.py delete mode 100644 venv/Lib/site-packages/dns/rcode.py delete mode 100644 venv/Lib/site-packages/dns/rdata.py delete mode 100644 venv/Lib/site-packages/dns/rdataclass.py delete mode 100644 venv/Lib/site-packages/dns/rdataset.py delete mode 100644 venv/Lib/site-packages/dns/rdatatype.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/AFSDB.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/AMTRELAY.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/AVC.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/CAA.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/CDNSKEY.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/CDS.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/CERT.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/CNAME.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/CSYNC.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/DLV.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/DNAME.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/DNSKEY.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/DS.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/EUI48.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/EUI64.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/GPOS.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/HINFO.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/HIP.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/ISDN.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/L32.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/L64.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/LOC.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/LP.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/MX.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/NID.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/NINFO.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/NS.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/NSEC.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3PARAM.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/OPENPGPKEY.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/OPT.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/PTR.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/RESINFO.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/RP.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/RRSIG.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/RT.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/SMIMEA.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/SOA.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/SPF.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/SSHFP.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/TKEY.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/TLSA.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/TSIG.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/TXT.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/URI.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/WALLET.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/X25.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/ZONEMD.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__init__.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AFSDB.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AMTRELAY.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AVC.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CAA.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CDNSKEY.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CDS.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CERT.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CNAME.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CSYNC.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/DLV.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/DNAME.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/DNSKEY.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/DS.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/EUI48.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/EUI64.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/GPOS.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/HINFO.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/HIP.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/ISDN.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/L32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/L64.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/LOC.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/LP.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/MX.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NID.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NINFO.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NS.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC3.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC3PARAM.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/OPENPGPKEY.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/OPT.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/PTR.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RESINFO.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RP.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RRSIG.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RT.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SMIMEA.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SOA.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SPF.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SSHFP.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TKEY.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TLSA.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TSIG.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TXT.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/URI.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/WALLET.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/X25.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/ZONEMD.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/CH/A.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/CH/__init__.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/CH/__pycache__/A.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/CH/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/A.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/AAAA.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/APL.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/DHCID.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/HTTPS.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/IPSECKEY.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/KX.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/NAPTR.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/NSAP.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/NSAP_PTR.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/PX.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/SRV.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/SVCB.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/WKS.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__init__.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/A.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/AAAA.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/APL.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/DHCID.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/HTTPS.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/IPSECKEY.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/KX.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NAPTR.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NSAP.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NSAP_PTR.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/PX.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/SRV.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/SVCB.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/WKS.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__init__.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/dnskeybase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/dsbase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/euibase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/mxbase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/nsbase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/svcbbase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/tlsabase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/txtbase.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dns/rdtypes/dnskeybase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/dsbase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/euibase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/mxbase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/nsbase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/svcbbase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/tlsabase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/txtbase.py delete mode 100644 venv/Lib/site-packages/dns/rdtypes/util.py delete mode 100644 venv/Lib/site-packages/dns/renderer.py delete mode 100644 venv/Lib/site-packages/dns/resolver.py delete mode 100644 venv/Lib/site-packages/dns/reversename.py delete mode 100644 venv/Lib/site-packages/dns/rrset.py delete mode 100644 venv/Lib/site-packages/dns/serial.py delete mode 100644 venv/Lib/site-packages/dns/set.py delete mode 100644 venv/Lib/site-packages/dns/tokenizer.py delete mode 100644 venv/Lib/site-packages/dns/transaction.py delete mode 100644 venv/Lib/site-packages/dns/tsig.py delete mode 100644 venv/Lib/site-packages/dns/tsigkeyring.py delete mode 100644 venv/Lib/site-packages/dns/ttl.py delete mode 100644 venv/Lib/site-packages/dns/update.py delete mode 100644 venv/Lib/site-packages/dns/version.py delete mode 100644 venv/Lib/site-packages/dns/versioned.py delete mode 100644 venv/Lib/site-packages/dns/win32util.py delete mode 100644 venv/Lib/site-packages/dns/wire.py delete mode 100644 venv/Lib/site-packages/dns/xfr.py delete mode 100644 venv/Lib/site-packages/dns/zone.py delete mode 100644 venv/Lib/site-packages/dns/zonefile.py delete mode 100644 venv/Lib/site-packages/dns/zonetypes.py delete mode 100644 venv/Lib/site-packages/dnspython-2.7.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/dnspython-2.7.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/dnspython-2.7.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/dnspython-2.7.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/dnspython-2.7.0.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/docutils-0.21.2.dist-info/COPYING.txt delete mode 100644 venv/Lib/site-packages/docutils-0.21.2.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/docutils-0.21.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/docutils-0.21.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/docutils-0.21.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/docutils-0.21.2.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/docutils/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/__main__.py delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/examples.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/frontend.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/io.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/nodes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/__pycache__/statemachine.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/core.py delete mode 100644 venv/Lib/site-packages/docutils/docutils.conf delete mode 100644 venv/Lib/site-packages/docutils/examples.py delete mode 100644 venv/Lib/site-packages/docutils/frontend.py delete mode 100644 venv/Lib/site-packages/docutils/io.py delete mode 100644 venv/Lib/site-packages/docutils/languages/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/af.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/ar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/ca.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/cs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/da.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/de.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/en.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/eo.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/es.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/fa.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/fi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/fr.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/gl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/he.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/it.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/ja.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/ka.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/ko.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/lt.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/lv.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/nl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/pl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/pt_br.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/ru.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/sk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/sv.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/uk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/zh_cn.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/__pycache__/zh_tw.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/languages/af.py delete mode 100644 venv/Lib/site-packages/docutils/languages/ar.py delete mode 100644 venv/Lib/site-packages/docutils/languages/ca.py delete mode 100644 venv/Lib/site-packages/docutils/languages/cs.py delete mode 100644 venv/Lib/site-packages/docutils/languages/da.py delete mode 100644 venv/Lib/site-packages/docutils/languages/de.py delete mode 100644 venv/Lib/site-packages/docutils/languages/en.py delete mode 100644 venv/Lib/site-packages/docutils/languages/eo.py delete mode 100644 venv/Lib/site-packages/docutils/languages/es.py delete mode 100644 venv/Lib/site-packages/docutils/languages/fa.py delete mode 100644 venv/Lib/site-packages/docutils/languages/fi.py delete mode 100644 venv/Lib/site-packages/docutils/languages/fr.py delete mode 100644 venv/Lib/site-packages/docutils/languages/gl.py delete mode 100644 venv/Lib/site-packages/docutils/languages/he.py delete mode 100644 venv/Lib/site-packages/docutils/languages/it.py delete mode 100644 venv/Lib/site-packages/docutils/languages/ja.py delete mode 100644 venv/Lib/site-packages/docutils/languages/ka.py delete mode 100644 venv/Lib/site-packages/docutils/languages/ko.py delete mode 100644 venv/Lib/site-packages/docutils/languages/lt.py delete mode 100644 venv/Lib/site-packages/docutils/languages/lv.py delete mode 100644 venv/Lib/site-packages/docutils/languages/nl.py delete mode 100644 venv/Lib/site-packages/docutils/languages/pl.py delete mode 100644 venv/Lib/site-packages/docutils/languages/pt_br.py delete mode 100644 venv/Lib/site-packages/docutils/languages/ru.py delete mode 100644 venv/Lib/site-packages/docutils/languages/sk.py delete mode 100644 venv/Lib/site-packages/docutils/languages/sv.py delete mode 100644 venv/Lib/site-packages/docutils/languages/uk.py delete mode 100644 venv/Lib/site-packages/docutils/languages/zh_cn.py delete mode 100644 venv/Lib/site-packages/docutils/languages/zh_tw.py delete mode 100644 venv/Lib/site-packages/docutils/nodes.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/__pycache__/commonmark_wrapper.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/__pycache__/null.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/__pycache__/recommonmark_wrapper.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/commonmark_wrapper.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/null.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/recommonmark_wrapper.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/__pycache__/roles.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/__pycache__/states.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/__pycache__/tableparser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/admonitions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/body.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/html.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/images.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/misc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/parts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/references.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/__pycache__/tables.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/admonitions.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/body.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/html.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/images.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/misc.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/parts.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/references.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/directives/tables.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/README.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isoamsa.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isoamsb.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isoamsc.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isoamsn.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isoamso.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isoamsr.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isobox.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isocyr1.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isocyr2.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isodia.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isogrk1.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isogrk2.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isogrk3.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isogrk4-wide.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isogrk4.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isolat1.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isolat2.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isomfrk-wide.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isomfrk.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isomopf-wide.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isomopf.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isomscr-wide.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isomscr.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isonum.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isopub.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/isotech.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/mmlalias.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/mmlextra-wide.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/mmlextra.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/s5defs.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/xhtml1-lat1.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/xhtml1-special.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/include/xhtml1-symbol.txt delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/af.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/ar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/ca.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/cs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/da.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/de.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/en.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/eo.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/es.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/fa.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/fi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/fr.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/gl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/he.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/it.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/ja.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/ka.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/ko.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/lt.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/lv.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/nl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/pl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/pt_br.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/ru.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/sk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/sv.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/uk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/zh_cn.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/__pycache__/zh_tw.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/af.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/ar.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/ca.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/cs.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/da.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/de.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/en.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/eo.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/es.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/fa.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/fi.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/fr.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/gl.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/he.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/it.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/ja.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/ka.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/ko.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/lt.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/lv.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/nl.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/pl.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/pt_br.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/ru.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/sk.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/sv.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/uk.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/zh_cn.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/languages/zh_tw.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/roles.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/states.py delete mode 100644 venv/Lib/site-packages/docutils/parsers/rst/tableparser.py delete mode 100644 venv/Lib/site-packages/docutils/readers/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/readers/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/readers/__pycache__/doctree.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/readers/__pycache__/pep.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/readers/__pycache__/standalone.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/readers/doctree.py delete mode 100644 venv/Lib/site-packages/docutils/readers/pep.py delete mode 100644 venv/Lib/site-packages/docutils/readers/standalone.py delete mode 100644 venv/Lib/site-packages/docutils/statemachine.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/components.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/frontmatter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/misc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/parts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/peps.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/references.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/universal.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/__pycache__/writer_aux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/transforms/components.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/frontmatter.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/misc.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/parts.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/peps.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/references.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/universal.py delete mode 100644 venv/Lib/site-packages/docutils/transforms/writer_aux.py delete mode 100644 venv/Lib/site-packages/docutils/utils/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/code_analyzer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/error_reporting.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/punctuation_chars.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/roman.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/smartquotes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/__pycache__/urischemes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/code_analyzer.py delete mode 100644 venv/Lib/site-packages/docutils/utils/error_reporting.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/latex2mathml.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/math2html.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/mathalphabet2unichar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/mathml_elements.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/tex2mathml_extern.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/tex2unichar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/__pycache__/unichar2tex.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/utils/math/latex2mathml.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/math2html.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/mathalphabet2unichar.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/mathml_elements.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/tex2mathml_extern.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/tex2unichar.py delete mode 100644 venv/Lib/site-packages/docutils/utils/math/unichar2tex.py delete mode 100644 venv/Lib/site-packages/docutils/utils/punctuation_chars.py delete mode 100644 venv/Lib/site-packages/docutils/utils/roman.py delete mode 100644 venv/Lib/site-packages/docutils/utils/smartquotes.py delete mode 100644 venv/Lib/site-packages/docutils/utils/urischemes.py delete mode 100644 venv/Lib/site-packages/docutils/writers/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/__pycache__/_html_base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/__pycache__/docutils_xml.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/__pycache__/manpage.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/__pycache__/null.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/__pycache__/pseudoxml.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/_html_base.py delete mode 100644 venv/Lib/site-packages/docutils/writers/docutils_xml.py delete mode 100644 venv/Lib/site-packages/docutils/writers/html4css1/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/html4css1/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/html4css1/html4css1.css delete mode 100644 venv/Lib/site-packages/docutils/writers/html4css1/template.txt delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/italic-field-names.css delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/math.css delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/minimal.css delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/plain.css delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/responsive.css delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/template.txt delete mode 100644 venv/Lib/site-packages/docutils/writers/html5_polyglot/tuftig.css delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/default.tex delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/docutils.sty delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/titlepage.tex delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/titlingpage.tex delete mode 100644 venv/Lib/site-packages/docutils/writers/latex2e/xelatex.tex delete mode 100644 venv/Lib/site-packages/docutils/writers/manpage.py delete mode 100644 venv/Lib/site-packages/docutils/writers/null.py delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/__pycache__/prepstyles.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/__pycache__/pygmentsformatter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/prepstyles.py delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/pygmentsformatter.py delete mode 100644 venv/Lib/site-packages/docutils/writers/odf_odt/styles.odt delete mode 100644 venv/Lib/site-packages/docutils/writers/pep_html/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/pep_html/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/pep_html/pep.css delete mode 100644 venv/Lib/site-packages/docutils/writers/pep_html/template.txt delete mode 100644 venv/Lib/site-packages/docutils/writers/pseudoxml.py delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/README.txt delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/big-black/__base__ delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/big-black/framing.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/big-black/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/big-white/framing.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/big-white/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/framing.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/opera.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/outline.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/print.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/s5-core.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/slides.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/default/slides.js delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/medium-black/__base__ delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/medium-black/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/medium-white/framing.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/medium-white/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/small-black/__base__ delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/small-black/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/small-white/framing.css delete mode 100644 venv/Lib/site-packages/docutils/writers/s5_html/themes/small-white/pretty.css delete mode 100644 venv/Lib/site-packages/docutils/writers/xetex/__init__.py delete mode 100644 venv/Lib/site-packages/docutils/writers/xetex/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__init__.py delete mode 100644 venv/Lib/site-packages/dotenv/__main__.py delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/cli.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/ipython.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/main.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/variables.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/dotenv/cli.py delete mode 100644 venv/Lib/site-packages/dotenv/ipython.py delete mode 100644 venv/Lib/site-packages/dotenv/main.py delete mode 100644 venv/Lib/site-packages/dotenv/parser.py delete mode 100644 venv/Lib/site-packages/dotenv/py.typed delete mode 100644 venv/Lib/site-packages/dotenv/variables.py delete mode 100644 venv/Lib/site-packages/dotenv/version.py delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/flask-3.1.0.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/flask/__init__.py delete mode 100644 venv/Lib/site-packages/flask/__main__.py delete mode 100644 venv/Lib/site-packages/flask/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/app.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/blueprints.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/cli.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/config.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/ctx.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/debughelpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/globals.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/logging.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/sessions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/signals.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/templating.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/typing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/views.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/__pycache__/wrappers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/app.py delete mode 100644 venv/Lib/site-packages/flask/blueprints.py delete mode 100644 venv/Lib/site-packages/flask/cli.py delete mode 100644 venv/Lib/site-packages/flask/config.py delete mode 100644 venv/Lib/site-packages/flask/ctx.py delete mode 100644 venv/Lib/site-packages/flask/debughelpers.py delete mode 100644 venv/Lib/site-packages/flask/globals.py delete mode 100644 venv/Lib/site-packages/flask/helpers.py delete mode 100644 venv/Lib/site-packages/flask/json/__init__.py delete mode 100644 venv/Lib/site-packages/flask/json/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/json/__pycache__/provider.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/json/__pycache__/tag.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/json/provider.py delete mode 100644 venv/Lib/site-packages/flask/json/tag.py delete mode 100644 venv/Lib/site-packages/flask/logging.py delete mode 100644 venv/Lib/site-packages/flask/py.typed delete mode 100644 venv/Lib/site-packages/flask/sansio/README.md delete mode 100644 venv/Lib/site-packages/flask/sansio/__pycache__/app.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/sansio/__pycache__/blueprints.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/sansio/__pycache__/scaffold.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/flask/sansio/app.py delete mode 100644 venv/Lib/site-packages/flask/sansio/blueprints.py delete mode 100644 venv/Lib/site-packages/flask/sansio/scaffold.py delete mode 100644 venv/Lib/site-packages/flask/sessions.py delete mode 100644 venv/Lib/site-packages/flask/signals.py delete mode 100644 venv/Lib/site-packages/flask/templating.py delete mode 100644 venv/Lib/site-packages/flask/testing.py delete mode 100644 venv/Lib/site-packages/flask/typing.py delete mode 100644 venv/Lib/site-packages/flask/views.py delete mode 100644 venv/Lib/site-packages/flask/wrappers.py delete mode 100644 venv/Lib/site-packages/gridfs/__init__.py delete mode 100644 venv/Lib/site-packages/gridfs/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/__pycache__/grid_file.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/__pycache__/grid_file_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/asynchronous/__init__.py delete mode 100644 venv/Lib/site-packages/gridfs/asynchronous/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/asynchronous/__pycache__/grid_file.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/asynchronous/grid_file.py delete mode 100644 venv/Lib/site-packages/gridfs/errors.py delete mode 100644 venv/Lib/site-packages/gridfs/grid_file.py delete mode 100644 venv/Lib/site-packages/gridfs/grid_file_shared.py delete mode 100644 venv/Lib/site-packages/gridfs/py.typed delete mode 100644 venv/Lib/site-packages/gridfs/synchronous/__pycache__/grid_file.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gridfs/synchronous/grid_file.py delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/LICENSE delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/gunicorn-23.0.0.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/gunicorn/__init__.py delete mode 100644 venv/Lib/site-packages/gunicorn/__main__.py delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/arbiter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/config.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/debug.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/glogging.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/pidfile.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/reloader.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/sock.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/systemd.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/app/__init__.py delete mode 100644 venv/Lib/site-packages/gunicorn/app/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/app/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/app/__pycache__/pasterapp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/app/__pycache__/wsgiapp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/app/base.py delete mode 100644 venv/Lib/site-packages/gunicorn/app/pasterapp.py delete mode 100644 venv/Lib/site-packages/gunicorn/app/wsgiapp.py delete mode 100644 venv/Lib/site-packages/gunicorn/arbiter.py delete mode 100644 venv/Lib/site-packages/gunicorn/config.py delete mode 100644 venv/Lib/site-packages/gunicorn/debug.py delete mode 100644 venv/Lib/site-packages/gunicorn/errors.py delete mode 100644 venv/Lib/site-packages/gunicorn/glogging.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/__init__.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/body.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/message.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/unreader.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/__pycache__/wsgi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/http/body.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/errors.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/message.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/parser.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/unreader.py delete mode 100644 venv/Lib/site-packages/gunicorn/http/wsgi.py delete mode 100644 venv/Lib/site-packages/gunicorn/instrument/__init__.py delete mode 100644 venv/Lib/site-packages/gunicorn/instrument/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/instrument/__pycache__/statsd.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/instrument/statsd.py delete mode 100644 venv/Lib/site-packages/gunicorn/pidfile.py delete mode 100644 venv/Lib/site-packages/gunicorn/reloader.py delete mode 100644 venv/Lib/site-packages/gunicorn/sock.py delete mode 100644 venv/Lib/site-packages/gunicorn/systemd.py delete mode 100644 venv/Lib/site-packages/gunicorn/util.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__init__.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/base_async.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/geventlet.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/ggevent.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/gthread.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/gtornado.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/sync.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/__pycache__/workertmp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/gunicorn/workers/base.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/base_async.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/geventlet.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/ggevent.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/gthread.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/gtornado.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/sync.py delete mode 100644 venv/Lib/site-packages/gunicorn/workers/workertmp.py delete mode 100644 venv/Lib/site-packages/idna-3.10.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/idna-3.10.dist-info/LICENSE.md delete mode 100644 venv/Lib/site-packages/idna-3.10.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/idna-3.10.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/idna-3.10.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/idna/__init__.py delete mode 100644 venv/Lib/site-packages/idna/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/codec.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/idnadata.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/intranges.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/package_data.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/__pycache__/uts46data.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/idna/codec.py delete mode 100644 venv/Lib/site-packages/idna/compat.py delete mode 100644 venv/Lib/site-packages/idna/core.py delete mode 100644 venv/Lib/site-packages/idna/idnadata.py delete mode 100644 venv/Lib/site-packages/idna/intranges.py delete mode 100644 venv/Lib/site-packages/idna/package_data.py delete mode 100644 venv/Lib/site-packages/idna/py.typed delete mode 100644 venv/Lib/site-packages/idna/uts46data.py delete mode 100644 venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/itsdangerous-2.2.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/itsdangerous/__init__.py delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/_json.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/encoding.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/exc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/serializer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/signer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/timed.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/__pycache__/url_safe.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/itsdangerous/_json.py delete mode 100644 venv/Lib/site-packages/itsdangerous/encoding.py delete mode 100644 venv/Lib/site-packages/itsdangerous/exc.py delete mode 100644 venv/Lib/site-packages/itsdangerous/py.typed delete mode 100644 venv/Lib/site-packages/itsdangerous/serializer.py delete mode 100644 venv/Lib/site-packages/itsdangerous/signer.py delete mode 100644 venv/Lib/site-packages/itsdangerous/timed.py delete mode 100644 venv/Lib/site-packages/itsdangerous/url_safe.py delete mode 100644 venv/Lib/site-packages/jinja2-3.1.6.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/jinja2-3.1.6.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/jinja2-3.1.6.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/jinja2-3.1.6.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/jinja2-3.1.6.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/jinja2-3.1.6.dist-info/licenses/LICENSE.txt delete mode 100644 venv/Lib/site-packages/jinja2/__init__.py delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/_identifier.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/async_utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/bccache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/compiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/constants.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/debug.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/defaults.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/environment.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/ext.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/filters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/idtracking.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/lexer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/loaders.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/meta.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/nativetypes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/nodes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/optimizer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/runtime.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/sandbox.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/tests.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/__pycache__/visitor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/jinja2/_identifier.py delete mode 100644 venv/Lib/site-packages/jinja2/async_utils.py delete mode 100644 venv/Lib/site-packages/jinja2/bccache.py delete mode 100644 venv/Lib/site-packages/jinja2/compiler.py delete mode 100644 venv/Lib/site-packages/jinja2/constants.py delete mode 100644 venv/Lib/site-packages/jinja2/debug.py delete mode 100644 venv/Lib/site-packages/jinja2/defaults.py delete mode 100644 venv/Lib/site-packages/jinja2/environment.py delete mode 100644 venv/Lib/site-packages/jinja2/exceptions.py delete mode 100644 venv/Lib/site-packages/jinja2/ext.py delete mode 100644 venv/Lib/site-packages/jinja2/filters.py delete mode 100644 venv/Lib/site-packages/jinja2/idtracking.py delete mode 100644 venv/Lib/site-packages/jinja2/lexer.py delete mode 100644 venv/Lib/site-packages/jinja2/loaders.py delete mode 100644 venv/Lib/site-packages/jinja2/meta.py delete mode 100644 venv/Lib/site-packages/jinja2/nativetypes.py delete mode 100644 venv/Lib/site-packages/jinja2/nodes.py delete mode 100644 venv/Lib/site-packages/jinja2/optimizer.py delete mode 100644 venv/Lib/site-packages/jinja2/parser.py delete mode 100644 venv/Lib/site-packages/jinja2/py.typed delete mode 100644 venv/Lib/site-packages/jinja2/runtime.py delete mode 100644 venv/Lib/site-packages/jinja2/sandbox.py delete mode 100644 venv/Lib/site-packages/jinja2/tests.py delete mode 100644 venv/Lib/site-packages/jinja2/utils.py delete mode 100644 venv/Lib/site-packages/jinja2/visitor.py delete mode 100644 venv/Lib/site-packages/markupsafe/__init__.py delete mode 100644 venv/Lib/site-packages/markupsafe/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/markupsafe/__pycache__/_native.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/markupsafe/_native.py delete mode 100644 venv/Lib/site-packages/markupsafe/_speedups.c delete mode 100644 venv/Lib/site-packages/markupsafe/_speedups.cp310-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/markupsafe/_speedups.pyi delete mode 100644 venv/Lib/site-packages/markupsafe/py.typed delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/licenses/LICENSE.APACHE delete mode 100644 venv/Lib/site-packages/packaging-25.0.dist-info/licenses/LICENSE.BSD delete mode 100644 venv/Lib/site-packages/packaging/__init__.py delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/_elffile.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/_manylinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/_musllinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/_structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/_tokenizer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/markers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/metadata.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/requirements.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/specifiers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/tags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/_elffile.py delete mode 100644 venv/Lib/site-packages/packaging/_manylinux.py delete mode 100644 venv/Lib/site-packages/packaging/_musllinux.py delete mode 100644 venv/Lib/site-packages/packaging/_parser.py delete mode 100644 venv/Lib/site-packages/packaging/_structures.py delete mode 100644 venv/Lib/site-packages/packaging/_tokenizer.py delete mode 100644 venv/Lib/site-packages/packaging/licenses/__init__.py delete mode 100644 venv/Lib/site-packages/packaging/licenses/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/licenses/__pycache__/_spdx.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/packaging/licenses/_spdx.py delete mode 100644 venv/Lib/site-packages/packaging/markers.py delete mode 100644 venv/Lib/site-packages/packaging/metadata.py delete mode 100644 venv/Lib/site-packages/packaging/py.typed delete mode 100644 venv/Lib/site-packages/packaging/requirements.py delete mode 100644 venv/Lib/site-packages/packaging/specifiers.py delete mode 100644 venv/Lib/site-packages/packaging/tags.py delete mode 100644 venv/Lib/site-packages/packaging/utils.py delete mode 100644 venv/Lib/site-packages/packaging/version.py delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/pathlib-1.0.1.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/pathlib.py delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/pip-22.2.1.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/pip/__init__.py delete mode 100644 venv/Lib/site-packages/pip/__main__.py delete mode 100644 venv/Lib/site-packages/pip/__pip-runner__.py delete mode 100644 venv/Lib/site-packages/pip/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/__pycache__/__pip-runner__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/main.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/pyproject.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/build_env.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cache.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/main.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/autocompletion.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/base_command.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/command_context.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/main.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/main_parser.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/parser.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/progress_bars.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/req_command.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/spinners.py delete mode 100644 venv/Lib/site-packages/pip/_internal/cli/status_codes.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/completion.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/debug.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/download.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/hash.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/index.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/list.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/search.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/show.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/cache.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/check.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/completion.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/configuration.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/debug.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/download.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/freeze.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/hash.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/help.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/index.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/inspect.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/install.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/list.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/search.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/show.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/uninstall.py delete mode 100644 venv/Lib/site-packages/pip/_internal/commands/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/configuration.py delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/base.py delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/installed.py delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/sdist.py delete mode 100644 venv/Lib/site-packages/pip/_internal/distributions/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/exceptions.py delete mode 100644 venv/Lib/site-packages/pip/_internal/index/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/collector.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/index/__pycache__/sources.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/index/collector.py delete mode 100644 venv/Lib/site-packages/pip/_internal/index/package_finder.py delete mode 100644 venv/Lib/site-packages/pip/_internal/index/sources.py delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/_distutils.py delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/_sysconfig.py delete mode 100644 venv/Lib/site-packages/pip/_internal/locations/base.py delete mode 100644 venv/Lib/site-packages/pip/_internal/main.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/_json.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/base.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/_compat.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py delete mode 100644 venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/format_control.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/index.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/link.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/scheme.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/target_python.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/models/candidate.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/direct_url.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/format_control.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/index.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/installation_report.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/link.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/scheme.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/search_scope.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/selection_prefs.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/target_python.py delete mode 100644 venv/Lib/site-packages/pip/_internal/models/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/download.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/session.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/network/auth.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/cache.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/download.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/session.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/utils.py delete mode 100644 venv/Lib/site-packages/pip/_internal/network/xmlrpc.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/check.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata_editable.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/metadata_legacy.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel_editable.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/build/wheel_legacy.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/check.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/freeze.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/legacy.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/install/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/operations/prepare.py delete mode 100644 venv/Lib/site-packages/pip/_internal/pyproject.py delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/constructors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_file.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_install.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/req/constructors.py delete mode 100644 venv/Lib/site-packages/pip/_internal/req/req_file.py delete mode 100644 venv/Lib/site-packages/pip/_internal/req/req_install.py delete mode 100644 venv/Lib/site-packages/pip/_internal/req/req_set.py delete mode 100644 venv/Lib/site-packages/pip/_internal/req/req_uninstall.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/base.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py delete mode 100644 venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py delete mode 100644 venv/Lib/site-packages/pip/_internal/self_outdated_check.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/_log.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/distutils_args.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/inject_securetransport.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/logging.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/misc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/urls.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/_log.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/appdirs.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/compat.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/compatibility_tags.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/datetime.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/deprecation.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/direct_url_helpers.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/distutils_args.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/egg_link.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/encoding.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/entrypoints.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/filesystem.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/filetypes.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/glibc.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/hashes.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/logging.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/misc.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/models.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/packaging.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/subprocess.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/temp_dir.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/unpacking.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/urls.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/virtualenv.py delete mode 100644 venv/Lib/site-packages/pip/_internal/utils/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/git.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/bazaar.py delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/git.py delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/mercurial.py delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/subversion.py delete mode 100644 venv/Lib/site-packages/pip/_internal/vcs/versioncontrol.py delete mode 100644 venv/Lib/site-packages/pip/_internal/wheel_builder.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__main__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem delete mode 100644 venv/Lib/site-packages/pip/_vendor/certifi/core.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/big5freq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/big5prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/chardistribution.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/charsetgroupprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/charsetprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cli/chardetect.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/codingstatemachine.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/cp949prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/enums.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/escprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/escsm.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/eucjpprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euckrfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euckrprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euctwfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/euctwprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/gb2312freq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/gb2312prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/hebrewprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/jisfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/johabfreq.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/johabprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/jpcntx.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langbulgarianmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langgreekmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langhebrewmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langhungarianmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langrussianmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langthaimodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/langturkishmodel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/latin1prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcharsetprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcsgroupprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/mbcssm.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/metadata/languages.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sbcharsetprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sbcsgroupprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/sjisprober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/universaldetector.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/utf1632prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/utf8prober.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/chardet/version.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/colorama/winterm.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/database.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/index.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t32.exe delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t64-arm.exe delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/t64.exe delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/util.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/version.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w32.exe delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w64-arm.exe delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/w64.exe delete mode 100644 venv/Lib/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__main__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/distro/distro.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/codec.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/core.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/idnadata.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/intranges.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/package_data.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/idna/uts46data.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/exceptions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/ext.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__about__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_manylinux.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_musllinux.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/markers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/requirements.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/tags.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/utils.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/packaging/version.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/build.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/check.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/colorlog.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/dirtools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/envbuild.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/meta.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/__pycache__/wrappers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/build.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/check.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/colorlog.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/dirtools.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/envbuild.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/__pycache__/_in_process.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/in_process/_in_process.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/meta.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pep517/wrappers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/android.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/api.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/version.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__main__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/console.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filter.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatter.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexer.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/modeline.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/plugin.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/scanner.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/style.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/token.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/unistring.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pygments/util.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/common.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/core.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/exceptions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/helpers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/results.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/testing.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/unicode.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/pyparsing/util.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/help.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/__version__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/_internal_utils.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/api.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/auth.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/certs.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/compat.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/help.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/models.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/packages.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/structures.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/requests/utils.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/providers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/reporters.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/resolvers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/resolvelib/structs.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__main__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/align.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/box.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/console.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/control.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/json.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/region.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/status.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/style.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/table.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/text.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_cell_widths.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_emoji_codes.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_emoji_replace.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_export_format.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_extension.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_inspect.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_log_render.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_loop.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_palettes.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_pick.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_ratio.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_spinners.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_stack.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_timer.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_win32_console.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_windows.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_windows_renderer.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/_wrap.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/abc.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/align.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/ansi.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/bar.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/box.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/cells.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/color.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/color_triplet.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/columns.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/console.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/constrain.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/containers.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/control.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/default_styles.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/diagnose.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/emoji.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/errors.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/file_proxy.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/filesize.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/highlighter.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/json.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/jupyter.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/layout.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/live.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/live_render.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/logging.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/markup.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/measure.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/padding.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/pager.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/palette.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/panel.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/pretty.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/progress.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/progress_bar.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/prompt.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/protocol.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/region.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/repr.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/rule.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/scope.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/screen.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/segment.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/spinner.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/status.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/style.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/styled.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/syntax.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/table.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/terminal_theme.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/text.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/theme.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/themes.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/traceback.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/rich/tree.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/six.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/_asyncio.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/_utils.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/after.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/before.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/before_sleep.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/nap.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/retry.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/stop.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/tornadoweb.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tenacity/wait.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_parser.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_re.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/tomli/_types.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/typing_extensions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/_collections.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/_version.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/connection.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/connectionpool.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/appengine.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/securetransport.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/contrib/socks.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/exceptions.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/fields.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/filepost.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/packages/six.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/poolmanager.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/request.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/response.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/proxy.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/queue.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/ssltransport.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/vendor.txt delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__init__.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/labels.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/mklabels.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/tests.py delete mode 100644 venv/Lib/site-packages/pip/_vendor/webencodings/x_user_defined.py delete mode 100644 venv/Lib/site-packages/pip/py.typed delete mode 100644 venv/Lib/site-packages/pkg_resources/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/appdirs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/__pycache__/zipp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/appdirs.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_adapters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_itertools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/_legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/abc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/readers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/__pycache__/simple.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_adapters.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_common.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_compat.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_itertools.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/_legacy.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/abc.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/readers.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/importlib_resources/simple.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__pycache__/context.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/__pycache__/functools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/context.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/functools.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/text/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/jaraco/text/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/more.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/__pycache__/recipes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/more.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/more_itertools/recipes.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__about__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/__about__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/_structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/markers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/requirements.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/tags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/_manylinux.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/_musllinux.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/_structures.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/markers.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/requirements.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/specifiers.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/tags.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/utils.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/packaging/version.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/results.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/actions.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/common.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/core.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/diagram/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/exceptions.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/helpers.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/results.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/testing.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/unicode.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/pyparsing/util.py delete mode 100644 venv/Lib/site-packages/pkg_resources/_vendor/zipp.py delete mode 100644 venv/Lib/site-packages/pkg_resources/extern/__init__.py delete mode 100644 venv/Lib/site-packages/pkg_resources/extern/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo-4.12.1.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/pymongo-4.12.1.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/pymongo-4.12.1.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/pymongo-4.12.1.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/pymongo-4.12.1.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/pymongo-4.12.1.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/pymongo/__init__.py delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_asyncio_lock.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_asyncio_task.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_azure_helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_client_bulk_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_csot.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_gcp_helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/_version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/auth_oidc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/auth_oidc_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/auth_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/bulk_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/change_stream.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/client_options.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/client_session.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/collation.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/collection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/command_cursor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/compression_support.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/cursor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/cursor_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/daemon.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/database.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/database_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/driver_info.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/encryption.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/encryption_options.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/event_loggers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/hello.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/helpers_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/lock.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/logger.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/max_staleness_selectors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/message.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/mongo_client.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/monitoring.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/network_layer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/ocsp_cache.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/ocsp_support.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/operations.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/periodic_executor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/pool.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/pool_options.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/pool_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/pyopenssl_context.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/read_concern.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/read_preferences.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/results.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/saslprep.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/server_api.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/server_description.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/server_selectors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/server_type.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/socket_checker.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/ssl_context.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/ssl_support.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/topology_description.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/typings.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/uri_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/uri_parser_shared.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/__pycache__/write_concern.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/_asyncio_lock.py delete mode 100644 venv/Lib/site-packages/pymongo/_asyncio_task.py delete mode 100644 venv/Lib/site-packages/pymongo/_azure_helpers.py delete mode 100644 venv/Lib/site-packages/pymongo/_client_bulk_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/_cmessage.cp310-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/pymongo/_cmessage.cp39-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/pymongo/_cmessagemodule.c delete mode 100644 venv/Lib/site-packages/pymongo/_csot.py delete mode 100644 venv/Lib/site-packages/pymongo/_gcp_helpers.py delete mode 100644 venv/Lib/site-packages/pymongo/_version.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__init__.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/aggregation.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/auth_aws.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/auth_oidc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/bulk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/change_stream.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/client_bulk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/client_session.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/collection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/command_cursor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/cursor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/database.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/encryption.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/mongo_client.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/monitor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/network.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/pool.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/server.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/settings.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/srv_resolver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/topology.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/__pycache__/uri_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/aggregation.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/auth.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/auth_aws.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/auth_oidc.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/bulk.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/change_stream.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/client_bulk.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/client_session.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/collection.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/command_cursor.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/cursor.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/database.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/encryption.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/helpers.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/mongo_client.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/monitor.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/network.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/pool.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/server.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/settings.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/srv_resolver.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/topology.py delete mode 100644 venv/Lib/site-packages/pymongo/asynchronous/uri_parser.py delete mode 100644 venv/Lib/site-packages/pymongo/auth.py delete mode 100644 venv/Lib/site-packages/pymongo/auth_oidc.py delete mode 100644 venv/Lib/site-packages/pymongo/auth_oidc_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/auth_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/bulk_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/change_stream.py delete mode 100644 venv/Lib/site-packages/pymongo/client_options.py delete mode 100644 venv/Lib/site-packages/pymongo/client_session.py delete mode 100644 venv/Lib/site-packages/pymongo/collation.py delete mode 100644 venv/Lib/site-packages/pymongo/collection.py delete mode 100644 venv/Lib/site-packages/pymongo/command_cursor.py delete mode 100644 venv/Lib/site-packages/pymongo/common.py delete mode 100644 venv/Lib/site-packages/pymongo/compression_support.py delete mode 100644 venv/Lib/site-packages/pymongo/cursor.py delete mode 100644 venv/Lib/site-packages/pymongo/cursor_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/daemon.py delete mode 100644 venv/Lib/site-packages/pymongo/database.py delete mode 100644 venv/Lib/site-packages/pymongo/database_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/driver_info.py delete mode 100644 venv/Lib/site-packages/pymongo/encryption.py delete mode 100644 venv/Lib/site-packages/pymongo/encryption_options.py delete mode 100644 venv/Lib/site-packages/pymongo/errors.py delete mode 100644 venv/Lib/site-packages/pymongo/event_loggers.py delete mode 100644 venv/Lib/site-packages/pymongo/hello.py delete mode 100644 venv/Lib/site-packages/pymongo/helpers_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/lock.py delete mode 100644 venv/Lib/site-packages/pymongo/logger.py delete mode 100644 venv/Lib/site-packages/pymongo/max_staleness_selectors.py delete mode 100644 venv/Lib/site-packages/pymongo/message.py delete mode 100644 venv/Lib/site-packages/pymongo/mongo_client.py delete mode 100644 venv/Lib/site-packages/pymongo/monitoring.py delete mode 100644 venv/Lib/site-packages/pymongo/network_layer.py delete mode 100644 venv/Lib/site-packages/pymongo/ocsp_cache.py delete mode 100644 venv/Lib/site-packages/pymongo/ocsp_support.py delete mode 100644 venv/Lib/site-packages/pymongo/operations.py delete mode 100644 venv/Lib/site-packages/pymongo/periodic_executor.py delete mode 100644 venv/Lib/site-packages/pymongo/pool.py delete mode 100644 venv/Lib/site-packages/pymongo/pool_options.py delete mode 100644 venv/Lib/site-packages/pymongo/pool_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/py.typed delete mode 100644 venv/Lib/site-packages/pymongo/pyopenssl_context.py delete mode 100644 venv/Lib/site-packages/pymongo/read_concern.py delete mode 100644 venv/Lib/site-packages/pymongo/read_preferences.py delete mode 100644 venv/Lib/site-packages/pymongo/response.py delete mode 100644 venv/Lib/site-packages/pymongo/results.py delete mode 100644 venv/Lib/site-packages/pymongo/saslprep.py delete mode 100644 venv/Lib/site-packages/pymongo/server_api.py delete mode 100644 venv/Lib/site-packages/pymongo/server_description.py delete mode 100644 venv/Lib/site-packages/pymongo/server_selectors.py delete mode 100644 venv/Lib/site-packages/pymongo/server_type.py delete mode 100644 venv/Lib/site-packages/pymongo/socket_checker.py delete mode 100644 venv/Lib/site-packages/pymongo/ssl_context.py delete mode 100644 venv/Lib/site-packages/pymongo/ssl_support.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__init__.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/aggregation.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/auth_aws.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/auth_oidc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/bulk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/change_stream.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/client_bulk.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/client_session.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/collection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/command_cursor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/cursor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/database.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/encryption.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/mongo_client.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/monitor.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/network.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/pool.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/server.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/settings.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/srv_resolver.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/topology.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/__pycache__/uri_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/aggregation.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/auth.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/auth_aws.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/auth_oidc.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/bulk.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/change_stream.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/client_bulk.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/client_session.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/collection.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/command_cursor.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/cursor.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/database.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/encryption.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/helpers.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/mongo_client.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/monitor.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/network.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/pool.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/server.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/settings.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/srv_resolver.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/topology.py delete mode 100644 venv/Lib/site-packages/pymongo/synchronous/uri_parser.py delete mode 100644 venv/Lib/site-packages/pymongo/topology_description.py delete mode 100644 venv/Lib/site-packages/pymongo/typings.py delete mode 100644 venv/Lib/site-packages/pymongo/uri_parser.py delete mode 100644 venv/Lib/site-packages/pymongo/uri_parser_shared.py delete mode 100644 venv/Lib/site-packages/pymongo/write_concern.py delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/python_dotenv-1.1.0.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/pytz-2025.2.dist-info/zip-safe delete mode 100644 venv/Lib/site-packages/pytz/__init__.py delete mode 100644 venv/Lib/site-packages/pytz/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pytz/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pytz/__pycache__/lazy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pytz/__pycache__/reference.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pytz/__pycache__/tzfile.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pytz/__pycache__/tzinfo.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/pytz/exceptions.py delete mode 100644 venv/Lib/site-packages/pytz/lazy.py delete mode 100644 venv/Lib/site-packages/pytz/reference.py delete mode 100644 venv/Lib/site-packages/pytz/tzfile.py delete mode 100644 venv/Lib/site-packages/pytz/tzinfo.py delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Abidjan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Accra delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Addis_Ababa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Algiers delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Asmara delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Asmera delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Bamako delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Bangui delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Banjul delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Bissau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Blantyre delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Brazzaville delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Bujumbura delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Cairo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Casablanca delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Ceuta delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Conakry delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Dakar delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Dar_es_Salaam delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Djibouti delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Douala delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/El_Aaiun delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Freetown delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Gaborone delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Harare delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Johannesburg delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Juba delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Kampala delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Khartoum delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Kigali delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Kinshasa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Lagos delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Libreville delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Lome delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Luanda delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Lubumbashi delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Lusaka delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Malabo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Maputo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Maseru delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Mbabane delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Mogadishu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Monrovia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Nairobi delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Ndjamena delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Niamey delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Nouakchott delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Ouagadougou delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Porto-Novo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Sao_Tome delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Timbuktu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Tripoli delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Tunis delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Africa/Windhoek delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Adak delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Anchorage delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Anguilla delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Antigua delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Araguaina delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Buenos_Aires delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Catamarca delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/ComodRivadavia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Cordoba delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Jujuy delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/La_Rioja delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Mendoza delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Rio_Gallegos delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Salta delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/San_Juan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/San_Luis delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Tucuman delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Argentina/Ushuaia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Aruba delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Asuncion delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Atikokan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Atka delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Bahia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Bahia_Banderas delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Barbados delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Belem delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Belize delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Blanc-Sablon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Boa_Vista delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Bogota delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Boise delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Buenos_Aires delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Cambridge_Bay delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Campo_Grande delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Cancun delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Caracas delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Catamarca delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Cayenne delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Cayman delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Chicago delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Chihuahua delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Ciudad_Juarez delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Coral_Harbour delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Cordoba delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Costa_Rica delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Coyhaique delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Creston delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Cuiaba delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Curacao delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Danmarkshavn delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Dawson delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Dawson_Creek delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Denver delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Detroit delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Dominica delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Edmonton delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Eirunepe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/El_Salvador delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Ensenada delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Fort_Nelson delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Fort_Wayne delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Fortaleza delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Glace_Bay delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Godthab delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Goose_Bay delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Grand_Turk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Grenada delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Guadeloupe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Guatemala delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Guayaquil delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Guyana delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Halifax delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Havana delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Hermosillo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Indianapolis delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Knox delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Marengo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Petersburg delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Tell_City delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Vevay delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Vincennes delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indiana/Winamac delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Indianapolis delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Inuvik delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Iqaluit delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Jamaica delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Jujuy delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Juneau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Kentucky/Louisville delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Kentucky/Monticello delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Knox_IN delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Kralendijk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/La_Paz delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Lima delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Los_Angeles delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Louisville delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Lower_Princes delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Maceio delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Managua delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Manaus delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Marigot delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Martinique delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Matamoros delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Mazatlan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Mendoza delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Menominee delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Merida delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Metlakatla delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Mexico_City delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Miquelon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Moncton delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Monterrey delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Montevideo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Montreal delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Montserrat delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Nassau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/New_York delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Nipigon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Nome delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Noronha delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/North_Dakota/Beulah delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/North_Dakota/Center delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/North_Dakota/New_Salem delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Nuuk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Ojinaga delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Panama delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Pangnirtung delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Paramaribo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Phoenix delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Port-au-Prince delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Port_of_Spain delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Porto_Acre delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Porto_Velho delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Puerto_Rico delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Punta_Arenas delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Rainy_River delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Rankin_Inlet delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Recife delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Regina delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Resolute delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Rio_Branco delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Rosario delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Santa_Isabel delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Santarem delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Santiago delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Santo_Domingo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Sao_Paulo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Scoresbysund delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Shiprock delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Sitka delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/St_Barthelemy delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/St_Johns delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/St_Kitts delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/St_Lucia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/St_Thomas delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/St_Vincent delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Swift_Current delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Tegucigalpa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Thule delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Thunder_Bay delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Tijuana delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Toronto delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Tortola delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Vancouver delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Virgin delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Whitehorse delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Winnipeg delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Yakutat delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/America/Yellowknife delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Casey delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Davis delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/DumontDUrville delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Macquarie delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Mawson delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/McMurdo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Palmer delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Rothera delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/South_Pole delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Syowa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Troll delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Antarctica/Vostok delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Arctic/Longyearbyen delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Aden delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Almaty delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Amman delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Anadyr delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Aqtau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Aqtobe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ashgabat delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ashkhabad delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Atyrau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Baghdad delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Bahrain delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Baku delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Bangkok delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Barnaul delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Beirut delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Bishkek delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Brunei delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Calcutta delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Chita delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Choibalsan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Chongqing delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Chungking delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Colombo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Dacca delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Damascus delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Dhaka delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Dili delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Dubai delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Dushanbe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Famagusta delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Gaza delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Harbin delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Hebron delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ho_Chi_Minh delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Hong_Kong delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Hovd delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Irkutsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Istanbul delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Jakarta delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Jayapura delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Jerusalem delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kabul delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kamchatka delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Karachi delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kashgar delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kathmandu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Katmandu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Khandyga delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kolkata delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Krasnoyarsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kuala_Lumpur delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kuching delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Kuwait delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Macao delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Macau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Magadan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Makassar delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Manila delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Muscat delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Nicosia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Novokuznetsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Novosibirsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Omsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Oral delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Phnom_Penh delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Pontianak delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Pyongyang delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Qatar delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Qostanay delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Qyzylorda delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Rangoon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Riyadh delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Saigon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Sakhalin delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Samarkand delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Seoul delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Shanghai delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Singapore delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Srednekolymsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Taipei delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Tashkent delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Tbilisi delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Tehran delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Tel_Aviv delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Thimbu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Thimphu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Tokyo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Tomsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ujung_Pandang delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ulaanbaatar delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ulan_Bator delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Urumqi delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Ust-Nera delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Vientiane delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Vladivostok delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Yakutsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Yangon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Yekaterinburg delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Asia/Yerevan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Azores delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Bermuda delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Canary delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Cape_Verde delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Faeroe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Faroe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Jan_Mayen delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Madeira delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Reykjavik delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/South_Georgia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/St_Helena delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Atlantic/Stanley delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/ACT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Adelaide delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Brisbane delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Broken_Hill delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Canberra delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Currie delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Darwin delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Eucla delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Hobart delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/LHI delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Lindeman delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Lord_Howe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Melbourne delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/NSW delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/North delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Perth delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Queensland delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/South delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Sydney delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Tasmania delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Victoria delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/West delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Australia/Yancowinna delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Brazil/Acre delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Brazil/DeNoronha delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Brazil/East delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Brazil/West delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/CET delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/CST6CDT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Atlantic delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Central delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Eastern delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Mountain delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Newfoundland delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Pacific delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Saskatchewan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Canada/Yukon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Chile/Continental delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Chile/EasterIsland delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Cuba delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/EET delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/EST delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/EST5EDT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Egypt delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Eire delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+0 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+1 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+10 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+11 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+12 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+2 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+3 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+4 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+5 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+6 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+7 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+8 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT+9 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-0 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-1 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-10 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-11 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-12 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-13 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-14 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-2 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-3 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-4 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-5 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-6 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-7 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-8 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT-9 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/GMT0 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/Greenwich delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/UCT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/UTC delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/Universal delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Etc/Zulu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Amsterdam delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Andorra delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Astrakhan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Athens delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Belfast delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Belgrade delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Berlin delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Bratislava delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Brussels delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Bucharest delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Budapest delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Busingen delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Chisinau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Copenhagen delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Dublin delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Gibraltar delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Guernsey delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Helsinki delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Isle_of_Man delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Istanbul delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Jersey delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Kaliningrad delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Kiev delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Kirov delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Kyiv delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Lisbon delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Ljubljana delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/London delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Luxembourg delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Madrid delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Malta delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Mariehamn delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Minsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Monaco delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Moscow delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Nicosia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Oslo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Paris delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Podgorica delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Prague delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Riga delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Rome delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Samara delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/San_Marino delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Sarajevo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Saratov delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Simferopol delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Skopje delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Sofia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Stockholm delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Tallinn delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Tirane delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Tiraspol delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Ulyanovsk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Uzhgorod delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Vaduz delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Vatican delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Vienna delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Vilnius delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Volgograd delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Warsaw delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Zagreb delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Zaporozhye delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Europe/Zurich delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Factory delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/GB delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/GB-Eire delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/GMT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/GMT+0 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/GMT-0 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/GMT0 delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Greenwich delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/HST delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Hongkong delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Iceland delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Antananarivo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Chagos delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Christmas delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Cocos delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Comoro delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Kerguelen delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Mahe delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Maldives delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Mauritius delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Mayotte delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Indian/Reunion delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Iran delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Israel delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Jamaica delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Japan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Kwajalein delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Libya delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/MET delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/MST delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/MST7MDT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Mexico/BajaNorte delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Mexico/BajaSur delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Mexico/General delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/NZ delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/NZ-CHAT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Navajo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/PRC delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/PST8PDT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Apia delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Auckland delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Bougainville delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Chatham delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Chuuk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Easter delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Efate delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Enderbury delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Fakaofo delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Fiji delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Funafuti delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Galapagos delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Gambier delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Guadalcanal delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Guam delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Honolulu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Johnston delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Kanton delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Kiritimati delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Kosrae delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Kwajalein delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Majuro delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Marquesas delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Midway delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Nauru delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Niue delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Norfolk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Noumea delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Pago_Pago delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Palau delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Pitcairn delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Pohnpei delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Ponape delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Port_Moresby delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Rarotonga delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Saipan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Samoa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Tahiti delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Tarawa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Tongatapu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Truk delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Wake delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Wallis delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Pacific/Yap delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Poland delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Portugal delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/ROC delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/ROK delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Singapore delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Turkey delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/UCT delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Alaska delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Aleutian delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Arizona delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Central delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/East-Indiana delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Eastern delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Hawaii delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Indiana-Starke delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Michigan delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Mountain delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Pacific delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/US/Samoa delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/UTC delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Universal delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/W-SU delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/WET delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/Zulu delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/iso3166.tab delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/leapseconds delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/tzdata.zi delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/zone.tab delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/zone1970.tab delete mode 100644 venv/Lib/site-packages/pytz/zoneinfo/zonenow.tab delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/LICENSE delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/requests-2.32.3.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/requests/__init__.py delete mode 100644 venv/Lib/site-packages/requests/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/__version__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/_internal_utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/adapters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/api.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/certs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/cookies.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/help.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/hooks.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/models.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/packages.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/sessions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/status_codes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/requests/__version__.py delete mode 100644 venv/Lib/site-packages/requests/_internal_utils.py delete mode 100644 venv/Lib/site-packages/requests/adapters.py delete mode 100644 venv/Lib/site-packages/requests/api.py delete mode 100644 venv/Lib/site-packages/requests/auth.py delete mode 100644 venv/Lib/site-packages/requests/certs.py delete mode 100644 venv/Lib/site-packages/requests/compat.py delete mode 100644 venv/Lib/site-packages/requests/cookies.py delete mode 100644 venv/Lib/site-packages/requests/exceptions.py delete mode 100644 venv/Lib/site-packages/requests/help.py delete mode 100644 venv/Lib/site-packages/requests/hooks.py delete mode 100644 venv/Lib/site-packages/requests/models.py delete mode 100644 venv/Lib/site-packages/requests/packages.py delete mode 100644 venv/Lib/site-packages/requests/sessions.py delete mode 100644 venv/Lib/site-packages/requests/status_codes.py delete mode 100644 venv/Lib/site-packages/requests/structures.py delete mode 100644 venv/Lib/site-packages/requests/utils.py delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/LICENSE delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/entry_points.txt delete mode 100644 venv/Lib/site-packages/setuptools-63.2.0.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/setuptools/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_deprecation_warning.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_entry_points.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_imp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_importlib.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_itertools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_path.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/_reqs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/archive_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/build_meta.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/dep_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/depends.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/discovery.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/dist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/extension.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/glob.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/installer.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/launch.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/logging.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/monkey.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/msvc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/namespaces.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/package_index.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/py34compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/sandbox.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/unicode_utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/wheel.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/__pycache__/windows_support.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_deprecation_warning.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/_collections.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/_functools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/_macos_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/_msvccompiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/archive_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/bcppcompiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/ccompiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/cmd.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/config.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/cygwinccompiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/debug.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/dep_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/dir_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/dist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/errors.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/extension.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/fancy_getopt.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/file_util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/filelist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/log.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/msvc9compiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/msvccompiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/py38compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/py39compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/spawn.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/sysconfig.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/text_file.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/unixccompiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/__pycache__/versionpredicate.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/_collections.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/_functools.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/_macos_compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/archive_util.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/bcppcompiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/ccompiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/cmd.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/_framework_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_dumb.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_msi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_rpm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/bdist_wininst.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_clib.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_ext.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_py.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/build_scripts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/check.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/clean.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/config.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_data.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_egg_info.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_headers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_lib.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/install_scripts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/py37compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/register.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/sdist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/__pycache__/upload.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/_framework_compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_msi.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/bdist_wininst.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_py.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/check.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/clean.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/config.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_data.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/py37compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/register.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/sdist.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/command/upload.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/config.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/core.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/debug.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/dep_util.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/dir_util.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/dist.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/errors.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/extension.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/file_util.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/filelist.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/log.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/msvc9compiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/msvccompiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/py38compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/py39compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/spawn.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/sysconfig.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/text_file.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/util.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/version.py delete mode 100644 venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py delete mode 100644 venv/Lib/site-packages/setuptools/_entry_points.py delete mode 100644 venv/Lib/site-packages/setuptools/_imp.py delete mode 100644 venv/Lib/site-packages/setuptools/_importlib.py delete mode 100644 venv/Lib/site-packages/setuptools/_itertools.py delete mode 100644 venv/Lib/site-packages/setuptools/_path.py delete mode 100644 venv/Lib/site-packages/setuptools/_reqs.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/ordered_set.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/typing_extensions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/__pycache__/zipp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_adapters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_collections.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_functools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_itertools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_meta.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__pycache__/_text.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_adapters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_itertools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/_legacy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/abc.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/readers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/__pycache__/simple.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_adapters.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_common.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_compat.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_itertools.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/_legacy.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/abc.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/readers.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/importlib_resources/simple.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/context.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/__pycache__/functools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/functools.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/more.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/__pycache__/recipes.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/more.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/ordered_set.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__about__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__about__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/_structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/markers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/requirements.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/tags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/__pycache__/version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/_manylinux.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/packaging/version.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/common.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/core.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/results.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/actions.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/common.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/core.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/diagram/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/exceptions.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/helpers.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/results.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/testing.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/unicode.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/pyparsing/util.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/__pycache__/_parser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/__pycache__/_re.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/__pycache__/_types.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/_parser.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/_re.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/tomli/_types.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py delete mode 100644 venv/Lib/site-packages/setuptools/_vendor/zipp.py delete mode 100644 venv/Lib/site-packages/setuptools/archive_util.py delete mode 100644 venv/Lib/site-packages/setuptools/build_meta.py delete mode 100644 venv/Lib/site-packages/setuptools/cli-32.exe delete mode 100644 venv/Lib/site-packages/setuptools/cli-64.exe delete mode 100644 venv/Lib/site-packages/setuptools/cli-arm64.exe delete mode 100644 venv/Lib/site-packages/setuptools/cli.exe delete mode 100644 venv/Lib/site-packages/setuptools/command/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/alias.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/bdist_egg.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/bdist_rpm.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build_clib.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build_ext.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/build_py.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/develop.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/dist_info.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/easy_install.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/egg_info.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install_egg_info.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install_lib.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/install_scripts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/py36compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/register.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/rotate.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/saveopts.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/sdist.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/setopt.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/upload.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/__pycache__/upload_docs.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/command/alias.py delete mode 100644 venv/Lib/site-packages/setuptools/command/bdist_egg.py delete mode 100644 venv/Lib/site-packages/setuptools/command/bdist_rpm.py delete mode 100644 venv/Lib/site-packages/setuptools/command/build.py delete mode 100644 venv/Lib/site-packages/setuptools/command/build_clib.py delete mode 100644 venv/Lib/site-packages/setuptools/command/build_ext.py delete mode 100644 venv/Lib/site-packages/setuptools/command/build_py.py delete mode 100644 venv/Lib/site-packages/setuptools/command/develop.py delete mode 100644 venv/Lib/site-packages/setuptools/command/dist_info.py delete mode 100644 venv/Lib/site-packages/setuptools/command/easy_install.py delete mode 100644 venv/Lib/site-packages/setuptools/command/egg_info.py delete mode 100644 venv/Lib/site-packages/setuptools/command/install.py delete mode 100644 venv/Lib/site-packages/setuptools/command/install_egg_info.py delete mode 100644 venv/Lib/site-packages/setuptools/command/install_lib.py delete mode 100644 venv/Lib/site-packages/setuptools/command/install_scripts.py delete mode 100644 venv/Lib/site-packages/setuptools/command/launcher manifest.xml delete mode 100644 venv/Lib/site-packages/setuptools/command/py36compat.py delete mode 100644 venv/Lib/site-packages/setuptools/command/register.py delete mode 100644 venv/Lib/site-packages/setuptools/command/rotate.py delete mode 100644 venv/Lib/site-packages/setuptools/command/saveopts.py delete mode 100644 venv/Lib/site-packages/setuptools/command/sdist.py delete mode 100644 venv/Lib/site-packages/setuptools/command/setopt.py delete mode 100644 venv/Lib/site-packages/setuptools/command/test.py delete mode 100644 venv/Lib/site-packages/setuptools/command/upload.py delete mode 100644 venv/Lib/site-packages/setuptools/command/upload_docs.py delete mode 100644 venv/Lib/site-packages/setuptools/config/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/config/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/__pycache__/_apply_pyprojecttoml.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/__pycache__/expand.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/__pycache__/pyprojecttoml.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/__pycache__/setupcfg.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_apply_pyprojecttoml.py delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__pycache__/error_reporting.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__pycache__/extra_validations.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__pycache__/fastjsonschema_exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__pycache__/fastjsonschema_validations.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/__pycache__/formats.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/error_reporting.py delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/extra_validations.py delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/fastjsonschema_exceptions.py delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/fastjsonschema_validations.py delete mode 100644 venv/Lib/site-packages/setuptools/config/_validate_pyproject/formats.py delete mode 100644 venv/Lib/site-packages/setuptools/config/expand.py delete mode 100644 venv/Lib/site-packages/setuptools/config/pyprojecttoml.py delete mode 100644 venv/Lib/site-packages/setuptools/config/setupcfg.py delete mode 100644 venv/Lib/site-packages/setuptools/dep_util.py delete mode 100644 venv/Lib/site-packages/setuptools/depends.py delete mode 100644 venv/Lib/site-packages/setuptools/discovery.py delete mode 100644 venv/Lib/site-packages/setuptools/dist.py delete mode 100644 venv/Lib/site-packages/setuptools/errors.py delete mode 100644 venv/Lib/site-packages/setuptools/extension.py delete mode 100644 venv/Lib/site-packages/setuptools/extern/__init__.py delete mode 100644 venv/Lib/site-packages/setuptools/extern/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/setuptools/glob.py delete mode 100644 venv/Lib/site-packages/setuptools/gui-32.exe delete mode 100644 venv/Lib/site-packages/setuptools/gui-64.exe delete mode 100644 venv/Lib/site-packages/setuptools/gui-arm64.exe delete mode 100644 venv/Lib/site-packages/setuptools/gui.exe delete mode 100644 venv/Lib/site-packages/setuptools/installer.py delete mode 100644 venv/Lib/site-packages/setuptools/launch.py delete mode 100644 venv/Lib/site-packages/setuptools/logging.py delete mode 100644 venv/Lib/site-packages/setuptools/monkey.py delete mode 100644 venv/Lib/site-packages/setuptools/msvc.py delete mode 100644 venv/Lib/site-packages/setuptools/namespaces.py delete mode 100644 venv/Lib/site-packages/setuptools/package_index.py delete mode 100644 venv/Lib/site-packages/setuptools/py34compat.py delete mode 100644 venv/Lib/site-packages/setuptools/sandbox.py delete mode 100644 venv/Lib/site-packages/setuptools/script (dev).tmpl delete mode 100644 venv/Lib/site-packages/setuptools/script.tmpl delete mode 100644 venv/Lib/site-packages/setuptools/unicode_utils.py delete mode 100644 venv/Lib/site-packages/setuptools/version.py delete mode 100644 venv/Lib/site-packages/setuptools/wheel.py delete mode 100644 venv/Lib/site-packages/setuptools/windows_support.py delete mode 100644 venv/Lib/site-packages/statistics-1.0.3.5-py3.10.egg-info/PKG-INFO delete mode 100644 venv/Lib/site-packages/statistics-1.0.3.5-py3.10.egg-info/SOURCES.txt delete mode 100644 venv/Lib/site-packages/statistics-1.0.3.5-py3.10.egg-info/dependency_links.txt delete mode 100644 venv/Lib/site-packages/statistics-1.0.3.5-py3.10.egg-info/installed-files.txt delete mode 100644 venv/Lib/site-packages/statistics-1.0.3.5-py3.10.egg-info/requires.txt delete mode 100644 venv/Lib/site-packages/statistics-1.0.3.5-py3.10.egg-info/top_level.txt delete mode 100644 venv/Lib/site-packages/statistics/__init__.py delete mode 100644 venv/Lib/site-packages/statistics/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/REQUESTED delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/licenses/LICENSE delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/licenses/licenses/LICENSE_APACHE delete mode 100644 venv/Lib/site-packages/tzdata-2025.2.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/tzdata/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Abidjan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Accra delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Addis_Ababa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Algiers delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Asmara delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Asmera delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bamako delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bangui delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Banjul delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bissau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Blantyre delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Brazzaville delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Bujumbura delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Cairo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Casablanca delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ceuta delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Conakry delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Dakar delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Dar_es_Salaam delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Djibouti delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Douala delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/El_Aaiun delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Freetown delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Gaborone delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Harare delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Johannesburg delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Juba delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kampala delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Khartoum delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kigali delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Kinshasa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lagos delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Libreville delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lome delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Luanda delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lubumbashi delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Lusaka delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Malabo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Maputo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Maseru delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Mbabane delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Mogadishu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Monrovia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Nairobi delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ndjamena delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Niamey delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Nouakchott delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Ouagadougou delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Porto-Novo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Sao_Tome delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Timbuktu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Tripoli delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Tunis delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/Windhoek delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Africa/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Adak delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Anchorage delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Anguilla delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Antigua delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Araguaina delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Buenos_Aires delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Catamarca delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/ComodRivadavia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Cordoba delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Jujuy delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/La_Rioja delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Mendoza delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Rio_Gallegos delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Salta delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/San_Juan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/San_Luis delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Tucuman delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/Ushuaia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Argentina/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Aruba delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Asuncion delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Atikokan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Atka delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Bahia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Bahia_Banderas delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Barbados delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Belem delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Belize delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Blanc-Sablon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Boa_Vista delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Bogota delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Boise delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Buenos_Aires delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cambridge_Bay delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Campo_Grande delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cancun delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Caracas delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Catamarca delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cayenne delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cayman delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Chicago delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Chihuahua delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Ciudad_Juarez delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Coral_Harbour delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cordoba delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Costa_Rica delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Coyhaique delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Creston delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Cuiaba delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Curacao delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Danmarkshavn delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Dawson delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Dawson_Creek delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Denver delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Detroit delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Dominica delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Edmonton delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Eirunepe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/El_Salvador delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Ensenada delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Fort_Nelson delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Fort_Wayne delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Fortaleza delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Glace_Bay delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Godthab delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Goose_Bay delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Grand_Turk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Grenada delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guadeloupe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guatemala delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guayaquil delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Guyana delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Halifax delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Havana delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Hermosillo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Indianapolis delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Knox delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Marengo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Petersburg delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Tell_City delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Vevay delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Vincennes delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/Winamac delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indiana/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Indianapolis delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Inuvik delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Iqaluit delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Jamaica delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Jujuy delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Juneau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/Louisville delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/Monticello delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kentucky/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Knox_IN delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Kralendijk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/La_Paz delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Lima delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Los_Angeles delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Louisville delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Lower_Princes delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Maceio delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Managua delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Manaus delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Marigot delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Martinique delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Matamoros delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Mazatlan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Mendoza delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Menominee delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Merida delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Metlakatla delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Mexico_City delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Miquelon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Moncton delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Monterrey delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Montevideo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Montreal delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Montserrat delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nassau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/New_York delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nipigon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nome delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Noronha delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/Beulah delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/Center delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/New_Salem delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/North_Dakota/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Nuuk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Ojinaga delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Panama delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Pangnirtung delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Paramaribo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Phoenix delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Port-au-Prince delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Port_of_Spain delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Porto_Acre delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Porto_Velho delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Puerto_Rico delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Punta_Arenas delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rainy_River delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rankin_Inlet delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Recife delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Regina delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Resolute delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rio_Branco delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Rosario delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santa_Isabel delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santarem delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santiago delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Santo_Domingo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Sao_Paulo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Scoresbysund delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Shiprock delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Sitka delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Barthelemy delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Johns delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Kitts delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Lucia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Thomas delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/St_Vincent delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Swift_Current delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Tegucigalpa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Thule delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Thunder_Bay delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Tijuana delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Toronto delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Tortola delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Vancouver delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Virgin delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Whitehorse delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Winnipeg delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Yakutat delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/Yellowknife delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/America/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Casey delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Davis delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/DumontDUrville delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Macquarie delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Mawson delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/McMurdo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Palmer delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Rothera delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/South_Pole delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Syowa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Troll delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/Vostok delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Antarctica/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Arctic/Longyearbyen delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Arctic/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Arctic/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aden delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Almaty delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Amman delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Anadyr delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aqtau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Aqtobe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ashgabat delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ashkhabad delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Atyrau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Baghdad delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bahrain delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Baku delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bangkok delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Barnaul delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Beirut delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Bishkek delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Brunei delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Calcutta delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chita delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Choibalsan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chongqing delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Chungking delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Colombo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dacca delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Damascus delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dhaka delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dili delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dubai delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Dushanbe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Famagusta delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Gaza delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Harbin delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hebron delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ho_Chi_Minh delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hong_Kong delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Hovd delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Irkutsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Istanbul delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jakarta delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jayapura delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Jerusalem delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kabul delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kamchatka delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Karachi delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kashgar delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kathmandu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Katmandu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Khandyga delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kolkata delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Krasnoyarsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuala_Lumpur delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuching delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Kuwait delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Macao delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Macau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Magadan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Makassar delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Manila delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Muscat delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Nicosia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Novokuznetsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Novosibirsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Omsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Oral delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Phnom_Penh delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Pontianak delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Pyongyang delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qatar delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qostanay delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Qyzylorda delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Rangoon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Riyadh delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Saigon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Sakhalin delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Samarkand delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Seoul delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Shanghai delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Singapore delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Srednekolymsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Taipei delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tashkent delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tbilisi delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tehran delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tel_Aviv delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Thimbu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Thimphu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tokyo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Tomsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ujung_Pandang delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ulaanbaatar delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ulan_Bator delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Urumqi delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Ust-Nera delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Vientiane delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Vladivostok delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yakutsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yangon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yekaterinburg delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/Yerevan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Asia/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Azores delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Bermuda delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Canary delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Cape_Verde delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Faeroe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Faroe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Jan_Mayen delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Madeira delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Reykjavik delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/South_Georgia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/St_Helena delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/Stanley delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Atlantic/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/ACT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Adelaide delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Brisbane delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Broken_Hill delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Canberra delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Currie delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Darwin delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Eucla delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Hobart delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/LHI delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Lindeman delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Lord_Howe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Melbourne delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/NSW delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/North delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Perth delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Queensland delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/South delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Sydney delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Tasmania delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Victoria delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/West delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/Yancowinna delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Australia/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/Acre delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/DeNoronha delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/East delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/West delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Brazil/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/CET delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/CST6CDT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Atlantic delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Central delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Eastern delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Mountain delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Newfoundland delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Pacific delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Saskatchewan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/Yukon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Canada/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/Continental delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/EasterIsland delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Chile/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Cuba delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/EET delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/EST delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/EST5EDT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Egypt delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Eire delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+0 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+1 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+10 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+11 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+12 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+2 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+3 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+4 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+5 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+6 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+7 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+8 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT+9 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-0 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-1 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-10 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-11 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-12 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-13 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-14 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-2 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-3 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-4 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-5 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-6 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-7 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-8 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT-9 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/GMT0 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/Greenwich delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/UCT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/UTC delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/Universal delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/Zulu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Etc/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Amsterdam delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Andorra delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Astrakhan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Athens delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Belfast delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Belgrade delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Berlin delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Bratislava delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Brussels delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Bucharest delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Budapest delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Busingen delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Chisinau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Copenhagen delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Dublin delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Gibraltar delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Guernsey delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Helsinki delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Isle_of_Man delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Istanbul delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Jersey delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kaliningrad delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kiev delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kirov delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Kyiv delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Lisbon delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Ljubljana delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/London delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Luxembourg delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Madrid delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Malta delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Mariehamn delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Minsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Monaco delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Moscow delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Nicosia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Oslo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Paris delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Podgorica delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Prague delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Riga delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Rome delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Samara delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/San_Marino delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Sarajevo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Saratov delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Simferopol delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Skopje delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Sofia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Stockholm delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tallinn delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tirane delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Tiraspol delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Ulyanovsk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Uzhgorod delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vaduz delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vatican delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vienna delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Vilnius delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Volgograd delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Warsaw delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zagreb delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zaporozhye delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/Zurich delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Europe/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Factory delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GB delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GB-Eire delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT+0 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT-0 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/GMT0 delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Greenwich delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/HST delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Hongkong delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Iceland delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Antananarivo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Chagos delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Christmas delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Cocos delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Comoro delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Kerguelen delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mahe delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Maldives delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mauritius delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Mayotte delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/Reunion delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Indian/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Iran delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Israel delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Jamaica delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Japan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Kwajalein delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Libya delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/MET delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/MST delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/MST7MDT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/BajaNorte delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/BajaSur delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/General delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Mexico/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/NZ delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/NZ-CHAT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Navajo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/PRC delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/PST8PDT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Apia delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Auckland delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Bougainville delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Chatham delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Chuuk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Easter delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Efate delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Enderbury delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Fakaofo delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Fiji delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Funafuti delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Galapagos delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Gambier delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Guadalcanal delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Guam delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Honolulu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Johnston delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kanton delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kiritimati delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kosrae delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Kwajalein delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Majuro delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Marquesas delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Midway delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Nauru delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Niue delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Norfolk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Noumea delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pago_Pago delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Palau delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pitcairn delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Pohnpei delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Ponape delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Port_Moresby delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Rarotonga delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Saipan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Samoa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tahiti delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tarawa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Tongatapu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Truk delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Wake delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Wallis delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/Yap delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Pacific/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Poland delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Portugal delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/ROC delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/ROK delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Singapore delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Turkey delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/UCT delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Alaska delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Aleutian delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Arizona delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Central delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/East-Indiana delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Eastern delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Hawaii delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Indiana-Starke delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Michigan delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Mountain delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Pacific delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/Samoa delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/US/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/UTC delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Universal delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/W-SU delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/WET delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/Zulu delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/__init__.py delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/iso3166.tab delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/leapseconds delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/tzdata.zi delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/zone.tab delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/zone1970.tab delete mode 100644 venv/Lib/site-packages/tzdata/zoneinfo/zonenow.tab delete mode 100644 venv/Lib/site-packages/tzdata/zones delete mode 100644 venv/Lib/site-packages/urllib3-2.4.0.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/urllib3-2.4.0.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/urllib3-2.4.0.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/urllib3-2.4.0.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/urllib3-2.4.0.dist-info/licenses/LICENSE.txt delete mode 100644 venv/Lib/site-packages/urllib3/__init__.py delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/_base_connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/_collections.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/_request_methods.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/_version.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/connectionpool.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/fields.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/filepost.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/poolmanager.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/_base_connection.py delete mode 100644 venv/Lib/site-packages/urllib3/_collections.py delete mode 100644 venv/Lib/site-packages/urllib3/_request_methods.py delete mode 100644 venv/Lib/site-packages/urllib3/_version.py delete mode 100644 venv/Lib/site-packages/urllib3/connection.py delete mode 100644 venv/Lib/site-packages/urllib3/connectionpool.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/__init__.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/__pycache__/pyopenssl.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/__pycache__/socks.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/__init__.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/fetch.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/request.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/connection.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/fetch.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/request.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/emscripten/response.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/pyopenssl.py delete mode 100644 venv/Lib/site-packages/urllib3/contrib/socks.py delete mode 100644 venv/Lib/site-packages/urllib3/exceptions.py delete mode 100644 venv/Lib/site-packages/urllib3/fields.py delete mode 100644 venv/Lib/site-packages/urllib3/filepost.py delete mode 100644 venv/Lib/site-packages/urllib3/http2/__init__.py delete mode 100644 venv/Lib/site-packages/urllib3/http2/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/http2/__pycache__/connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/http2/__pycache__/probe.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/http2/connection.py delete mode 100644 venv/Lib/site-packages/urllib3/http2/probe.py delete mode 100644 venv/Lib/site-packages/urllib3/poolmanager.py delete mode 100644 venv/Lib/site-packages/urllib3/py.typed delete mode 100644 venv/Lib/site-packages/urllib3/response.py delete mode 100644 venv/Lib/site-packages/urllib3/util/__init__.py delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/connection.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/proxy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/request.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/retry.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/ssl_.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/ssltransport.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/timeout.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/url.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/util.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/__pycache__/wait.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/urllib3/util/connection.py delete mode 100644 venv/Lib/site-packages/urllib3/util/proxy.py delete mode 100644 venv/Lib/site-packages/urllib3/util/request.py delete mode 100644 venv/Lib/site-packages/urllib3/util/response.py delete mode 100644 venv/Lib/site-packages/urllib3/util/retry.py delete mode 100644 venv/Lib/site-packages/urllib3/util/ssl_.py delete mode 100644 venv/Lib/site-packages/urllib3/util/ssl_match_hostname.py delete mode 100644 venv/Lib/site-packages/urllib3/util/ssltransport.py delete mode 100644 venv/Lib/site-packages/urllib3/util/timeout.py delete mode 100644 venv/Lib/site-packages/urllib3/util/url.py delete mode 100644 venv/Lib/site-packages/urllib3/util/util.py delete mode 100644 venv/Lib/site-packages/urllib3/util/wait.py delete mode 100644 venv/Lib/site-packages/werkzeug-3.1.3.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/werkzeug-3.1.3.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/werkzeug-3.1.3.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/werkzeug-3.1.3.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/werkzeug-3.1.3.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/werkzeug/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/_internal.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/_reloader.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/formparser.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/http.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/local.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/security.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/serving.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/test.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/testapp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/urls.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/user_agent.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/__pycache__/wsgi.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/_internal.py delete mode 100644 venv/Lib/site-packages/werkzeug/_reloader.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/accept.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/auth.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/cache_control.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/csp.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/etag.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/file_storage.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/headers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/mixins.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/range.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/__pycache__/structures.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/accept.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/auth.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/cache_control.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/csp.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/etag.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/file_storage.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/headers.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/mixins.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/range.py delete mode 100644 venv/Lib/site-packages/werkzeug/datastructures/structures.py delete mode 100644 venv/Lib/site-packages/werkzeug/debug/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/debug/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/debug/__pycache__/console.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/debug/__pycache__/repr.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/debug/__pycache__/tbtools.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/debug/console.py delete mode 100644 venv/Lib/site-packages/werkzeug/debug/repr.py delete mode 100644 venv/Lib/site-packages/werkzeug/debug/shared/ICON_LICENSE.md delete mode 100644 venv/Lib/site-packages/werkzeug/debug/shared/console.png delete mode 100644 venv/Lib/site-packages/werkzeug/debug/shared/debugger.js delete mode 100644 venv/Lib/site-packages/werkzeug/debug/shared/less.png delete mode 100644 venv/Lib/site-packages/werkzeug/debug/shared/more.png delete mode 100644 venv/Lib/site-packages/werkzeug/debug/shared/style.css delete mode 100644 venv/Lib/site-packages/werkzeug/debug/tbtools.py delete mode 100644 venv/Lib/site-packages/werkzeug/exceptions.py delete mode 100644 venv/Lib/site-packages/werkzeug/formparser.py delete mode 100644 venv/Lib/site-packages/werkzeug/http.py delete mode 100644 venv/Lib/site-packages/werkzeug/local.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/dispatcher.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/http_proxy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/lint.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/profiler.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/proxy_fix.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/__pycache__/shared_data.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/dispatcher.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/http_proxy.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/lint.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/profiler.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/proxy_fix.py delete mode 100644 venv/Lib/site-packages/werkzeug/middleware/shared_data.py delete mode 100644 venv/Lib/site-packages/werkzeug/py.typed delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__pycache__/converters.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__pycache__/map.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__pycache__/matcher.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/routing/__pycache__/rules.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/routing/converters.py delete mode 100644 venv/Lib/site-packages/werkzeug/routing/exceptions.py delete mode 100644 venv/Lib/site-packages/werkzeug/routing/map.py delete mode 100644 venv/Lib/site-packages/werkzeug/routing/matcher.py delete mode 100644 venv/Lib/site-packages/werkzeug/routing/rules.py delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__pycache__/http.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__pycache__/multipart.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__pycache__/request.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/__pycache__/utils.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/http.py delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/multipart.py delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/request.py delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/response.py delete mode 100644 venv/Lib/site-packages/werkzeug/sansio/utils.py delete mode 100644 venv/Lib/site-packages/werkzeug/security.py delete mode 100644 venv/Lib/site-packages/werkzeug/serving.py delete mode 100644 venv/Lib/site-packages/werkzeug/test.py delete mode 100644 venv/Lib/site-packages/werkzeug/testapp.py delete mode 100644 venv/Lib/site-packages/werkzeug/urls.py delete mode 100644 venv/Lib/site-packages/werkzeug/user_agent.py delete mode 100644 venv/Lib/site-packages/werkzeug/utils.py delete mode 100644 venv/Lib/site-packages/werkzeug/wrappers/__init__.py delete mode 100644 venv/Lib/site-packages/werkzeug/wrappers/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/wrappers/__pycache__/request.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/wrappers/__pycache__/response.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/werkzeug/wrappers/request.py delete mode 100644 venv/Lib/site-packages/werkzeug/wrappers/response.py delete mode 100644 venv/Lib/site-packages/werkzeug/wsgi.py delete mode 100644 venv/Lib/site-packages/zope.interface-7.2-py3.10-nspkg.pth delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/INSTALLER delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/LICENSE.txt delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/METADATA delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/RECORD delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/WHEEL delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/namespace_packages.txt delete mode 100644 venv/Lib/site-packages/zope.interface-7.2.dist-info/top_level.txt delete mode 100644 venv/Lib/site-packages/zope/interface/__init__.py delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/_compat.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/_flatten.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/adapter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/advice.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/declarations.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/document.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/interface.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/interfaces.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/registry.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/ro.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/__pycache__/verify.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/_compat.py delete mode 100644 venv/Lib/site-packages/zope/interface/_flatten.py delete mode 100644 venv/Lib/site-packages/zope/interface/_zope_interface_coptimizations.c delete mode 100644 venv/Lib/site-packages/zope/interface/_zope_interface_coptimizations.cp310-win_amd64.pyd delete mode 100644 venv/Lib/site-packages/zope/interface/adapter.py delete mode 100644 venv/Lib/site-packages/zope/interface/advice.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/__init__.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/builtins.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/collections.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/idatetime.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/interfaces.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/io.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/mapping.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/numbers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/__pycache__/sequence.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/builtins.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/collections.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/idatetime.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/interfaces.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/io.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/mapping.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/numbers.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/sequence.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__init__.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/basemapping.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/test_builtins.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/test_collections.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/test_idatetime.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/test_import_interfaces.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/test_io.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/__pycache__/test_numbers.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/basemapping.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/test_builtins.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/test_collections.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/test_idatetime.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/test_import_interfaces.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/test_io.py delete mode 100644 venv/Lib/site-packages/zope/interface/common/tests/test_numbers.py delete mode 100644 venv/Lib/site-packages/zope/interface/declarations.py delete mode 100644 venv/Lib/site-packages/zope/interface/document.py delete mode 100644 venv/Lib/site-packages/zope/interface/exceptions.py delete mode 100644 venv/Lib/site-packages/zope/interface/interface.py delete mode 100644 venv/Lib/site-packages/zope/interface/interfaces.py delete mode 100644 venv/Lib/site-packages/zope/interface/registry.py delete mode 100644 venv/Lib/site-packages/zope/interface/ro.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__init__.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/__init__.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/advisory_testing.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/dummy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/idummy.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/m1.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/odd.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_adapter.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_advice.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_compile_flags.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_declarations.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_document.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_element.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_exceptions.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_interface.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_interfaces.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_odd_declarations.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_registry.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_ro.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_sorting.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/__pycache__/test_verify.cpython-310.pyc delete mode 100644 venv/Lib/site-packages/zope/interface/tests/advisory_testing.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/dummy.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/idummy.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/m1.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/odd.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_adapter.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_advice.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_compile_flags.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_declarations.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_document.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_element.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_exceptions.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_interface.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_interfaces.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_odd_declarations.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_registry.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_ro.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_sorting.py delete mode 100644 venv/Lib/site-packages/zope/interface/tests/test_verify.py delete mode 100644 venv/Lib/site-packages/zope/interface/verify.py delete mode 100644 venv/Scripts/Activate.ps1 delete mode 100644 venv/Scripts/activate delete mode 100644 venv/Scripts/activate.bat delete mode 100644 venv/Scripts/deactivate.bat delete mode 100644 venv/Scripts/docutils.exe delete mode 100644 venv/Scripts/dotenv.exe delete mode 100644 venv/Scripts/flask.exe delete mode 100644 venv/Scripts/gunicorn.exe delete mode 100644 venv/Scripts/normalizer.exe delete mode 100644 venv/Scripts/pip.exe delete mode 100644 venv/Scripts/pip3.10.exe delete mode 100644 venv/Scripts/pip3.exe delete mode 100644 venv/Scripts/python.exe delete mode 100644 venv/Scripts/pythonw.exe delete mode 100644 venv/Scripts/rst2html.exe delete mode 100644 venv/Scripts/rst2html4.exe delete mode 100644 venv/Scripts/rst2html5.exe delete mode 100644 venv/Scripts/rst2latex.exe delete mode 100644 venv/Scripts/rst2man.exe delete mode 100644 venv/Scripts/rst2odt.exe delete mode 100644 venv/Scripts/rst2pseudoxml.exe delete mode 100644 venv/Scripts/rst2s5.exe delete mode 100644 venv/Scripts/rst2xetex.exe delete mode 100644 venv/Scripts/rst2xml.exe delete mode 100644 venv/pyvenv.cfg diff --git a/.env b/.env deleted file mode 100644 index 6dcc5e5..0000000 --- a/.env +++ /dev/null @@ -1,12 +0,0 @@ -MONGO_HOST=mongodb -MONGO_PORT=27017 -MONGO_DB=mongo -MONGO_USER=admin -MONGO_PASS=3LnS985q7tR9 #IHxq1V8j3hwH -MONGO_AUTHSRC=admin - - -# This is the URL of the GESSI dashboard API. -BASE_GESSI_URL =http://host.docker.internal:8888/api #http://gessi-dashboard.essi.upc.edu:8888/api - -QUALITY_MODELS_DIR = ./QUALITY_MODELS diff --git a/API_calls/__pycache__/StudentDatafromLDRESTAPI.cpython-310.pyc b/API_calls/__pycache__/StudentDatafromLDRESTAPI.cpython-310.pyc deleted file mode 100644 index 03c7625b2626bb2638a748fbe9f5371962463020..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1765 zcmZ`(&2QT_6ep=q%eImR=(eo6hhIDHZdzk^J2;u}71P`iW(hf6Qa!5K@ z4G9>~9k;{IYk|18{7bs-)cpq=Fkp|eoOK&Ufsf?-(&LZsy|mf%5RBh`e0uS79idcPpS zxQ|-(ci;;>Z{fn<-|Kgx!%n~7jm}Pbg)Nwxi)5(f>tVn~M{xjCehNgPUm%V*Bu5Hg zk_=*@#!n>28NM-=2qRd{CCW)g;9utAsTaUFVM=gz%>s47f(e%@NJqg;q?c@{WH1ux zw3PJP!AYlo8tff+AC-2C+T*p>JB`#WE*!4=Zv6{=myp(CuG74iZCR$t0(nPYtT|2%-!Usoxd~xvE;7l?h2eWZHWrH@8->P&r z=(Ri7@nkSpd?E*ZHK#05?O4S+>RwyNtHYhWEc_8u!;5I`*8- z9E|xjOV$q%blVl$-W}SHg?@CQ?;so?EkoSXdq`3w8k%U#R%8Qq#r=O=K3e@-Y8&YS z@hc3(7955!?}oOvVU`JI0v-yzLOJ3HQVO-vHespyq?uH#-RUTK=MZ3%$gu`z{byfG0qy9bB)D|G0L2*v0Kt@1b%$& z=j!NcCv!6>$5K*72eH)NVxV40>u)h_yf!jSo1mqO)L$Hxuem?x6ABMDjb}5Sj8~;n zjv_4bjwg_Y{k#&!F?Hz{<7NTzc!WRYfv&GnN+S|qkX z>)-YB;kkb4=s)2;1l_Xx+m?x4L-!Gv_}C;aCP0B_`h)<_gT03v#-^cnF35dMz9+xC zH4odajcx4xX*%L#@YkvdU6aMeFil2${75pTAi3nKp_=-Vt4?L`L=~n6Ug`k0-dw686f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6w**(xTqIJKxa zrXW2(H#Np3wK%&ZzaYlP#kDLkC&n?rGd?*nC#N_jK0Y%qvm`!Vub}c4hfQvNN@-52 N9mud^CLqDW000_ZAGZJi diff --git a/API_calls/__pycache__/load_config_file.cpython-310.pyc b/API_calls/__pycache__/load_config_file.cpython-310.pyc deleted file mode 100644 index cc8bbadeb075791e5a1e1294866c046b449cb420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 847 zcmY*XL5tHs6rPz((`;>PaZd_D4qkGw;K@Z65!!WCmKL@wVknf*nY7U)6J{orE$wN& zco6@>_UK=lt0(`0Ao?b0VSVAv%zH2Iy>GrZqSI+1kUwAj<&Gfq(;9cB0mds(^#&G( z7*0`G?>NL@laypm=wvjc7%_)8V!|kEe4(MsT;2qa!|6j5Q`Tf2cs+(EC^-5B)zBy) z#v2zp5qXpvI!xx;xRUEq=5rfA2;f2<=m50Bq0ud7n2{aXB26~X*Y^D8eD7?rc5dkg z@9=v>5OXP_=*Gclf}SDu_%p`Hejh-Y3pkqVla>#1AtL7MCHLP=#v^|&@;F(PGP210 zSV*6*c&>dVN;&7MU!{cI$@uDWa5k9@#-rD7&)3KM@T^Yne^eqjSgsqTj-Q?c*myjj z3zp=IQP40%DB~`;=K0D{QSjW*DuJc|B_QFwy2`AG^wQ8cN%;>XJ3zqi=Ytp1E5)Un z77LN_>5!{WS`^cZ;n^xmr=?C(HMLdtKxQ_%UtF8x%K1M^*HUV^Z8v(v!%zOo`(T(> zb>W%5F8CaS;~;ht4rn!r9vn2ffmv+O4sY?sP8P4vD|#-umI+kxGp-{R>8Ro{@)rqE zx#!cC_hTut1G5L}stN(Au{gjIoNc#okIUAq$f%btgiIHHo7J#w_yPD7g{4g?k=6>1 zWD_=N-@9?4H%vm>3rTw;Lm523eMhBbm2#(trCwHzywgmuGUYEVG0Il+kcWG?>pW`z E1CvM70{{R3 diff --git a/API_calls/__pycache__/logger_setup.cpython-310.pyc b/API_calls/__pycache__/logger_setup.cpython-310.pyc deleted file mode 100644 index 88118074c4c62e5405dffe9343f7c35dcbd3419b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 799 zcmYjQL2KJE6qaPiNs}h)Ve74+OCTPlFm@~LSeK+-z)K-XH}G7HS1GPL#}1MlXlYLy zyX~@HkR11y#7^5`>@N%kdvZ4DgZK2__ntmIJ=uA)Sw|p0zwKP^SP1S?JqMMK z!7#*div0D8eO$)GCye+ObC}I4A8p@ec#PcYFQ`Yun+S>uHJ#{unv$^eW)OUy7ME3zajbcd9s>|3PltI7xK z4l8@lCD$ zXVWAu1gGkf(=?A`F80byr`LaRcCt$c!{gIk`sQdf91J1sk4C4XUD_QDCWG#g=k8J3 zE(@{^<)X_Z+sR`#_T%Mi+C%vxTk{^Enr~3Sp!aIHq^lFU)i54S)?H7sAX` zH{L}uxmaITZ-%}8@zI$#36Eb*baSi(k7h5|y=Y5b!y!_!ynqhF&^%ulYCFlMxl8z0jeLNLLb*!i>Vh;2x?M3}E+=vIU&7F)(NjA Y+QBSmMarLHh@|-&YN&>5a6pUv1-g~dng9R* diff --git a/API_calls/__pycache__/quality_model_config.cpython-310.pyc b/API_calls/__pycache__/quality_model_config.cpython-310.pyc deleted file mode 100644 index e0bd18935eb4259e153e109f7b6af7556b1fbf32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1137 zcmZuw&u`N(6t z-~KSZE=0J9IKB>@d}3rgppUtS)_6C2r)KM!Jb9 zQ;H$Z46qZ#x(>s>0O!aQ&|Lh>n~q>LUBySzs!!RIXu z0a%a8l$`{pq(?p>(&oWNn}coYMDTx z3*qnOzU|gA4jL1eJ$Q^&%QDph0&QI?BLw747~5FJ3OEI2>?{u0AwZw99@%Lf2Gd|l zPsl0x7L21Y+a})$1Z?DbPntONtozWjanWzo?eihNObbHQ?$^`xCxh2k8at?Vbs+~m zY2Q0t4K{nvKP35J;#6)2mx!1%Q0@Ens!*v*by2N#5FrD%LJr~_dNVw`RM$L&Hg#8X zohG?m>z>~Ne4(x+FgfEBFZzaZvaoSruzJt3kq=C=caGU$F2D5OBn^at#4m;&dhhr3 zz}&>cSLe(OmB2-nt5mt+xbV$!f#6aU%-nE}xoh#x%_o@oPWInza#KUZ!f4F|_{DY>m6K&GVNs;oEV2U$7}cjhN* zec@uJf1asa&P3!}LT1S%cQG?qxes=wgYGTC+$^KJh3+rqv-aIcM_OBXiKT0B&Z6AH zFrpo5?!q*t2HO$041V=Zw~ul+$g~fvGd@HK)LpL6U&vEuthtI-K?RdsuHi3Q(-V;n Jy&2qZ{{j3pB{cv5 diff --git a/API_calls/__pycache__/quality_model_loader.cpython-310.pyc b/API_calls/__pycache__/quality_model_loader.cpython-310.pyc deleted file mode 100644 index d5aa964a470eb655e422c3faf697da1c06c9ecde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1357 zcmZ`(O>f&a7$zynmgJAP?l7P^3_9#E1F2DLJ#|44py_ScB^U-6E(}Ga9ksM5k#sT_ z6tE)w1N#T|aes-|o%R<34A@KA4!pxC@TK0bhwqmpdc7FIsy`>UpW6ui<(T6|fVqUN z5+D>&%+bW1gySWd5R9lt{V!p7fo5qb+- z4KPAEJcQJK9cZ+{25s>bdcUq)8hs!e&mhyr!o4m8-FH>I zKswN^2Mm}|4VIg>0S#bYPQAKQck3R-lzc&^cZD9D{D-=~$Lp9r;GGy^P9AVQFrFEh z)+XE{;Jx~pi8hgWw#68k!6tTzZ^@=Zg9iPi9-85%yG8Dl(!^%?0v+tDth%gTo5=V( zymO>`CVs#sIPg^rx?oPAh^@2_Wr-75*I8N=OeS+7lWLXnT(4g)1!X*;xn!9ZGG}TW zH@3f~{G&=(n%yR9bu$;7g5#=iR0^SI;Bl64A;2gvj!Yc(xRjz~QUh8t&pA_P4I~#S zRmqX=E>9a)&76t>U?vKsl2& zDW9%%&ee3^gLca`;>f%WfU2yDQ`J(IST zmL()>y#>=YP$f(c98loW`tGwFJ-6XuGHmoTGq&p*e(11`p4vExQqE^L>shs&MC?xQ zUM&H(T`gx#V69zp6Cc{HCT(Z6OiSB_I2%2l*`OIPIEr-1Cc(Us2hE-E7nv6m54@U= z?1=kW*cbm>NB3`0-vf!GzSqZHOmN?8DEZ18;yw=X0LS=i5@H`X@;mv5Ja#)n91{60 txQ%?-bvJY}!8v?VZhV`PHrk^&+>FR3nD89tb;a3*8%pKmA?o5T`4_lTg@ynC diff --git a/__pycache__/app.cpython-310.pyc b/__pycache__/app.cpython-310.pyc deleted file mode 100644 index 5564c0f86ba67ed1a10fdb239bd3f942cb106baa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3598 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 diff --git a/config/__pycache__/__init__.cpython-310.pyc b/config/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 17473613607d143218218804327be0118c6b37ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 141 zcmd1j<>g`k0-v+886f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wj*(xTqIJKxa zrXW2(H#Np3wK%&ZzaYlP#kDLkCnh;RFD)}YCO$qhFS8^*Uaz3?7Kcr4eoARhsvXFr KVkRKL!Tyf|YD<}Q}7kExu*d$!})qb|$`@ZkJ$c>E}aw9!Dn|KKQC^t8Z59^mO^#?E< zah##3`o|H5J;_M!MP5!Ln){KD5%)xp5Kg)Og+^;U5FvOxLGPo4@--fUcO5*w2*E@6 zIOUa|>a;u?cE=`_MVwi>pAL5K`q2y^X>a=`Iq_)9G7*R|um19v@T0Wo| z;A)YmUPT#MyOYj}3CJ6Csul=lls)f@1@kr*Pzc2K;k>mdH{=qcP`qjI>3$sL0 z!rL8R*saoe8)o1Hc1kz=O%mcqzttveY^|g}Fc)Jn#Nb#BR~P7~sxI!PL03?jIa=UL zJa^T`v%^xX6Jb;eQCKca%wrRms>W=Tg0M?TrIkD0hZL|05)OWl^Z>;&dYShW#+2-F3u*wJ%wp>J?;SX4=9+Y$Pk zsiLMIz_E5!Xi~KUf33Q5)l+paHUL4Pzmz*yu1v}aU@3=>ZK)-sEyXAw|2J*;JePcu Vi5IT!x&bCcA>PJKZ>O=d{s%%{6=VPa diff --git a/config/__pycache__/logger_config.cpython-310.pyc b/config/__pycache__/logger_config.cpython-310.pyc deleted file mode 100644 index 2ede9d2e82ea43237df97575c9b24158655bbaa4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 801 zcmYjQL2KJE6qaPiNz*3lVe74+OCTPlu){8;9qW>`3wSA{?FOEU@gl`>=h#7#3oY$w zW4B%Q3zFmhlGtfGjQxedU{Cf2eW0iJeedb%=}F34ttJBb`E7f)Z6Wl-fcpX*dJaQA z2E`D=De|is`?$o!Cye+ObC}I)A8p@e_!PPIUl5N*H%~gwttpVFq>z5lV9AjpGwlH{>j%uy&vdwC@XhkqG@vd`o(WD@~ zJewwQAvjetPSZS&x!5f|-TvUk`SA`Nj*d=t=$pgwXgC5m7>`fJJG3_*o(+44p1VtF zpHHJARrH{YtycSM-pO(34PFmCZJQJ$*V47JHQJfxVjd~om_->&xsU~g<9e`nlErkG zB`S&11ONFih>RUYP6DYe1WXTnN)s zz5Xte$)q~0-U$1Hqr-FWEIfL3rdy{<@M!+BszqD!8a9!Nz!v2`THjryc>P Y8~gK|6)As)0ZH>88mNIAutA&r1%5%&CIA2c diff --git a/config/__pycache__/quality_model_config.cpython-310.pyc b/config/__pycache__/quality_model_config.cpython-310.pyc deleted file mode 100644 index bac435b79b8adee46bceffc79f18e388480e83f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1151 zcmZuw&rjPh6t>S_fi-z&5>Vh$A13a_kB^bvrPhRHCZ1nd4&AL$?X=v_|g+K=_kIZi^f^4R}%rO+>=atPl#wrAHI4?AZA4C%Lh6F|rA<{4WtY!mRV3-|AW1W6UW~?3mfE91u7u3Yz{)5$gXxa;o>7JK z%g7F0T}wOGMNBc@Rf9qZ0$+u0)*)Cj0qBB#W#48`sHNv@LNDkE`$&Z66Q7)VloY`$ zVipf6CHQ=TE&%u$nXq&3f^^9#!mb~0G&!_Q6$u{kJSxky*yV{RaO@Tw5LFON*S%5hv9+vNFcq(Bz25|C)?P8mKRuS4I)GL|8vP{z(&pPc~o z3G0%b#)&uaCiI+Kkni3o7_n{ggFwPsrVgbJeaG4_9UJAnT1B7p@ueG(stT8#)i?bQ zMrzY9cU3O?U1|2MD*Kz=wSy?@PucF@QQ}&H^2jwiB8_dV@^Ynx5E+DJavWwr&fw}$ zRrCOOYIiafN10h^-<$$~zA7b1ITaKSx>{;wZbDCE`Hm$+=jrJ12DHYz+`@k^sUZwh ze$H>vXTKkKdLB2=TuU=Z1y0H=jZ-@q<*q);5nPOpxo$YdyDRrRhQWmD`jq5tbOS{% zT>#Y~JN{BB*_ClBBtIOc@$etHLI1IlJW(3#a%GG*UrX&!Y7T*`LUL0=f+UrKr$x0W z4`g9EoVngn84M>=NjUx@Qy000kV!PoY{)cL?z~-TfxQJ7>qQKYF#OegO5ekHsFaa+ zRJsrQ4EoLY1KOhcDGWoZk&dvT@vE!bBlNpQrJZN2c0O95V!7IX>z?YyN~@p)E*NKW Q1^>}Xo`AIIytmZ+1G*b3ZU6uP diff --git a/config/__pycache__/settings.cpython-310.pyc b/config/__pycache__/settings.cpython-310.pyc deleted file mode 100644 index c6efd1bb3bee39dc0c5f2ad43ab04cc15c1dca38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 809 zcmZ9K&u-d45XN_nF^1TNBrR>!C&(p`s!}A>HX#8eNF<~f4z-XhCp+O!4U5(eQn}_a zqDaZH&(XKoYfruQ$RX{lDNWn8=G))wertPH!)-f9aO{6A4~jY=-&FGVurN8mh<>0j z!e~f5HESUqYo10Gr^3`&_jF1?hx84-Hy+3+Gs<`-Xkaq^6}h3fNA9yM&5Q@l%O#v) zCh}UsS(Zb#5?*5#vYoKa9AqcqeB#e1Tu8W(@H!~ZI^@L&3Sz`IAb(5PCKOPgft9e0 z`Wzh8BCOw%JImW(FEFS}(Ep$3&Uo70e)%2iCTH7Ju7x~cKI1V=W|->dK|Gl2JDACh z58Z0B(fR0~wrcgJ>(?4>>HNDUox`eI_mAtY+wi;XrX(_V+B!RK`6n&6<7LKt(&y}A zwRqlYcf9oLz4Gp!G?%{Gq0GY!Cb7?gXmG&;!B+0BTW_!Uyz08rULL7-J11`YXrBB1 z_DZR=pp^wZSkThk+7GVdfy=MOCA^z&Jy}A28H58K#g*jy+nZA3ku;W-3k|PBW~Nwt zIJ^)km6^VOH4MS`Wkx{6!x>0p8VLMV&rGUT_hIxw-JHNCBf?N(D#M7?RBkD*tC=u^z6y=JXG3&P$dpIi<5y$IrXIO#__ x)6dd;JLc>g`k0`XJ98BvT3439w^WB?RnZ~)?B2_TWe5XF$f7{!>v6vdRn9L1c%62+3j z8qA={R>fsxU}UOmV5VzmfM6RL++s2`h+;Cbh+;A}@Y7_yB^n=Gl2}v{U!0tgno^pR zS`?p>Sdw~6INmic1znIo-Xp)X2qAh)Fy1#aue2l;MJPBmIUiZ?N`@kKpi{xbFFR+e zn9$^!(h^7?;%I?2`O~7#|ncvc#Mipw6_+^!T*QoYZ0%r!283GcgG$pjS|N Zi^C>2ALL9sP%spOLW+f%g%Jcf7y*!RSwR2* diff --git a/database/__pycache__/__init__.cpython-310.pyc b/database/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index d233cfeb89bfcc7f2da8e551b08f7e8690d19dc1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143 zcmd1j<>g`k0-dw686f&Gh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wr*(xTqIJKxa zrXW2(H#Np3wK%&ZzaYlP#kDLkCnhDaBrz$mI5j3dJ~J<~BtBlRpz;=nO>TZlX-=vg M$gE-}Ai=@_00W61qW}N^ diff --git a/database/__pycache__/mongo_client.cpython-310.pyc b/database/__pycache__/mongo_client.cpython-310.pyc deleted file mode 100644 index 97e8dc8602c807738e9c93d71a18f31e840e19dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 565 zcmY*X%}N6?5Ki`|-PT{cc@RP`br0^*gGi~iB7#3q?PXag+s$-c+-yn`g^Cx^XYd_- z7++woo_qyQCR?!Wz)WT)nJ+V6!Z$XWNK5x?@BRZL^lgG=v31bZDm&UxL~)K74ly>q zm0QdXZRUgyMu5S7!=VcU#M->>Wiz2|`BGlrxC>ARiQ;Mwk7wr#O#jtm1JjA!3G_ zQBrXeOlRfhYEKO_u^HWSh4HWbMp>WEsw!dfhPYyqrGW&cvLcnjJfU#RR&5R|Y9_Fy h5*0+%-;yzWmfkVr^f8Byp<0?hvW~W~XM1?Z{sV-np2{!`?Ch=dGL%Bd5)@0xcvtatB<>|fHgr~ZY3LSH$_kRB?dSAM@9y%|CG{VBQo)JEtp$DA$#%r$J4 z0AYw>fhO)G0UP8VroF@JyowLHw!xqa54sR^-&FAu z=|Hz0F<}G=Ot=d&Kp?cxGT) z+i-_~_v#lW+D7KZ4r62n+t?+(BijxO8uYVzXolPF4!KiG6Pw{HbhNM1>bm;DM8@Ca zT_W8x@gp|Dk*{LV1q%X2Y|%cHB~D=7rZmsFOcsSqsx=jv-n?EFjEjV2lBc?m8CT=D zvHg{b4=Uj_y-U=3z9<9($93+gEDAjXkBdYU1sG-diHXA=m$E3i)PR;OGQrhF11Sp1 zRC1!b&uGJ{nNx89Op9D;xlXl8pyOGd=?o-^Gn}t8!Db-cgVCJ9#f<+3cj!C5O6Hqm zPP2VZ&O*ywai{esE%Vn|R(;Kcn=%Sqdbo2I} ziYcR-&Z*+lLnHP<9||!pH#WW$nbK*oDzCnBk-0F>(Z|;cnmGHf)4n_7OHrg$s4I9m zdfKk!f@;p*y6i1_!WW~yC55tWX9G>Neo6J6_1_m+Zi7sLNV==6?+mQ}0CQjiQ9N*I zTeK`8U+XQowt*^PfZ%`{m)3V*=IEsjkHcZ3=drO}*YjhOZS>s9NkoO1%{Q}ZHHrAW z-oIJ`Y`a>`n!sB7nB~i3eUy zQ})FDFYK%Tt)u(BsPBNpQQzz1E+)9|HI#he4RIfbcz|R4B?++)9QmF6L!P>wAr6WB u8r(*{?7AB|X(0rBRc?Ztk~Z3tINX@XCYbONMs_Xum77cD@OtBKQDPCe>$ECrpFEFpQ&oCrC0b;-H(wTu3Y~eskx`>(_4I z3%>e#ZTM3T;Vu(sxUl2FPBfG8b{7h7-<}Y8Gj|GakET}cn*X?Zm!xwx z$tyeGQDWZ08&~g5-F{3D|F zMu?nw?-{$0Y1Vdoegn@f5pvZ~St1%?9A_iJ8xO^fYIJ3mH1aLcX!T{*7c!3om|-W+ zWW&I(T2M9Et47%1Q73PVqI?S)nGz5XF^5FC!-`2IU6UdXbHUfQMVf0rN}&_Nn9^<{ zav61WWhA2BR<5+2hKbOXZYGmq9BL18qL;}XJ;#OW$f%!3S*oerb%uHO(iJ3$C(=&F zqqKKG-#MV4KQrmD>-Iw#Caq^KCO7nSrkb9%ahy~;3Y+$|ukujl%J>de9~r1Ck>XJg z11o~3PB+d%IQ(rG55>BanQZ#fE>ASWD=>Iz$H1iIX|qDR+K!`CXbVf)**2=$lHo{O z7(XTQJfse;t$xhI_`;3E&D7z`sRcrb-OnCco|)m0GBv8he#%%dJ%pbV7JIw)Str@m$8OSESA|JE(` zz0JV=-Ckn<_YNL%nyY@n6{)7xIr55-pNY#I?BE?_ZT`v>x z>M%k!B28!M%SAUzBa=jjS#AJC>L1N@BzddUm!_M@c@RyGbs7eifp-JnpJzaNIM{t} zObaSmLHEgo{KN*Rwld&PseBzWO{Q7vvZhJNoRasz*Zy)Gsl1aV{gsc6L1X<4*?sqc zaeo%f0KT`D`#pBWkV{4 z%z@}ixGiMZ6R+GsEkUdVz&8Mx!@mRsd2IL5%Xa@1c9c2%5|LH>q{*mF|3jTZ| z^ai+z^gE1A3BjSmrK+AkcB_<@fWOs4$1(A0T4grN3uc?9A*M2?q>M@ZB>2XCWs00R zF7@d-yoNGR_b+(`3&#L5jmY$$vLNahly?u!Y0fx%Vk1ed-PJP5HgE@;4&0b|e5t$# z8*2DqdKIGin$A0Iz=s*ErYVYUS+1z2rK>M=bggVkXdXyzsjJh&KpE#Y08i`LIE@}! z86<(sviu|j=Z-?40yJ*%D8Pjf43cGNDia-MGeBTo_iwoZ#tp>iO&;dqgHVaqu^`O6 zDIL(KI$7F{dMzdL9KB3Q(?PU_-mGnNsT_J(nmyuM8K^Qw-ZG#X#$v^QtxT=fNR2MC Ja~JCM{{TZsIu!r_ diff --git a/logic/factors_logic/__pycache__/factor_recalculation.cpython-310.pyc b/logic/factors_logic/__pycache__/factor_recalculation.cpython-310.pyc deleted file mode 100644 index 03900f1714e2dc808e09bf869ed215a1dec21661..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2708 zcmZ`*&yO5O74GWl?&0ZiJJTCK`k5yI{``S}Hnd!a)nu}sgjn7pJ@eI&!qszZS zD11!ieC9lIPsoy1^p}LW70C#rDPi8H?$WC~vCaI-W5Jd)aZ_^ODEBdC4M?vdr{pt- zg^%bdS^BKWT9psmHtRrk|KdXSkd8ik#p>&9gKe@)n7wSqDP0E2uju2T3Qh_3Z&VHO zK6{m2dFWJ)J?8{_u`RRXV0*FOiqJkVAIgt-r0()4PZXCbsy{wDO7c0sCI`_(l+)K->v5|i3J_f zPZn$O$I11@53i4ITz@OR^XASX*qJ73d>2o_Q~qGl*x?T{spQWGt}rRroz09U}usEsqor{@x;|M&e$lZlQ1^Eo;MeYkA8qI zuR^3w<=km4Nky2mwhbD>)U*yKS;6A6;Mx_ad*eIHxemA- zCo`@+W2~D=n&MD!oP$t!FcT&Y3-4-oJXGc@ucz8^%r3pteS9YXxz}C%SFFUdAjN zs|%=IgOLf?e6{=lN1ZxLiteHNmHXH^b@rS)+lTHlFc^Zq0X)HS$WcB`(q1IwSUWWyS2LT=va5U*)MKm$3;n_Q zoiib<1FvD_S#Lc>EloODNvqz8-2{s842BMkuo+ulXhVMIt$i$|A~?jK*al zRi@@(+Y2ltYmPaX&t|~6jCPYFE|Qe*MoGb<-D94mcNJ&x*>pL>dxMmfB?#eFob@6s z$|x%kk8Xg-rht=ftc(_3a+F?sMh2t)|N8qsGB9Ot$zT(TC4*o|6!LIFRwQ5`52o`c zd6_8ezJakO=cvHezqpL)pP>KKpm)<*ylyauY^^S;mjPEd>hPo`!W4FB|MG+U z^D+J&F>X2MVzhufi*NdbjJh>*e7D}E2CTuVjrC_n`8LFb?F@`8l<>6t_#4BIO+bb$ zarss5rt^^lc(@E%dqVc>P3bBrN8(N6^^7EIW@z3_dBGpd#4Vd>lX3Ug+s@*(uguW% z^^4#bg^*rbY{I;)0g_Zit8c*3xYcmrb8wzU{rq8M#wh2mn$Sq65yz@T!_ z(tf7+RO%p^&3M5y#a{?{$5QR~EyI(D$StHjVO4b^-W8}_YfmcmH8}hBM&*RcYRSWR-D$9Yu5 zIhNiqPB@_v!b8~^rbV1Z58`Z$^GCDa5F2 z_tE{kXmK(xe28}md|PfJTt+M4!AirgqBY=G(YjcMa~om>=sB=w%ly&x` z!(YYxkOJs5=}e(2TMuzMI^<01ku;+e$)2hV7Ucw`!xW=uYWLp2+@o{Aj9|j}^Gekz zNH9H$QPmDUYN}x;c%~}3GPZ&j`k*o{!E#BqhJ@zhES9bK0jBW?OBaI2BSMd*w?}Tw z_^LB?iR}bG1ywhww}RQhouF!O1+yC}e=9gUz7t5RDbEhVETL)Hl&$w~dRaC9^*3>u zA{Ok%?C^lZ6jk$QDG4?|-`Tvqvw3IGrfc9fT?ZmtB_&7D0Hia`Dct}mv=Dd@M#eP3 zVLwk9ON-I0+F7`$8VaN=WqHh#!wAL4Otuq>L5!~Pfh~Jjc^@nHc0nlZY4fmB=seOp z%k?!*p*d;;qp~hA%qw5fFN-N`?m~ld#-&2gV3DepLJj4wS&)a+RGiB=9je!p24T`F z;jKYdW+}&yxO5eqnq*l3J}%8FEu{$^Pa&f~5%fW6!`7Th6AVcwE=yb>X;T6il-3bR z3+atZ6|34jI7e;egri7H5m!0ky#}c4zm6Jm0%5m@<1CAmV_|33P?blaH$_sE$0hA4 zD?WadGOlurNFwzj^k<#5j45Z~3@H&Mgoh3vml=j`s{)K3hMkl}XULQ-#>WU35H4g~ z+F5*nv#>L}PUR)+&QKQ}WF)y4`ZLTmZJ(}yGa=wzZ{Vq@9$!EkCSr$i`|=W@&2qlql}EwWS>Fh^ejtXFf91ybYFLM-*62_?-@$Ap*ydP=e?e< zG^U|juUx}=X_(gE#w*8jbOS!Gp@zPoJI{@tk}SY<{<6BDH{i@m!}4Cxt8n?CGsT)) z!NaR;G=QUNf1919iY2W+di~-6nT$kSj{> YeggF{&hTZ`d6@dI^feWqitxPo4=|Z^?EnA( diff --git a/logic/indicators_logic/__pycache__/indicator_event_mapping.cpython-310.pyc b/logic/indicators_logic/__pycache__/indicator_event_mapping.cpython-310.pyc deleted file mode 100644 index 6162ea5593e13df193560d78babceeadea2b16d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2175 zcmZ`)TW=gS6t+E{+1be^jZzS8)WS&6mIb;31QM4JL6aa=Ds5?6szzH4leKpY4najKw)#-}Q z0yYCH74Eb#tFhT9c*AFN>!^NaA1tFf*5_p_&ZAyGP7}2gWd-AD)GkuS1uQOneea7K z*Y7@vzPh!#c4IwSy?#gg?Ih*hSZ!%faMc%i3ma3@$DGTw6=?D$SlI&fzu*y0(1<{D z6e{5i%whDY^J8yBOS+04-XFQ8yNAcfe8p=pCd?gU5%w0CSGwC+T*K zH>#AL-QkrL`-ORlw~<&bDu;YWBWUAv2=SqK%j*+;n+|u90xuZPu9aZn6 ze1;-b+4&YD^OpXo`T*s4fXZs=lpd?H;0JOZS-XyS3^KxIme75~0*WZwg@}}7{Xg^f zklYZTMXf!gGhmOop<^co?T?G2kqG#CK%a7DX1SEgm+yqUds=5-!6e zXGtqog$PXqWCL~^_scL2VL^q1L~X&QLUK^xDFY4rljRD;Le~UOW5wCpHqVvz+Hngk z>B@j7oh>Cb&Et&gO1ltQKaI5yKjNK2?C2TBWlJPol@z(gV(9i&`|3x)4WH+&f+cz9 z0Ka~KKifAf7<%1U#93qCgUL-jnaR4ZDV!qLu2f)22U5jCNrM+eT_B#WB$6c^7&r-_ zbK7YVD;<0jr+vOAL?P;dp!O6~H$}!x+BM#h;;dQ0ZB5f8=h}fK?QWZ`+7aaBJn0<~_-UY<4@~_2w#o0MY=G?>r>jo=v$i zVNfcbOy(YQ#$*peI^k8ci>;2&s-P1b>dc(dnP@>70j;^8eN#q;E0$x|`UwyYn0R>d zknwhsCx$jhbT-Zcjvphnp>jh&4Md^_okl0B2?3Fb`#Lmv4!RD2f9Q{Ji3KU~9vY*c zNDnf~M)w&OFN02``F&&1SU-n`S2hj!qnJg2ys?xP ztvHp-FnGR4m^?bb?+8=hbS2*ABJS}2$9nYQ+x>G6V5RO!qf%J&v_Wws{kvk2qRA^ zu*n&IY1y<6SCT1+;S};!do6{szd5;?pg=+ud=b@T!y3@R;i9ZNx_Y=%*KEmvyapl) zU7ef>0uIMFbeJTWfesa}(#s-I6za4mE}rs)G~D5jBPi5SFZ&oaOT%SC2_&_7y}!h# zAh=nt>WeH^@n$S}<3u>7fGh@mrd8zaq|=aGDJU~in9SA=6i-b}r9T2`%^rhiLuR?| ZFM-ecDPJ~Tmxi%5RKp9-;^q0de*xCMF*5)F diff --git a/logic/indicators_logic/__pycache__/indicator_recalculation.cpython-310.pyc b/logic/indicators_logic/__pycache__/indicator_recalculation.cpython-310.pyc deleted file mode 100644 index d11d5f18dbc15cdaa28958c197adb9d1c3dd8e93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2216 zcmaJ@%WoS+7@x;_y>@IjP11^n*9uxCmQX;56AA&^R0shE=cV?V` zwU&TH;vx0Gfm2nfIrd+gD+kmA5)!vc2!6BcCT&4XG~;g`-(!FC`@TuuZZ`?q@8W}7 z?{^6K)lHsk0VeOEYc~iYXiA23hf*iAlnwa~hujjLs2$NAPx!JX>e3ehdPCL+foO`k zBX1`Ve4BLJ4`GFLsXebvu4FICMADBS_LS7))L^F*OVjJ;X)60B$+N9KcPg`1!>@;a z1zmrJ!62f7+$HzeA)WGq-=~5VG@-|I>J^^gW1`LpFQ(h1;9t)6L@lPmzr)-KwJJEy z)i00%bEjg0D1*sXGeo;4jY{Oc49zVWrje1_goCJ$aKrs59m`eS4F@V8hM(kFoNrzZ z2iS?iIN6t3ICRSWwbIZesMPeD^($$s%eH<){AKGh+mX&<KztvpDwk}GqvC%Z@6fyDBCA)dO{BDT&b#iV1u!~l4h*3r!M{s^nG-PfWAfv zE^5lrJ@i_^?vrD(Np3FhvZ+6<7j?*skb`N%QKD!ZgRq4M$uFfEq`*nH=WjO)uDik! zgx+U@34Y9`&7vvz9#fYMD0N7U=f>yBbWT9JOGND+pSH5kamvT3UqoF5N0ojfCdX`( zfQ;>;t!_fIUFuWOynxj`t_ET*b{1zVOJv$MHRD%voCcA9B;S((MN$PvLE)9wI);n3 z=o}H8exekSV6QWQ3fUu^F^-4Y*jg178t9xD1At)E673sq-A}vLjXJKM=*v~U<5;F$jW{j^+>5BN< z*gCRn2=dwb zOljgp`|;`{+O_k~+UtWMCyhaJtlUP|OBiBOkemLL8sKn9e`dGw^<{=2<7$I6j|?)B zt-WFCLAhKFXQ64E>uI7*9|&!1V*aPIy+kIL+zK!|Eof`&X^w2s8xS6A*m@PGwtiI| zVrZlN@$P@dyNIo);{5^fULa4zTLsP33pi=%@By{$%J7?&qtn3EOE~f&x_TMIQ|??! zm1%`v?JRxk;AtRz=oGcIU`yl%L8>qT1Rv0?$|;{Y-B&L{rE=toj4EMjtj98wUyanp zN6xB4pMA4TCKvw?r^hN2{{Xy*S0{_tv%M@o$ifqHge#BeO4m~k8s)AMwa-zrSJsc6 zsw4W&p>L!YWjy4$q1#K{&D}GnZq+&GyD>ohbFMYQaAF0%ZIzQ*9agWnqk$QZdd{qByD5i~W%&pu9*1we zBpc+`cj?tTu+4)W@I$glQGxp^^eS-A{tLv5*wb%e@O+PYbe^|p6Mrqr{_^S`ZSjE5 z(+&;zdHNh(pbKn)hHM$<=6S%>JI?YY4Bf`gYh}$}JE_jIM_}#Q=X&T~yb>0BPDCbh zQLmMYy?&aY8kBEURrWc)TD=bYwgwbZSvf4paypc>3D$?X7^iZ>rLT7Xdb9{Wg}oI1 E19`7ftN;K2 diff --git a/logic/indicators_logic/__pycache__/store_indicator_mongo.cpython-310.pyc b/logic/indicators_logic/__pycache__/store_indicator_mongo.cpython-310.pyc deleted file mode 100644 index 31be92872e0c54c04be615e37208867e1139ec14..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2053 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 SCCW^0A$?5!on2w?t^Nnuv?>_@ diff --git a/logic/metrics_logic/__pycache__/metric_placeholder.cpython-311.pyc b/logic/metrics_logic/__pycache__/metric_placeholder.cpython-311.pyc deleted file mode 100644 index 8eb41ba637454e1fe48ea4d27705615793d78a00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2265 zcmb7F+e;i*7(Zt&*`4*WW=%Dk1df-YTiUImX%P`asBH+9kg_c$!LXgooYgV2Gut_{ zvC4{4Qo4cD}Qmp zs|K#h^AB(#8Qz_*09KHHXe|#sru3t{4(pp-MznX)9QJD?gr@ejqdZ=R-J3NALoyZq ztb@d6O$wtV>OtobQ>LXay(xx;tHz_s7t6{H;r6aSEOy|X=1z-esayWu=qJ0t~c z)wT}b&HVuyMfKz4QB6EttL=!UW}!*qn*Nm~yw8Eq5ta*iG$$?M|8~}!XU5@9bMl;$ zm)5wIj zH!Ubwg_o01-IyfIhgjWTv|TrwAmX5(S^gw!(0wvZf!HA?O%DkiT53=61MxHv1{#14H_!w(Pz)+_t@sBm9YQXxE?am}1fN4(czj>j5%4*-5n7;mG71@V*>6~iB? O2Ay5Fql}J&Q2952a~|{n diff --git a/logic/metrics_logic/__pycache__/metric_recalculation.cpython-310.pyc b/logic/metrics_logic/__pycache__/metric_recalculation.cpython-310.pyc deleted file mode 100644 index 878d5495fc149e8bda0449836c82c7d76e01d48c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4576 zcmbW5TaVku6~{TeNEAg~SG)GEV~0tdtd%Ak_ug)7BY~Y129iw?J1rn=D$p8AW=x98 zkg^kH^t1uu6zD_I$JW5^OVKe1!TT>HiERt>QW;P%U^koH=tp=Qn3I zsnr~fe!(yAHlEY8f2xl)L8Y(bN&f-CHO?ZfM{hl1vEI{Tqh~PsHX<{&dX`F?Q7JC> z%CX(E)wdN@VyEY*bSbLFZqHTea#V}!y}C-bpEal(2X zUI{k26KwG+9v4rIv!TQ5yz!aYJF_aKl4fvrQQG2dly37)zQH@6vEB}6x3uooSD1@- z(AD#eDDip!qiG;M>1RPaiTo_c&x-(wLC{z7ZW8f8r2TMQ=yh4Xk!Fbq`f-qnaL^Y) zI*l?kwj-wFew>U)$)d$!A{I({Gq~?ZQ?%YkW;~62G*grdhPNA56G6`}w&8D2Hjr};tD_P*jMY1GN zUyKJP&3*B!<6Xsb9Z%{pP0O?o*|9FM&D+`uJsqGuqtB49Skzyd+E9+}4iG z6YWnLx1<3{dF5?Vz7?x8++=2cmh72c8#>a`ykSG14bLdzAtAuH%lrxr3t8d8^*WU_K( z&0SUAk?yiwy6Kc}&TGi8@-3<{wlY`R(mm2uZi%0fHMD>Bk)hhd_@pLlXit}}Ec5N( zmod&An9jM`yN-w7^(3B5v*2ZKxv!o-=AN<(q`Yv#V<}}-R zFBqsX!8p8|2RCm1dfD@CZjvoLuI|zx$o8&Ynl-v=M2nGJ-JNakdSol!gD|`61s`XD z82eE_CsP`)MFxxxVn@^s)Zwr;qjdd{$N8{n(%EdoznCgMIH`n2Y+& zUOh-We>4)o$cNi_g}bCLd$8w>20IL?C%A`~CEn$|%QO2uiExb)? zAUEKWxdp8_%`G0>nT~`-%H;>X7-QI?L?a+)>ekihPKTsMoZEN&G*I0+1z%{JbCbL| zZ>(*k^3&>KXZmR-^2%y8b8DiC%?Xw#H!wZnp~o*Z@e{lr-@LwmNc)iy z+052GJeQbloYmW`$(lx!nTE++<``|ZV~C$Y5er;YO}|AOYKRtG(dI9THi{@j7&g_! zMh5n9T{3v0QFtQZ8o36C&dQrjZmsxJQamZ61u#eP$I2{F$0F?`Vnaz9{3pC&bvgnzLfkf^f73 zXNy@WLeclOtgqIjp8lQh%o}P2&&kFzALD9{E3&TU+sxXsBAe)!^s4+B(&OhB%-aC# zG}(}hGuf0Dzo3{$$K|uL-~4apDSEsT;Uroi@6tF~2jTi@+AY|3FzdWOzBf)DjKNVH zS{@x?-tMfu3q0HlCllgBVZbx@O{GEpv+s#E>_}{o=#bcin6<92PEe2B25LHiOVE@K;nla zegu)*%SFx0i$g`xQT&)R2#|&NDe0bB&Y-X+ioy`^`SCAMm|lah0k<|Yfi%ykGn;kr z;176v-ZT~L9K&ICv#A4m%rr@}gmQUxOz3K z$nvoxs|qYGda5E6TZKlU_Jt;03by7oS>rA+SjQVUe5lDff~|Kmm)9Q>S`|*EnT|#X z3bWcn?YMrT9kDOiLj;QVbn!>t09cIU25-{1QQzdPKkM^m)?A^b4YU}1gV3Vp+))VH zED$6cx3tf-&)HDtTl~ytwlr^`{dp^E$<`6$XYZNfuRs{m^Tt@G-u}Nny4$l`3TU?` z!65XbR|Yt#_u-Q&r1K`pWN|PeP(xJb3l1;4AF8v`ONLOKj^U`2K!6VMoj?>YdjdAI z&N@p9v-5TpMrP+#DE3_e*Ha17dE>uAsC}8M+KFk@YOvsEf(npwLlaU`w$QCq`!rraPAodb4$9_ zK{nGM>eX3YH+2Mc21=R3bX{kquaU*p|4RRESD=I3(l@T21R$y#x=*ouae3&hO6l@|dk5(X`mae| z#+cMyy@I>M+r{O=?yLJqzpo4{H+eY7U@@6cfwNHd^g1f5lJ2kz=7mf3YySaVg~B}m diff --git a/logic/metrics_logic/__pycache__/metric_recalculation.cpython-311.pyc b/logic/metrics_logic/__pycache__/metric_recalculation.cpython-311.pyc deleted file mode 100644 index f30792b5cd566f619313e98cd59d406b5940305e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6628 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 JCLqDW005sK9-IIG diff --git a/utils/__pycache__/evaluation_test.cpython-310.pyc b/utils/__pycache__/evaluation_test.cpython-310.pyc deleted file mode 100644 index 49b8ea5297bbe7a6f1ff569a89477a4cb2584a7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3182 zcma)8-EZ4Q66aDMre(>NW%)~v6XmOk6I)4|wr*V8sVd1i19p>I-js6>@=k93}gab(welVV9L%yHju}xX*&nGV60g)b{_JuE<0TzPsgtcfFpkOb-QXr?TbM`VUpRr*UamBe~g(;YLa~?0eWl+TAn~OZd zC*P`Y301ss%-}L=ce1`np!8<&^sKCdV$2F4gV)4x@(We`it99=f-f+Q_izorz!E?I7dqFYe;vIi%!L=~PfVmR6KG4g&WnNe zeT2U?#J|UDqkIDXn*pDT{8GSY^AsPFh|iX(z&392%Zm!h({LYG`4zk`Sj9tgC?Cq( z73(Xz0u{RoRf@{Zx%F60LWW7CHiTQ~g%Wz-#V*-zQ=z9LxcdpYho3B=wUwGa#Ew0<> z3A5qqW{2bVdKZO$WS?l8M#FQ&2U^uHG#tCz^Dwg3n~u<3ug9_D`SZV_^U$zYRDW`y z3f=lMmf;brftQzt)kBKC95N$DX2Uoep81n4^mKel(WI$CCK(sKURSrAR?Ft1iN&nt7+gQ<8J6k2vK@|=RQNNEw&S>XN$QWr{#ZEQVZ(#;VB)EZ0^){^-TtC2ee>rV zw{BTZ!?4

ur3ze*4ZkOohwihTDGb7=rr~-0%$Db$X(K{bWrpeyhK*T9hj+{>k*( zMf~1F(J?IDqhSE1j(sb?!K<+buG z`2%~+xU#7HRXtJNrsW=@JYvH$osKRKzSMo?r#3Cq^<-jf|4~MlRPu^AM=w9&Hk>X(N@l`K zlhcXOfs6-dDv3Zm%qww0g0;bVN0%Gr@9!*E%#yK~lMlI=cdA&F-dOWwZDL7kB_mS~ zmgxb>a3lNKXhVyhQ|!68QS2ALk!kD}oo3N%<6y(37?LT9d2-NK|9?*6q6|CS>JvIY z4Cv5-Ob=>nST@7*3ghZQc|kIi`j=1Bj5bQr96Bhj?83O$7HDuPDo8YCFA?&91l`<< zkQoDGQO)_PZj48 zhC<0D#w0!YKjU{poVFR4Hu9efltSLaeQ+aY!-)^pG9itq?RA=Fi)^X6gk!yFS}4*| zn;&Xr9Y%VQk*Z7O$GbX_x7^Y}*g~sR=}qC-d(|h@K}anoC2%S75p^y-Y+d1`m?DJ8 zO4wMJni{ngF)gKWYL$D`6;b$_uFI;?bx6_zmN)8xSevP{^-dExYLt)>2LR8b+=L;fzE|4&&*HPYvq0Yp#HQ< z5fAkJ@?)3{rlJ-bbX_^^C%VGyc#sOS#Ct_uVq&EK!GzKC+H@%eZ6b4O#~|4VnmMTa zxgV!wGW@vNp&Ly0JwHZUB8qZ9rs-Y`o95t-gjAS%I>)9sFEQz;=Y(-aETWW#RFutR z;U|LvbYUz?U>I+jvR%_Oej_`duWeGQ^(@?$SBCp%dT1=qH2S7h`OUIy@J_Qd%d&JV9n)A+O|f)B zQ>B!SC1XjZ#o~!Lqi;+jy+(R1k!R-;`B*{K64IN-a!mbiO3ksHnvWL<6DPluYK{=3.7 -License-File: LICENSE.txt -Requires-Dist: zope.interface -Requires-Dist: pytz - -.. image:: https://github.com/zopefoundation/DateTime/workflows/tests/badge.svg - :target: https://github.com/zopefoundation/DateTime/actions?query=workflow%3Atests - :alt: CI status - -.. image:: https://img.shields.io/pypi/v/DateTime.svg - :target: https://pypi.org/project/DateTime/ - :alt: Current version on PyPI - -.. image:: https://img.shields.io/pypi/pyversions/DateTime.svg - :target: https://pypi.org/project/DateTime/ - :alt: Supported Python versions - - -DateTime -======== - -This package provides a DateTime data type, as known from Zope. - -Unless you need to communicate with Zope APIs, you're probably better -off using Python's built-in datetime module. - -For further documentation, please have a look at `src/DateTime/DateTime.txt`. - - -.. contents:: - -The DateTime package -==================== - -Encapsulation of date/time values. - - -Function Timezones() --------------------- - -Returns the list of recognized timezone names: - - >>> from DateTime import Timezones - >>> zones = set(Timezones()) - -Almost all of the standard pytz timezones are included, with the exception -of some commonly-used but ambiguous abbreviations, where historical Zope -usage conflicts with the name used by pytz: - - >>> import pytz - >>> [x for x in pytz.all_timezones if x not in zones] - ['CET', 'EET', 'EST', 'MET', 'MST', 'WET'] - -Class DateTime --------------- - -DateTime objects represent instants in time and provide interfaces for -controlling its representation without affecting the absolute value of -the object. - -DateTime objects may be created from a wide variety of string or -numeric data, or may be computed from other DateTime objects. -DateTimes support the ability to convert their representations to many -major timezones, as well as the ability to create a DateTime object -in the context of a given timezone. - -DateTime objects provide partial numerical behavior: - -* Two date-time objects can be subtracted to obtain a time, in days - between the two. - -* A date-time object and a positive or negative number may be added to - obtain a new date-time object that is the given number of days later - than the input date-time object. - -* A positive or negative number and a date-time object may be added to - obtain a new date-time object that is the given number of days later - than the input date-time object. - -* A positive or negative number may be subtracted from a date-time - object to obtain a new date-time object that is the given number of - days earlier than the input date-time object. - -DateTime objects may be converted to integer, long, or float numbers -of days since January 1, 1901, using the standard int, long, and float -functions (Compatibility Note: int, long and float return the number -of days since 1901 in GMT rather than local machine timezone). -DateTime objects also provide access to their value in a float format -usable with the Python time module, provided that the value of the -object falls in the range of the epoch-based time module. - -A DateTime object should be considered immutable; all conversion and numeric -operations return a new DateTime object rather than modify the current object. - -A DateTime object always maintains its value as an absolute UTC time, -and is represented in the context of some timezone based on the -arguments used to create the object. A DateTime object's methods -return values based on the timezone context. - -Note that in all cases the local machine timezone is used for -representation if no timezone is specified. - -Constructor for DateTime ------------------------- - -DateTime() returns a new date-time object. DateTimes may be created -with from zero to seven arguments: - -* If the function is called with no arguments, then the current date/ - time is returned, represented in the timezone of the local machine. - -* If the function is invoked with a single string argument which is a - recognized timezone name, an object representing the current time is - returned, represented in the specified timezone. - -* If the function is invoked with a single string argument - representing a valid date/time, an object representing that date/ - time will be returned. - - As a general rule, any date-time representation that is recognized - and unambiguous to a resident of North America is acceptable. (The - reason for this qualification is that in North America, a date like: - 2/1/1994 is interpreted as February 1, 1994, while in some parts of - the world, it is interpreted as January 2, 1994.) A date/ time - string consists of two components, a date component and an optional - time component, separated by one or more spaces. If the time - component is omitted, 12:00am is assumed. - - Any recognized timezone name specified as the final element of the - date/time string will be used for computing the date/time value. - (If you create a DateTime with the string, - "Mar 9, 1997 1:45pm US/Pacific", the value will essentially be the - same as if you had captured time.time() at the specified date and - time on a machine in that timezone). If no timezone is passed, then - the timezone configured on the local machine will be used, **except** - that if the date format matches ISO 8601 ('YYYY-MM-DD'), the instance - will use UTC / GMT+0 as the timezone. - - o Returns current date/time, represented in US/Eastern: - - >>> from DateTime import DateTime - >>> e = DateTime('US/Eastern') - >>> e.timezone() - 'US/Eastern' - - o Returns specified time, represented in local machine zone: - - >>> x = DateTime('1997/3/9 1:45pm') - >>> x.parts() # doctest: +ELLIPSIS - (1997, 3, 9, 13, 45, ...) - - o Specified time in local machine zone, verbose format: - - >>> y = DateTime('Mar 9, 1997 13:45:00') - >>> y.parts() # doctest: +ELLIPSIS - (1997, 3, 9, 13, 45, ...) - >>> y == x - True - - o Specified time in UTC via ISO 8601 rule: - - >>> z = DateTime('2014-03-24') - >>> z.parts() # doctest: +ELLIPSIS - (2014, 3, 24, 0, 0, ...) - >>> z.timezone() - 'GMT+0' - - The date component consists of year, month, and day values. The - year value must be a one-, two-, or four-digit integer. If a one- - or two-digit year is used, the year is assumed to be in the - twentieth century. The month may an integer, from 1 to 12, a month - name, or a month abbreviation, where a period may optionally follow - the abbreviation. The day must be an integer from 1 to the number of - days in the month. The year, month, and day values may be separated - by periods, hyphens, forward slashes, or spaces. Extra spaces are - permitted around the delimiters. Year, month, and day values may be - given in any order as long as it is possible to distinguish the - components. If all three components are numbers that are less than - 13, then a month-day-year ordering is assumed. - - The time component consists of hour, minute, and second values - separated by colons. The hour value must be an integer between 0 - and 23 inclusively. The minute value must be an integer between 0 - and 59 inclusively. The second value may be an integer value - between 0 and 59.999 inclusively. The second value or both the - minute and second values may be omitted. The time may be followed - by am or pm in upper or lower case, in which case a 12-hour clock is - assumed. - -* If the DateTime function is invoked with a single numeric argument, - the number is assumed to be either a floating point value such as - that returned by time.time(), or a number of days after January 1, - 1901 00:00:00 UTC. - - A DateTime object is returned that represents either the GMT value - of the time.time() float represented in the local machine's - timezone, or that number of days after January 1, 1901. Note that - the number of days after 1901 need to be expressed from the - viewpoint of the local machine's timezone. A negative argument will - yield a date-time value before 1901. - -* If the function is invoked with two numeric arguments, then the - first is taken to be an integer year and the second argument is - taken to be an offset in days from the beginning of the year, in the - context of the local machine timezone. The date-time value returned - is the given offset number of days from the beginning of the given - year, represented in the timezone of the local machine. The offset - may be positive or negative. Two-digit years are assumed to be in - the twentieth century. - -* If the function is invoked with two arguments, the first a float - representing a number of seconds past the epoch in GMT (such as - those returned by time.time()) and the second a string naming a - recognized timezone, a DateTime with a value of that GMT time will - be returned, represented in the given timezone. - - >>> import time - >>> t = time.time() - - Time t represented as US/Eastern: - - >>> now_east = DateTime(t, 'US/Eastern') - - Time t represented as US/Pacific: - - >>> now_west = DateTime(t, 'US/Pacific') - - Only their representations are different: - - >>> now_east.equalTo(now_west) - True - -* If the function is invoked with three or more numeric arguments, - then the first is taken to be an integer year, the second is taken - to be an integer month, and the third is taken to be an integer day. - If the combination of values is not valid, then a DateTimeError is - raised. One- or two-digit years up to 69 are assumed to be in the - 21st century, whereas values 70-99 are assumed to be 20th century. - The fourth, fifth, and sixth arguments are floating point, positive - or negative offsets in units of hours, minutes, and days, and - default to zero if not given. An optional string may be given as - the final argument to indicate timezone (the effect of this is as if - you had taken the value of time.time() at that time on a machine in - the specified timezone). - -If a string argument passed to the DateTime constructor cannot be -parsed, it will raise SyntaxError. Invalid date, time, or -timezone components will raise a DateTimeError. - -The module function Timezones() will return a list of the timezones -recognized by the DateTime module. Recognition of timezone names is -case-insensitive. - -Instance Methods for DateTime (IDateTime interface) ---------------------------------------------------- - -Conversion and comparison methods -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* ``timeTime()`` returns the date/time as a floating-point number in - UTC, in the format used by the Python time module. Note that it is - possible to create date /time values with DateTime that have no - meaningful value to the time module, and in such cases a - DateTimeError is raised. A DateTime object's value must generally - be between Jan 1, 1970 (or your local machine epoch) and Jan 2038 to - produce a valid time.time() style value. - - >>> dt = DateTime('Mar 9, 1997 13:45:00 US/Eastern') - >>> dt.timeTime() - 857933100.0 - - >>> DateTime('2040/01/01 UTC').timeTime() - 2208988800.0 - - >>> DateTime('1900/01/01 UTC').timeTime() - -2208988800.0 - -* ``toZone(z)`` returns a DateTime with the value as the current - object, represented in the indicated timezone: - - >>> dt.toZone('UTC') - DateTime('1997/03/09 18:45:00 UTC') - - >>> dt.toZone('UTC').equalTo(dt) - True - -* ``isFuture()`` returns true if this object represents a date/time - later than the time of the call: - - >>> dt.isFuture() - False - >>> DateTime('Jan 1 3000').isFuture() # not time-machine safe! - True - -* ``isPast()`` returns true if this object represents a date/time - earlier than the time of the call: - - >>> dt.isPast() - True - >>> DateTime('Jan 1 3000').isPast() # not time-machine safe! - False - -* ``isCurrentYear()`` returns true if this object represents a - date/time that falls within the current year, in the context of this - object's timezone representation: - - >>> dt.isCurrentYear() - False - >>> DateTime().isCurrentYear() - True - -* ``isCurrentMonth()`` returns true if this object represents a - date/time that falls within the current month, in the context of - this object's timezone representation: - - >>> dt.isCurrentMonth() - False - >>> DateTime().isCurrentMonth() - True - -* ``isCurrentDay()`` returns true if this object represents a - date/time that falls within the current day, in the context of this - object's timezone representation: - - >>> dt.isCurrentDay() - False - >>> DateTime().isCurrentDay() - True - -* ``isCurrentHour()`` returns true if this object represents a - date/time that falls within the current hour, in the context of this - object's timezone representation: - - >>> dt.isCurrentHour() - False - - >>> DateTime().isCurrentHour() - True - -* ``isCurrentMinute()`` returns true if this object represents a - date/time that falls within the current minute, in the context of - this object's timezone representation: - - >>> dt.isCurrentMinute() - False - >>> DateTime().isCurrentMinute() - True - -* ``isLeapYear()`` returns true if the current year (in the context of - the object's timezone) is a leap year: - - >>> dt.isLeapYear() - False - >>> DateTime('Mar 8 2004').isLeapYear() - True - -* ``earliestTime()`` returns a new DateTime object that represents the - earliest possible time (in whole seconds) that still falls within - the current object's day, in the object's timezone context: - - >>> dt.earliestTime() - DateTime('1997/03/09 00:00:00 US/Eastern') - -* ``latestTime()`` return a new DateTime object that represents the - latest possible time (in whole seconds) that still falls within the - current object's day, in the object's timezone context - - >>> dt.latestTime() - DateTime('1997/03/09 23:59:59 US/Eastern') - -Component access -~~~~~~~~~~~~~~~~ - -* ``parts()`` returns a tuple containing the calendar year, month, - day, hour, minute second and timezone of the object - - >>> dt.parts() # doctest: +ELLIPSIS - (1997, 3, 9, 13, 45, ... 'US/Eastern') - -* ``timezone()`` returns the timezone in which the object is represented: - - >>> dt.timezone() in Timezones() - True - -* ``tzoffset()`` returns the timezone offset for the objects timezone: - - >>> dt.tzoffset() - -18000 - -* ``year()`` returns the calendar year of the object: - - >>> dt.year() - 1997 - -* ``month()`` returns the month of the object as an integer: - - >>> dt.month() - 3 - -* ``Month()`` returns the full month name: - - >>> dt.Month() - 'March' - -* ``aMonth()`` returns the abbreviated month name: - - >>> dt.aMonth() - 'Mar' - -* ``pMonth()`` returns the abbreviated (with period) month name: - - >>> dt.pMonth() - 'Mar.' - -* ``day()`` returns the integer day: - - >>> dt.day() - 9 - -* ``Day()`` returns the full name of the day of the week: - - >>> dt.Day() - 'Sunday' - -* ``dayOfYear()`` returns the day of the year, in context of the - timezone representation of the object: - - >>> dt.dayOfYear() - 68 - -* ``aDay()`` returns the abbreviated name of the day of the week: - - >>> dt.aDay() - 'Sun' - -* ``pDay()`` returns the abbreviated (with period) name of the day of - the week: - - >>> dt.pDay() - 'Sun.' - -* ``dow()`` returns the integer day of the week, where Sunday is 0: - - >>> dt.dow() - 0 - -* ``dow_1()`` returns the integer day of the week, where sunday is 1: - - >>> dt.dow_1() - 1 - -* ``h_12()`` returns the 12-hour clock representation of the hour: - - >>> dt.h_12() - 1 - -* ``h_24()`` returns the 24-hour clock representation of the hour: - - >>> dt.h_24() - 13 - -* ``ampm()`` returns the appropriate time modifier (am or pm): - - >>> dt.ampm() - 'pm' - -* ``hour()`` returns the 24-hour clock representation of the hour: - - >>> dt.hour() - 13 - -* ``minute()`` returns the minute: - - >>> dt.minute() - 45 - -* ``second()`` returns the second: - - >>> dt.second() == 0 - True - -* ``millis()`` returns the milliseconds since the epoch in GMT. - - >>> dt.millis() == 857933100000 - True - -strftime() -~~~~~~~~~~ - -See ``tests/test_datetime.py``. - -General formats from previous DateTime -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* ``Date()`` return the date string for the object: - - >>> dt.Date() - '1997/03/09' - -* ``Time()`` returns the time string for an object to the nearest - second: - - >>> dt.Time() - '13:45:00' - -* ``TimeMinutes()`` returns the time string for an object not showing - seconds: - - >>> dt.TimeMinutes() - '13:45' - -* ``AMPM()`` returns the time string for an object to the nearest second: - - >>> dt.AMPM() - '01:45:00 pm' - -* ``AMPMMinutes()`` returns the time string for an object not showing - seconds: - - >>> dt.AMPMMinutes() - '01:45 pm' - -* ``PreciseTime()`` returns the time string for the object: - - >>> dt.PreciseTime() - '13:45:00.000' - -* ``PreciseAMPM()`` returns the time string for the object: - - >>> dt.PreciseAMPM() - '01:45:00.000 pm' - -* ``yy()`` returns the calendar year as a 2 digit string - - >>> dt.yy() - '97' - -* ``mm()`` returns the month as a 2 digit string - - >>> dt.mm() - '03' - -* ``dd()`` returns the day as a 2 digit string: - - >>> dt.dd() - '09' - -* ``rfc822()`` returns the date in RFC 822 format: - - >>> dt.rfc822() - 'Sun, 09 Mar 1997 13:45:00 -0500' - -New formats -~~~~~~~~~~~ - -* ``fCommon()`` returns a string representing the object's value in - the format: March 9, 1997 1:45 pm: - - >>> dt.fCommon() - 'March 9, 1997 1:45 pm' - -* ``fCommonZ()`` returns a string representing the object's value in - the format: March 9, 1997 1:45 pm US/Eastern: - - >>> dt.fCommonZ() - 'March 9, 1997 1:45 pm US/Eastern' - -* ``aCommon()`` returns a string representing the object's value in - the format: Mar 9, 1997 1:45 pm: - - >>> dt.aCommon() - 'Mar 9, 1997 1:45 pm' - -* ``aCommonZ()`` return a string representing the object's value in - the format: Mar 9, 1997 1:45 pm US/Eastern: - - >>> dt.aCommonZ() - 'Mar 9, 1997 1:45 pm US/Eastern' - -* ``pCommon()`` returns a string representing the object's value in - the format Mar. 9, 1997 1:45 pm: - - >>> dt.pCommon() - 'Mar. 9, 1997 1:45 pm' - -* ``pCommonZ()`` returns a string representing the object's value in - the format: Mar. 9, 1997 1:45 pm US/Eastern: - - >>> dt.pCommonZ() - 'Mar. 9, 1997 1:45 pm US/Eastern' - -* ``ISO()`` returns a string with the date/time in ISO format. Note: - this is not ISO 8601-format! See the ISO8601 and HTML4 methods below - for ISO 8601-compliant output. Dates are output as: YYYY-MM-DD HH:MM:SS - - >>> dt.ISO() - '1997-03-09 13:45:00' - -* ``ISO8601()`` returns the object in ISO 8601-compatible format - containing the date, time with seconds-precision and the time zone - identifier - see http://www.w3.org/TR/NOTE-datetime. Dates are - output as: YYYY-MM-DDTHH:MM:SSTZD (T is a literal character, TZD is - Time Zone Designator, format +HH:MM or -HH:MM). - - The ``HTML4()`` method below offers the same formatting, but - converts to UTC before returning the value and sets the TZD"Z" - - >>> dt.ISO8601() - '1997-03-09T13:45:00-05:00' - - -* ``HTML4()`` returns the object in the format used in the HTML4.0 - specification, one of the standard forms in ISO8601. See - http://www.w3.org/TR/NOTE-datetime. Dates are output as: - YYYY-MM-DDTHH:MM:SSZ (T, Z are literal characters, the time is in - UTC.): - - >>> dt.HTML4() - '1997-03-09T18:45:00Z' - -* ``JulianDay()`` returns the Julian day according to - http://www.tondering.dk/claus/cal/node3.html#sec-calcjd - - >>> dt.JulianDay() - 2450517 - -* ``week()`` returns the week number according to ISO - see http://www.tondering.dk/claus/cal/node6.html#SECTION00670000000000000000 - - >>> dt.week() - 10 - -Deprecated API -~~~~~~~~~~~~~~ - -* DayOfWeek(): see Day() - -* Day_(): see pDay() - -* Mon(): see aMonth() - -* Mon_(): see pMonth - -General Services Provided by DateTime -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -DateTimes can be repr()'ed; the result will be a string indicating how -to make a DateTime object like this: - - >>> repr(dt) - "DateTime('1997/03/09 13:45:00 US/Eastern')" - -When we convert them into a string, we get a nicer string that could -actually be shown to a user: - - >>> str(dt) - '1997/03/09 13:45:00 US/Eastern' - -The hash value of a DateTime is based on the date and time and is -equal for different representations of the DateTime: - - >>> hash(dt) - 3618678 - >>> hash(dt.toZone('UTC')) - 3618678 - -DateTime objects can be compared to other DateTime objects OR floating -point numbers such as the ones which are returned by the Python time -module by using the equalTo method. Using this API, True is returned if the -object represents a date/time equal to the specified DateTime or time module -style time: - - >>> dt.equalTo(dt) - True - >>> dt.equalTo(dt.toZone('UTC')) - True - >>> dt.equalTo(dt.timeTime()) - True - >>> dt.equalTo(DateTime()) - False - -Same goes for inequalities: - - >>> dt.notEqualTo(dt) - False - >>> dt.notEqualTo(dt.toZone('UTC')) - False - >>> dt.notEqualTo(dt.timeTime()) - False - >>> dt.notEqualTo(DateTime()) - True - -Normal equality operations only work with DateTime objects and take the -timezone setting into account: - - >>> dt == dt - True - >>> dt == dt.toZone('UTC') - False - >>> dt == DateTime() - False - - >>> dt != dt - False - >>> dt != dt.toZone('UTC') - True - >>> dt != DateTime() - True - -But the other comparison operations compare the referenced moment in time and -not the representation itself: - - >>> dt > dt - False - >>> DateTime() > dt - True - >>> dt > DateTime().timeTime() - False - >>> DateTime().timeTime() > dt - True - - >>> dt.greaterThan(dt) - False - >>> DateTime().greaterThan(dt) - True - >>> dt.greaterThan(DateTime().timeTime()) - False - - >>> dt >= dt - True - >>> DateTime() >= dt - True - >>> dt >= DateTime().timeTime() - False - >>> DateTime().timeTime() >= dt - True - - >>> dt.greaterThanEqualTo(dt) - True - >>> DateTime().greaterThanEqualTo(dt) - True - >>> dt.greaterThanEqualTo(DateTime().timeTime()) - False - - >>> dt < dt - False - >>> DateTime() < dt - False - >>> dt < DateTime().timeTime() - True - >>> DateTime().timeTime() < dt - False - - >>> dt.lessThan(dt) - False - >>> DateTime().lessThan(dt) - False - >>> dt.lessThan(DateTime().timeTime()) - True - - >>> dt <= dt - True - >>> DateTime() <= dt - False - >>> dt <= DateTime().timeTime() - True - >>> DateTime().timeTime() <= dt - False - - >>> dt.lessThanEqualTo(dt) - True - >>> DateTime().lessThanEqualTo(dt) - False - >>> dt.lessThanEqualTo(DateTime().timeTime()) - True - -Numeric Services Provided by DateTime -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A DateTime may be added to a number and a number may be added to a -DateTime: - - >>> dt + 5 - DateTime('1997/03/14 13:45:00 US/Eastern') - >>> 5 + dt - DateTime('1997/03/14 13:45:00 US/Eastern') - -Two DateTimes cannot be added: - - >>> from DateTime.interfaces import DateTimeError - >>> try: - ... dt + dt - ... print('fail') - ... except DateTimeError: - ... print('ok') - ok - -Either a DateTime or a number may be subtracted from a DateTime, -however, a DateTime may not be subtracted from a number: - - >>> DateTime('1997/03/10 13:45 US/Eastern') - dt - 1.0 - >>> dt - 1 - DateTime('1997/03/08 13:45:00 US/Eastern') - >>> 1 - dt - Traceback (most recent call last): - ... - TypeError: unsupported operand type(s) for -: 'int' and 'DateTime' - -DateTimes can also be converted to integers (number of seconds since -the epoch) and floats: - - >>> int(dt) - 857933100 - >>> float(dt) - 857933100.0 - - -Changelog -========= - -5.5 (2024-03-21) ----------------- - -- Change pickle format to export the microseconds as an int, to - solve a problem with dates after 2038. - (`#56 `_) - - -5.4 (2023-12-15) ----------------- - -- Fix ``UnknownTimeZoneError`` when unpickling ``DateTime.DateTime().asdatetime()``. - (`#58 `_) - -- Repair equality comparison between DateTime instances and other types. - (`#60 `_) - - -5.3 (2023-11-14) ----------------- - -- Add support for Python 3.12. - -- Add preliminary support for Python 3.13a2. - - -5.2 (2023-07-19) ----------------- - -- Cast int to float in compare methods. -- Fix compare methods between DateTime instances and None. - (`#52 `_) - - -5.1 (2023-03-14) ----------------- - -- Add missing ``python_requires`` to ``setup.py``. - - -5.0 (2023-01-12) ----------------- - -- Drop support for Python 2.7, 3.5, 3.6. - - -4.8 (2022-12-16) ----------------- - -- Fix insidious buildout configuration bug that prevented tests on Python 2.7 - and 3.5, and fix test code that was incompatible with Python 3.5. - (`#44 `_) - -- Add support for Python 3.11. - - -4.7 (2022-09-14) ----------------- - -- Fix rounding problem with `DateTime` addition beyond the year 2038 - (`#41 `_) - - -4.6 (2022-09-10) ----------------- - -- Fix ``__format__`` method for DateTime objects - (`#39 `_) - - -4.5 (2022-07-04) ----------------- - -- Add ``__format__`` method for DateTime objects - (`#35 `_) - - -4.4 (2022-02-11) ----------------- - -- Fix WAT definition - `#31 `_. - -- Add support for Python 3.8, 3.9, and 3.10. - -- Drop support for Python 3.4. - -4.3 (2018-10-05) ----------------- - -- Add support for Python 3.7. - -4.2 (2017-04-26) ----------------- - -- Add support for Python 3.6, drop support for Python 3.3. - -4.1.1 (2016-04-30) ------------------- - -- Support unpickling instances having a numeric timezone like `+0430`. - -4.1 (2016-04-03) ----------------- - -- Add support for Python 3.4 and 3.5. - -- Drop support for Python 2.6 and 3.2. - -4.0.1 (2013-10-15) ------------------- - -- Provide more backward compatible timezones. - [vangheem] - -4.0 (2013-02-23) ----------------- - -- Added support for Python 3.2 and 3.3 in addition to 2.6 and 2.7. - -- Removed unused legacy pytz tests and the DateTimeZone module and renamed - some test internals. - -3.0.3 (2013-01-22) ------------------- - -- Allow timezone argument to be a Unicode string while creating a DateTime - object using two arguments. - -3.0.2 (2012-10-21) ------------------- - -- LP #1045233: Respect date format setting for parsing dates like `11-01-2001`. - -3.0.1 (2012-09-23) ------------------- - -- Add `_dt_reconstructor` function introduced in DateTime 2.12.7 to provide - forward compatibility with pickles that might reference this function. - -3.0 (2011-12-09) ----------------- - -- No changes. - -Backwards compatibility of DateTime 3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -DateTime 3 changes its pickle representation. DateTime instances pickled with -former versions of DateTime can be read, but older DateTime versions cannot read -DateTime instances pickled with version 3. - -DateTime 3 changes DateTime to be a new-style class with slots instead of being -an old-style class. - -DateTime 3 tries to preserve microsecond resolution throughout most of its API's -while former versions were often only accurate to millisecond resolution. Due to -the representation of float values in Python versions before Python 2.7 you -shouldn't compare string or float representations of DateTime instances if you -want high accuracy. The same is true for calculated values returned by methods -like `timeTime()`. You get the highest accuracy of comparing DateTime values by -calling its `micros()` methods. DateTime is not particular well suited to be -used in comparing timestamps of file systems - use the time and datetime objects -from the Python standard library instead. - -3.0b3 (2011-10-19) ------------------- - -- Allow comparison of DateTime objects against None. - -3.0b2 (2011-10-19) ------------------- - -- Reverted the single argument `None` special case handling for unpickling and - continue to treat it as meaning `now`. - -3.0b1 (2011-05-07) ------------------- - -- Restored `strftimeFormatter` as a class. - -- Added tests for read-only class attributes and interface. - -3.0a2 (2011-05-07) ------------------- - -- Added back support for reading old DateTime pickles without a `_micros` value. - -- Avoid storing `_t` representing the time as a float in seconds since the - epoch, as we already have `_micros` doing the same as a long. Memory use is - down to about 300 bytes per DateTime instance. - -- Updated exception raising syntax to current style. - -- Avoid storing `_aday`, `_fday`, `_pday`, `_amon`, `_fmon`, `_pmon`, `_pmhour` - and `_pm` in memory for every instance but look them up dynamically based on - `_dayoffset`, `_month` and `_hour`. This saves another 150 bytes of memory - per DateTime instance. - -- Moved various internal parsing related class variables to module constants. - -- No longer provide the `DateError`, `DateTimeError`, `SyntaxError` and - `TimeError` exceptions as class attributes, import them from their canonical - `DateTime.interfaces` location instead. - -- Removed deprecated `_isDST` and `_localzone` class variables. - -- Moved pytz cache from `DateTime._tzinfo` to a module global `_TZINFO`. - -- Make DateTime a new-style class and limit its available attributes via a - slots definition. The pickle size increases to 110 bytes thanks to the - `ccopy_reg\n_reconstructor` stanza. But the memory size drops from 3kb to - 500 bytes for each instance. - -3.0a1 (2011-05-06) ------------------- - -- Reordered some calculations in `_calcIndependentSecondEtc` to preserve more - floating point precision. - -- Optimized the pickled data, by only storing a tuple of `_micros` and time - zone information - this reduces the pickle size from an average of 300 bytes - to just 60 bytes. - -- Optimized un-pickling, by avoiding the creation of an intermediate DateTime - value representing the current time. - -- Removed in-place migration of old DateTime pickles without a `_micros` value. - -- Removed deprecated support for using `DateTime.__cmp__`. - -- Take time zone settings into account when comparing two date times for - (non-) equality. - -- Fixed (possibly unused) _parse_iso8601 function. - -- Removed unused import of legacy DateTimeZone, strftime and re. - Remove trailing whitespace. - -- Removed reference to missing version section from buildout. - -2.12.7 (2012-08-11) -------------------- - -- Added forward compatibility with DateTime 3 pickle format. DateTime - instances constructed under version 3 can be read and unpickled by this - version. The pickled data is converted to the current versions format - (old-style class / no slots). Once converted it will be stored again in the - old format. This should allow for a transparent upgrade/downgrade path - between DateTime 2 and 3. - -2.12.6 (2010-10-17) -------------------- - -- Changed ``testDayOfWeek`` test to be independent of OS locale. - -2.12.5 (2010-07-29) -------------------- - -- Launchpad #143269: Corrected the documentation for year value - behavior when constructing a DateTime object with three numeric - arguments. - -- Launchpad #142521: Removed confusing special case in - DateTime.__str__ where DateTime instances for midnight - (e.g. '2010-07-27 00:00:00 US/Eastern') values would - render only their date and nothing else. - -2.12.4 (2010-07-12) -------------------- - -- Fixed mapping of EDT (was -> 'GMT-0400', now 'GMT-4'). - -2.12.3 (2010-07-09) -------------------- - -- Added EDT timezone support. Addresses bug #599856. - [vangheem] - -2.12.2 (2010-05-05) -------------------- - -- Launchpad #572715: Relaxed pin on pytz, after applying a patch from - Marius Gedminus which fixes the apparent API breakage. - -2.12.1 (2010-04-30) -------------------- - -- Removed an undeclared testing dependency on zope.testing.doctest in favor of - the standard libraries doctest module. - -- Added a maximum version requirement on pytz <= 2010b. Later versions produce - test failures related to timezone changes. - -2.12.0 (2009-03-04) -------------------- - -- Launchpad #290254: Forward-ported fix for '_micros'-less pickles from - the Zope 2.11 branch version. - -2.11.2 (2009-02-02) -------------------- - -- Include *all* pytz zone names, not just "common" ones. - -- Fix one fragile doctest, band-aid another. - -- Fix for launchpad #267545: DateTime(DateTime()) should preserve the - correct hour. - -2.11.1 (2008-08-05) -------------------- - -- DateTime conversion of datetime objects with non-pytz tzinfo. Timezones() - returns a copy of the timezone list (allows tests to run). - -- Merged the slinkp-datetime-200007 branch: fix the DateTime(anotherDateTime) - constructor to preserve timezones. - -2.11.0b1 (2008-01-06) ---------------------- - -- Split off from the Zope2 main source code tree. diff --git a/venv/Lib/site-packages/DateTime-5.5.dist-info/RECORD b/venv/Lib/site-packages/DateTime-5.5.dist-info/RECORD deleted file mode 100644 index 1de0834..0000000 --- a/venv/Lib/site-packages/DateTime-5.5.dist-info/RECORD +++ /dev/null @@ -1,22 +0,0 @@ -DateTime-5.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -DateTime-5.5.dist-info/LICENSE.txt,sha256=PmcdsR32h1FswdtbPWXkqjg-rKPCDOo_r1Og9zNdCjw,2070 -DateTime-5.5.dist-info/METADATA,sha256=W1k0PqPJ6SU6QTJAu40JPtHK8XeQRL0GGEpfVGPjWGI,33735 -DateTime-5.5.dist-info/RECORD,, -DateTime-5.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -DateTime-5.5.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92 -DateTime-5.5.dist-info/top_level.txt,sha256=iVdUvuV_RIkkMzsnPGNfwojRWvuonInryaK3hA5Hh0o,9 -DateTime/DateTime.py,sha256=65LbTcnrCSsDPGoGLVkk7NC3H8Kq-PjkC1fQVR33gE8,71364 -DateTime/DateTime.txt,sha256=KZFzxoQItLsar1ZDd2vZN74Y6L4a04H8jXMwqc8KjmY,22487 -DateTime/__init__.py,sha256=trlFzEmNkmUpxZT7krPSVDayDK1bRxToccg3CcCF8wg,714 -DateTime/__pycache__/DateTime.cpython-310.pyc,, -DateTime/__pycache__/__init__.cpython-310.pyc,, -DateTime/__pycache__/interfaces.cpython-310.pyc,, -DateTime/__pycache__/pytz_support.cpython-310.pyc,, -DateTime/interfaces.py,sha256=n47sexf1eQ6YMdYB_60PgHtSzYIj4FND-RmHFiNpm1E,12187 -DateTime/pytz.txt,sha256=9Phns9ESXs9MaOKxXztX6sJ09QczGxsbYoSRSllKUfk,5619 -DateTime/pytz_support.py,sha256=inR1SO0X17fp9C2GsRw99S_MhxKiEt5dOV3-TGsBxDI,11853 -DateTime/tests/__init__.py,sha256=H7Ixo1xp-8BlJ65u14hk5i_TKEmETyi2FmLMD6H-mpo,683 -DateTime/tests/__pycache__/__init__.cpython-310.pyc,, -DateTime/tests/__pycache__/test_datetime.cpython-310.pyc,, -DateTime/tests/julian_testdata.txt,sha256=qxvLvabVB9ayhh5UHBvPhuqW5mRL_lizzbUh6lc3d4I,1397 -DateTime/tests/test_datetime.py,sha256=dsrfAqQpz1od1bOVPvSYfZAlduJpJIpc2F_hdN7WRAU,30385 diff --git a/venv/Lib/site-packages/DateTime-5.5.dist-info/REQUESTED b/venv/Lib/site-packages/DateTime-5.5.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/DateTime-5.5.dist-info/WHEEL b/venv/Lib/site-packages/DateTime-5.5.dist-info/WHEEL deleted file mode 100644 index 98c0d20..0000000 --- a/venv/Lib/site-packages/DateTime-5.5.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.42.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/venv/Lib/site-packages/DateTime-5.5.dist-info/top_level.txt b/venv/Lib/site-packages/DateTime-5.5.dist-info/top_level.txt deleted file mode 100644 index 1b8c206..0000000 --- a/venv/Lib/site-packages/DateTime-5.5.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -DateTime diff --git a/venv/Lib/site-packages/DateTime/DateTime.py b/venv/Lib/site-packages/DateTime/DateTime.py deleted file mode 100644 index fc289e6..0000000 --- a/venv/Lib/site-packages/DateTime/DateTime.py +++ /dev/null @@ -1,1948 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Foundation and Contributors. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE -# -############################################################################## - -import copyreg as copy_reg -import math -import re -from datetime import datetime -from time import altzone -from time import daylight -from time import gmtime -from time import localtime -from time import time -from time import timezone -from time import tzname - -from zope.interface import implementer - -from .interfaces import DateError -from .interfaces import DateTimeError -from .interfaces import IDateTime -from .interfaces import SyntaxError -from .interfaces import TimeError -from .pytz_support import PytzCache - - -basestring = str -long = int -explicit_unicode_type = type(None) - -default_datefmt = None - - -def getDefaultDateFormat(): - global default_datefmt - if default_datefmt is None: - try: - from App.config import getConfiguration - default_datefmt = getConfiguration().datetime_format - return default_datefmt - except Exception: - return 'us' - else: - return default_datefmt - - -# To control rounding errors, we round system time to the nearest -# microsecond. Then delicate calculations can rely on the fact that the -# maximum precision that needs to be preserved is known. -_system_time = time - - -def time(): - return round(_system_time(), 6) - - -# Determine machine epoch -tm = ((0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334), - (0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335)) -yr, mo, dy, hr, mn, sc = gmtime(0)[:6] -i = int(yr - 1) -to_year = int(i * 365 + i // 4 - i // 100 + i // 400 - 693960.0) -to_month = tm[yr % 4 == 0 and (yr % 100 != 0 or yr % 400 == 0)][mo] -EPOCH = ((to_year + to_month + dy + - (hr / 24.0 + mn / 1440.0 + sc / 86400.0)) * 86400) -jd1901 = 2415385 - -_TZINFO = PytzCache() - -INT_PATTERN = re.compile(r'([0-9]+)') -FLT_PATTERN = re.compile(r':([0-9]+\.[0-9]+)') -NAME_PATTERN = re.compile(r'([a-zA-Z]+)', re.I) -SPACE_CHARS = ' \t\n' -DELIMITERS = '-/.:,+' - -_MONTH_LEN = ((0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), - (0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)) -_MONTHS = ('', 'January', 'February', 'March', 'April', 'May', 'June', - 'July', 'August', 'September', 'October', 'November', 'December') -_MONTHS_A = ('', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec') -_MONTHS_P = ('', 'Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June', - 'July', 'Aug.', 'Sep.', 'Oct.', 'Nov.', 'Dec.') -_MONTHMAP = {'january': 1, 'jan': 1, - 'february': 2, 'feb': 2, - 'march': 3, 'mar': 3, - 'april': 4, 'apr': 4, - 'may': 5, - 'june': 6, 'jun': 6, - 'july': 7, 'jul': 7, - 'august': 8, 'aug': 8, - 'september': 9, 'sep': 9, 'sept': 9, - 'october': 10, 'oct': 10, - 'november': 11, 'nov': 11, - 'december': 12, 'dec': 12} -_DAYS = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', - 'Thursday', 'Friday', 'Saturday') -_DAYS_A = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat') -_DAYS_P = ('Sun.', 'Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.') -_DAYMAP = {'sunday': 1, 'sun': 1, - 'monday': 2, 'mon': 2, - 'tuesday': 3, 'tues': 3, 'tue': 3, - 'wednesday': 4, 'wed': 4, - 'thursday': 5, 'thurs': 5, 'thur': 5, 'thu': 5, - 'friday': 6, 'fri': 6, - 'saturday': 7, 'sat': 7} - -numericTimeZoneMatch = re.compile(r'[+-][0-9][0-9][0-9][0-9]').match -iso8601Match = re.compile(r''' - (?P\d\d\d\d) # four digits year - (?:-? # one optional dash - (?: # followed by: - (?P\d\d\d # three digits year day - (?!\d)) # when there is no fourth digit - | # or: - W # one W - (?P\d\d) # two digits week - (?:-? # one optional dash - (?P\d) # one digit week day - )? # week day is optional - | # or: - (?P\d\d)? # two digits month - (?:-? # one optional dash - (?P\d\d)? # two digits day - )? # after day is optional - ) # - )? # after year is optional - (?:[T ] # one T or one whitespace - (?P\d\d) # two digits hour - (?::? # one optional colon - (?P\d\d)? # two digits minute - (?::? # one optional colon - (?P\d\d)? # two digits second - (?:[.,] # one dot or one comma - (?P\d+) # n digits fraction - )? # after second is optional - )? # after minute is optional - )? # after hour is optional - (?: # timezone: - (?PZ) # one Z - | # or: - (?P[-+]) # one plus or one minus as signal - (?P\d # one digit for hour offset... - (?:\d(?!\d$) # ...or two, if not the last two digits - )?) # second hour offset digit is optional - (?::? # one optional colon - (?P\d\d) # two digits minute offset - )? # after hour offset is optional - )? # timezone is optional - )? # time is optional - (?P.*) # store the extra garbage -''', re.VERBOSE).match - - -def _findLocalTimeZoneName(isDST): - if not daylight: - # Daylight savings does not occur in this time zone. - isDST = 0 - try: - # Get the name of the current time zone depending - # on DST. - _localzone = PytzCache._zmap[tzname[isDST].lower()] - except BaseException: - try: - # Generate a GMT-offset zone name. - if isDST: - localzone = altzone - else: - localzone = timezone - offset = (-localzone / 3600.0) - majorOffset = int(offset) - if majorOffset != 0: - minorOffset = abs(int((offset % majorOffset) * 60.0)) - else: - minorOffset = 0 - m = majorOffset >= 0 and '+' or '' - lz = '%s%0.02d%0.02d' % (m, majorOffset, minorOffset) - _localzone = PytzCache._zmap[('GMT%s' % lz).lower()] - except BaseException: - _localzone = '' - return _localzone - - -_localzone0 = _findLocalTimeZoneName(0) -_localzone1 = _findLocalTimeZoneName(1) -_multipleZones = (_localzone0 != _localzone1) - -# Some utility functions for calculating dates: - - -def _calcSD(t): - # Returns timezone-independent days since epoch and the fractional - # part of the days. - dd = t + EPOCH - 86400.0 - d = dd / 86400.0 - s = d - math.floor(d) - return s, d - - -def _calcDependentSecond(tz, t): - # Calculates the timezone-dependent second (integer part only) - # from the timezone-independent second. - fset = _tzoffset(tz, t) - return fset + long(math.floor(t)) + long(EPOCH) - 86400 - - -def _calcDependentSecond2(yr, mo, dy, hr, mn, sc): - # Calculates the timezone-dependent second (integer part only) - # from the date given. - ss = int(hr) * 3600 + int(mn) * 60 + int(sc) - x = long(_julianday(yr, mo, dy) - jd1901) * 86400 + ss - return x - - -def _calcIndependentSecondEtc(tz, x, ms): - # Derive the timezone-independent second from the timezone - # dependent second. - fsetAtEpoch = _tzoffset(tz, 0.0) - nearTime = x - fsetAtEpoch - long(EPOCH) + 86400 + ms - # nearTime is now within an hour of being correct. - # Recalculate t according to DST. - fset = long(_tzoffset(tz, nearTime)) - d = (x - fset) / 86400.0 + (ms / 86400.0) - t = x - fset - long(EPOCH) + 86400 + ms - micros = (x + 86400 - fset) * 1000000 + \ - long(round(ms * 1000000.0)) - long(EPOCH * 1000000.0) - s = d - math.floor(d) - return (s, d, t, micros) - - -def _calcHMS(x, ms): - # hours, minutes, seconds from integer and float. - hr = x // 3600 - x = x - hr * 3600 - mn = x // 60 - sc = x - mn * 60 + ms - return (hr, mn, sc) - - -def _calcYMDHMS(x, ms): - # x is a timezone-dependent integer of seconds. - # Produces yr,mo,dy,hr,mn,sc. - yr, mo, dy = _calendarday(x // 86400 + jd1901) - x = int(x - (x // 86400) * 86400) - hr = x // 3600 - x = x - hr * 3600 - mn = x // 60 - sc = x - mn * 60 + ms - return (yr, mo, dy, hr, mn, sc) - - -def _julianday(yr, mo, dy): - y, m, d = long(yr), long(mo), long(dy) - if m > 12: - y = y + m // 12 - m = m % 12 - elif m < 1: - m = -m - y = y - m // 12 - 1 - m = 12 - m % 12 - if y > 0: - yr_correct = 0 - else: - yr_correct = 3 - if m < 3: - y, m = y - 1, m + 12 - if y * 10000 + m * 100 + d > 15821014: - b = 2 - y // 100 + y // 400 - else: - b = 0 - return ((1461 * y - yr_correct) // 4 + - 306001 * (m + 1) // 10000 + d + 1720994 + b) - - -def _calendarday(j): - j = long(j) - if (j < 2299160): - b = j + 1525 - else: - a = (4 * j - 7468861) // 146097 - b = j + 1526 + a - a // 4 - c = (20 * b - 2442) // 7305 - d = 1461 * c // 4 - e = 10000 * (b - d) // 306001 - dy = int(b - d - 306001 * e // 10000) - mo = (e < 14) and int(e - 1) or int(e - 13) - yr = (mo > 2) and (c - 4716) or (c - 4715) - return (int(yr), int(mo), int(dy)) - - -def _tzoffset(tz, t): - """Returns the offset in seconds to GMT from a specific timezone (tz) at - a specific time (t). NB! The _tzoffset result is the same same sign as - the time zone, i.e. GMT+2 has a 7200 second offset. This is the opposite - sign of time.timezone which (confusingly) is -7200 for GMT+2.""" - try: - return _TZINFO[tz].info(t)[0] - except Exception: - if numericTimeZoneMatch(tz) is not None: - return int(tz[0:3]) * 3600 + int(tz[0] + tz[3:5]) * 60 - else: - return 0 # ?? - - -def _correctYear(year): - # Y2K patch. - if year >= 0 and year < 100: - # 00-69 means 2000-2069, 70-99 means 1970-1999. - if year < 70: - year = 2000 + year - else: - year = 1900 + year - return year - - -def safegmtime(t): - '''gmtime with a safety zone.''' - try: - return gmtime(t) - except (ValueError, OverflowError): - raise TimeError('The time %f is beyond the range of this Python ' - 'implementation.' % float(t)) - - -def safelocaltime(t): - '''localtime with a safety zone.''' - try: - return localtime(t) - except (ValueError, OverflowError): - raise TimeError('The time %f is beyond the range of this Python ' - 'implementation.' % float(t)) - - -def _tzoffset2rfc822zone(seconds): - """Takes an offset, such as from _tzoffset(), and returns an rfc822 - compliant zone specification. Please note that the result of - _tzoffset() is the negative of what time.localzone and time.altzone is. - """ - return "%+03d%02d" % divmod((seconds // 60), 60) - - -def _tzoffset2iso8601zone(seconds): - """Takes an offset, such as from _tzoffset(), and returns an ISO 8601 - compliant zone specification. Please note that the result of - _tzoffset() is the negative of what time.localzone and time.altzone is. - """ - return "%+03d:%02d" % divmod((seconds // 60), 60) - - -def Timezones(): - """Return the list of recognized timezone names""" - return sorted(list(PytzCache._zmap.values())) - - -class strftimeFormatter: - - def __init__(self, dt, format): - self.dt = dt - self.format = format - - def __call__(self): - return self.dt.strftime(self.format) - - -@implementer(IDateTime) -class DateTime: - """DateTime objects represent instants in time and provide - interfaces for controlling its representation without - affecting the absolute value of the object. - - DateTime objects may be created from a wide variety of string - or numeric data, or may be computed from other DateTime objects. - DateTimes support the ability to convert their representations - to many major timezones, as well as the ability to create a - DateTime object in the context of a given timezone. - - DateTime objects provide partial numerical behavior: - - - Two date-time objects can be subtracted to obtain a time, - in days between the two. - - - A date-time object and a positive or negative number may - be added to obtain a new date-time object that is the given - number of days later than the input date-time object. - - - A positive or negative number and a date-time object may - be added to obtain a new date-time object that is the given - number of days later than the input date-time object. - - - A positive or negative number may be subtracted from a - date-time object to obtain a new date-time object that is - the given number of days earlier than the input date-time - object. - - DateTime objects may be converted to integer, long, or float - numbers of days since January 1, 1901, using the standard int, - long, and float functions (Compatibility Note: int, long and - float return the number of days since 1901 in GMT rather than - local machine timezone). DateTime objects also provide access - to their value in a float format usable with the Python time - module, provided that the value of the object falls in the - range of the epoch-based time module, and as a datetime.datetime - object. - - A DateTime object should be considered immutable; all conversion - and numeric operations return a new DateTime object rather than - modify the current object.""" - - # For security machinery: - __roles__ = None - __allow_access_to_unprotected_subobjects__ = 1 - - # Limit the amount of instance attributes - __slots__ = ( - '_timezone_naive', - '_tz', - '_dayoffset', - '_year', - '_month', - '_day', - '_hour', - '_minute', - '_second', - '_nearsec', - '_d', - '_micros', - 'time', - ) - - def __init__(self, *args, **kw): - """Return a new date-time object""" - try: - return self._parse_args(*args, **kw) - except (DateError, TimeError, DateTimeError): - raise - except Exception: - raise SyntaxError('Unable to parse {}, {}'.format(args, kw)) - - def __getstate__(self): - return (self._micros, - getattr(self, '_timezone_naive', False), - self._tz) - - def __setstate__(self, value): - if isinstance(value, tuple): - micros, tz_naive, tz = value - if isinstance(micros, float): - # BBB: support for pickle where micros was a float - micros = int(micros * 1000000) - self._parse_args(micros / 1000000., tz) - self._micros = micros - self._timezone_naive = tz_naive - else: - for k, v in value.items(): - if k in self.__slots__: - setattr(self, k, v) - # BBB: support for very old DateTime pickles - if '_micros' not in value: - self._micros = long(value['_t'] * 1000000) - if '_timezone_naive' not in value: - self._timezone_naive = False - - def _parse_args(self, *args, **kw): - """Return a new date-time object. - - A DateTime object always maintains its value as an absolute - UTC time, and is represented in the context of some timezone - based on the arguments used to create the object. A DateTime - object's methods return values based on the timezone context. - - Note that in all cases the local machine timezone is used for - representation if no timezone is specified. - - DateTimes may be created with zero to seven arguments. - - - If the function is called with no arguments or with None, - then the current date/time is returned, represented in the - timezone of the local machine. - - - If the function is invoked with a single string argument - which is a recognized timezone name, an object representing - the current time is returned, represented in the specified - timezone. - - - If the function is invoked with a single string argument - representing a valid date/time, an object representing - that date/time will be returned. - - As a general rule, any date-time representation that is - recognized and unambiguous to a resident of North America - is acceptable. The reason for this qualification is that - in North America, a date like: 2/1/1994 is interpreted - as February 1, 1994, while in some parts of the world, - it is interpreted as January 2, 1994. - - A date/time string consists of two components, a date - component and an optional time component, separated by one - or more spaces. If the time component is omitted, 12:00am is - assumed. Any recognized timezone name specified as the final - element of the date/time string will be used for computing - the date/time value. If you create a DateTime with the - string 'Mar 9, 1997 1:45pm US/Pacific', the value will - essentially be the same as if you had captured time.time() - at the specified date and time on a machine in that timezone: - -

-            e = DateTime('US/Eastern')
-            # returns current date/time, represented in US/Eastern.
-
-            x = DateTime('1997/3/9 1:45pm')
-            # returns specified time, represented in local machine zone.
-
-            y = DateTime('Mar 9, 1997 13:45:00')
-            # y is equal to x
-            
- - The date component consists of year, month, and day - values. The year value must be a one-, two-, or - four-digit integer. If a one- or two-digit year is - used, the year is assumed to be in the twentieth - century. The month may be an integer, from 1 to 12, a - month name, or a month abbreviation, where a period may - optionally follow the abbreviation. The day must be an - integer from 1 to the number of days in the month. The - year, month, and day values may be separated by - periods, hyphens, forward slashes, or spaces. Extra - spaces are permitted around the delimiters. Year, - month, and day values may be given in any order as long - as it is possible to distinguish the components. If all - three components are numbers that are less than 13, - then a month-day-year ordering is assumed. - - The time component consists of hour, minute, and second - values separated by colons. The hour value must be an - integer between 0 and 23 inclusively. The minute value - must be an integer between 0 and 59 inclusively. The - second value may be an integer value between 0 and - 59.999 inclusively. The second value or both the minute - and second values may be omitted. The time may be - followed by am or pm in upper or lower case, in which - case a 12-hour clock is assumed. - - New in Zope 2.4: - The DateTime constructor automatically detects and handles - ISO8601 compliant dates (YYYY-MM-DDThh:ss:mmTZD). - - New in Zope 2.9.6: - The existing ISO8601 parser was extended to support almost - the whole ISO8601 specification. New formats includes: - -
-            y = DateTime('1993-045')
-            # returns the 45th day from 1993, which is 14th February
-
-            w = DateTime('1993-W06-7')
-            # returns the 7th day from the 6th week from 1993, which
-            # is also 14th February
-            
- - See http://en.wikipedia.org/wiki/ISO_8601 for full specs. - - Note that the Zope DateTime parser assumes timezone naive ISO - strings to be in UTC rather than local time as specified. - - - If the DateTime function is invoked with a single numeric - argument, the number is assumed to be a floating point value - such as that returned by time.time(). - - A DateTime object is returned that represents the GMT value - of the time.time() float represented in the local machine's - timezone. - - - If the DateTime function is invoked with a single argument - that is a DateTime instance, a copy of the passed object will - be created. - - - New in 2.11: - The DateTime function may now be invoked with a single argument - that is a datetime.datetime instance. DateTimes may be converted - back to datetime.datetime objects with asdatetime(). - DateTime instances may be converted to a timezone naive - datetime.datetime in UTC with utcdatetime(). - - - If the function is invoked with two numeric arguments, then - the first is taken to be an integer year and the second - argument is taken to be an offset in days from the beginning - of the year, in the context of the local machine timezone. - - The date-time value returned is the given offset number of - days from the beginning of the given year, represented in - the timezone of the local machine. The offset may be positive - or negative. - - Two-digit years are assumed to be in the twentieth - century. - - - If the function is invoked with two arguments, the first - a float representing a number of seconds past the epoch - in gmt (such as those returned by time.time()) and the - second a string naming a recognized timezone, a DateTime - with a value of that gmt time will be returned, represented - in the given timezone. - -
-            import time
-            t = time.time()
-
-            now_east = DateTime(t,'US/Eastern')
-            # Time t represented as US/Eastern
-
-            now_west = DateTime(t,'US/Pacific')
-            # Time t represented as US/Pacific
-
-            # now_east == now_west
-            # only their representations are different
-            
- - - If the function is invoked with three or more numeric - arguments, then the first is taken to be an integer - year, the second is taken to be an integer month, and - the third is taken to be an integer day. If the - combination of values is not valid, then a - DateError is raised. Two-digit years are assumed - to be in the twentieth century. The fourth, fifth, and - sixth arguments specify a time in hours, minutes, and - seconds; hours and minutes should be positive integers - and seconds is a positive floating point value, all of - these default to zero if not given. An optional string may - be given as the final argument to indicate timezone (the - effect of this is as if you had taken the value of time.time() - at that time on a machine in the specified timezone). - - New in Zope 2.7: - A new keyword parameter "datefmt" can be passed to the - constructor. If set to "international", the constructor - is forced to treat ambiguous dates as "days before month - before year". This useful if you need to parse non-US - dates in a reliable way - - In any case that a floating point number of seconds is given - or derived, it's rounded to the nearest millisecond. - - If a string argument passed to the DateTime constructor cannot be - parsed, it will raise DateTime.SyntaxError. Invalid date components - will raise a DateError, while invalid time or timezone components - will raise a DateTimeError. - - The module function Timezones() will return a list of the (common) - timezones recognized by the DateTime module. Recognition of - timezone names is case-insensitive. - """ - - datefmt = kw.get('datefmt', getDefaultDateFormat()) - d = t = s = None - ac = len(args) - microsecs = None - - if ac == 10: - # Internal format called only by DateTime - yr, mo, dy, hr, mn, sc, tz, t, d, s = args - elif ac == 11: - # Internal format that includes milliseconds (from the epoch) - yr, mo, dy, hr, mn, sc, tz, t, d, s, millisecs = args - microsecs = millisecs * 1000 - - elif ac == 12: - # Internal format that includes microseconds (from the epoch) and a - # flag indicating whether this was constructed in a timezone naive - # manner - yr, mo, dy, hr, mn, sc, tz, t, d, s, microsecs, tznaive = args - if tznaive is not None: # preserve this information - self._timezone_naive = tznaive - - elif not args or (ac and args[0] is None): - # Current time, to be displayed in local timezone - t = time() - lt = safelocaltime(t) - tz = self.localZone(lt) - ms = (t - math.floor(t)) - s, d = _calcSD(t) - yr, mo, dy, hr, mn, sc = lt[:6] - sc = sc + ms - self._timezone_naive = False - - elif ac == 1: - arg = args[0] - - if arg == '': - raise SyntaxError(arg) - - if isinstance(arg, DateTime): - """Construct a new DateTime instance from a given - DateTime instance. - """ - t = arg.timeTime() - s, d = _calcSD(t) - yr, mo, dy, hr, mn, sc, tz = arg.parts() - - elif isinstance(arg, datetime): - yr, mo, dy, hr, mn, sc, numerictz, tznaive = \ - self._parse_iso8601_preserving_tznaive(arg.isoformat()) - if arg.tzinfo is None: - self._timezone_naive = True - tz = None - else: - self._timezone_naive = False - # if we have a pytz tzinfo, use the `zone` attribute - # as a key - tz = getattr(arg.tzinfo, 'zone', numerictz) - ms = sc - math.floor(sc) - x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc) - - if tz: - try: - zone = _TZINFO[tz] - except DateTimeError: - try: - zone = _TZINFO[numerictz] - except DateTimeError: - raise DateTimeError( - 'Unknown time zone in date: %s' % arg) - tz = zone.tzinfo.zone - else: - tz = self._calcTimezoneName(x, ms) - s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms) - - elif (isinstance(arg, basestring) and - arg.lower() in _TZINFO._zidx): - # Current time, to be displayed in specified timezone - t, tz = time(), _TZINFO._zmap[arg.lower()] - ms = (t - math.floor(t)) - # Use integer arithmetic as much as possible. - s, d = _calcSD(t) - x = _calcDependentSecond(tz, t) - yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms) - - elif isinstance(arg, basestring): - # Date/time string - iso8601 = iso8601Match(arg.strip()) - fields_iso8601 = iso8601 and iso8601.groupdict() or {} - if fields_iso8601 and not fields_iso8601.get('garbage'): - yr, mo, dy, hr, mn, sc, tz, tznaive = \ - self._parse_iso8601_preserving_tznaive(arg) - self._timezone_naive = tznaive - else: - yr, mo, dy, hr, mn, sc, tz = self._parse(arg, datefmt) - - if not self._validDate(yr, mo, dy): - raise DateError('Invalid date: %s' % arg) - if not self._validTime(hr, mn, int(sc)): - raise TimeError('Invalid time: %s' % arg) - ms = sc - math.floor(sc) - x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc) - - if tz: - try: - tz = _TZINFO._zmap[tz.lower()] - except KeyError: - if numericTimeZoneMatch(tz) is None: - raise DateTimeError( - 'Unknown time zone in date: %s' % arg) - else: - tz = self._calcTimezoneName(x, ms) - s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms) - - else: - # Seconds from epoch, gmt - t = arg - lt = safelocaltime(t) - tz = self.localZone(lt) - ms = (t - math.floor(t)) - s, d = _calcSD(t) - yr, mo, dy, hr, mn, sc = lt[:6] - sc = sc + ms - - elif ac == 2: - if isinstance(args[1], basestring): - # Seconds from epoch (gmt) and timezone - t, tz = args - ms = (t - math.floor(t)) - try: - tz = _TZINFO._zmap[tz.lower()] - except KeyError: - if numericTimeZoneMatch(tz) is None: - raise DateTimeError('Unknown time zone: %s' % tz) - # Use integer arithmetic as much as possible. - s, d = _calcSD(t) - x = _calcDependentSecond(tz, t) - yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms) - else: - # Year, julian expressed in local zone - t = time() - lt = safelocaltime(t) - tz = self.localZone(lt) - yr, jul = args - yr = _correctYear(yr) - d = (_julianday(yr, 1, 0) - jd1901) + jul - x_float = d * 86400.0 - x_floor = math.floor(x_float) - ms = x_float - x_floor - x = long(x_floor) - yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms) - s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms) - else: - # Explicit format - yr, mo, dy = args[:3] - hr, mn, sc, tz = 0, 0, 0, 0 - yr = _correctYear(yr) - if not self._validDate(yr, mo, dy): - raise DateError('Invalid date: {}'.format(args)) - args = args[3:] - if args: - hr, args = args[0], args[1:] - if args: - mn, args = args[0], args[1:] - if args: - sc, args = args[0], args[1:] - if args: - tz, args = args[0], args[1:] - if args: - raise DateTimeError('Too many arguments') - if not self._validTime(hr, mn, sc): - raise TimeError('Invalid time: %s' % repr(args)) - - x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc) - ms = sc - math.floor(sc) - if tz: - try: - tz = _TZINFO._zmap[tz.lower()] - except KeyError: - if numericTimeZoneMatch(tz) is None: - raise DateTimeError('Unknown time zone: %s' % tz) - else: - # Get local time zone name - tz = self._calcTimezoneName(x, ms) - s, d, t, microsecs = _calcIndependentSecondEtc(tz, x, ms) - - self._dayoffset = int((_julianday(yr, mo, dy) + 2) % 7) - # Round to nearest microsecond in platform-independent way. You - # cannot rely on C sprintf (Python '%') formatting to round - # consistently; doing it ourselves ensures that all but truly - # horrid C sprintf implementations will yield the same result - # cross-platform, provided the format asks for exactly 6 digits after - # the decimal point. - sc = round(sc, 6) - if sc >= 60.0: # can happen if, e.g., orig sc was 59.9999999 - sc = 59.999999 - self._nearsec = math.floor(sc) - self._year, self._month, self._day = yr, mo, dy - self._hour, self._minute, self._second = hr, mn, sc - self.time, self._d, self._tz = s, d, tz - # self._micros is the time since the epoch - # in long integer microseconds. - if microsecs is None: - microsecs = long(round(t * 1000000.0)) - self._micros = microsecs - - def localZone(self, ltm=None): - '''Returns the time zone on the given date. The time zone - can change according to daylight savings.''' - if not _multipleZones: - return _localzone0 - if ltm is None: - ltm = localtime(time()) - isDST = ltm[8] - lz = isDST and _localzone1 or _localzone0 - return lz - - def _calcTimezoneName(self, x, ms): - # Derive the name of the local time zone at the given - # timezone-dependent second. - if not _multipleZones: - return _localzone0 - fsetAtEpoch = _tzoffset(_localzone0, 0.0) - nearTime = x - fsetAtEpoch - long(EPOCH) + 86400 + ms - # nearTime is within an hour of being correct. - try: - ltm = safelocaltime(nearTime) - except BaseException: - # We are beyond the range of Python's date support. - # Hopefully we can assume that daylight savings schedules - # repeat every 28 years. Calculate the name of the - # time zone using a supported range of years. - yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, 0) - yr = ((yr - 1970) % 28) + 1970 - x = _calcDependentSecond2(yr, mo, dy, hr, mn, sc) - nearTime = x - fsetAtEpoch - long(EPOCH) + 86400 + ms - - # nearTime might still be negative if we are east of Greenwich. - # But we can assume on 1969/12/31 were no timezone changes. - nearTime = max(0, nearTime) - - ltm = safelocaltime(nearTime) - tz = self.localZone(ltm) - return tz - - def _parse(self, st, datefmt=getDefaultDateFormat()): - # Parse date-time components from a string - month = year = tz = tm = None - ValidZones = _TZINFO._zidx - TimeModifiers = ['am', 'pm'] - - # Find timezone first, since it should always be the last - # element, and may contain a slash, confusing the parser. - st = st.strip() - sp = st.split() - tz = sp[-1] - if tz and (tz.lower() in ValidZones): - self._timezone_naive = False - st = ' '.join(sp[:-1]) - else: - self._timezone_naive = True - tz = None # Decide later, since the default time zone - # could depend on the date. - - ints = [] - i = 0 - len_st = len(st) - while i < len_st: - while i < len_st and st[i] in SPACE_CHARS: - i += 1 - if i < len_st and st[i] in DELIMITERS: - d = st[i] - i += 1 - else: - d = '' - while i < len_st and st[i] in SPACE_CHARS: - i += 1 - - # The float pattern needs to look back 1 character, because it - # actually looks for a preceding colon like ':33.33'. This is - # needed to avoid accidentally matching the date part of a - # dot-separated date string such as '1999.12.31'. - if i > 0: - b = i - 1 - else: - b = i - - ts_results = FLT_PATTERN.match(st, b) - if ts_results: - s = ts_results.group(1) - i = i + len(s) - ints.append(float(s)) - continue - - ts_results = INT_PATTERN.match(st, i) - if ts_results: - s = ts_results.group(0) - - ls = len(s) - i = i + ls - if (ls == 4 and d and d in '+-' and - (len(ints) + (not not month) >= 3)): - tz = '{}{}'.format(d, s) - else: - v = int(s) - ints.append(v) - continue - - ts_results = NAME_PATTERN.match(st, i) - if ts_results: - s = ts_results.group(0).lower() - i = i + len(s) - if i < len_st and st[i] == '.': - i += 1 - # Check for month name: - _v = _MONTHMAP.get(s) - if _v is not None: - if month is None: - month = _v - else: - raise SyntaxError(st) - continue - # Check for time modifier: - if s in TimeModifiers: - if tm is None: - tm = s - else: - raise SyntaxError(st) - continue - # Check for and skip day of week: - if s in _DAYMAP: - continue - - raise SyntaxError(st) - - day = None - if ints[-1] > 60 and d not in ('.', ':', '/') and len(ints) > 2: - year = ints[-1] - del ints[-1] - if month: - day = ints[0] - del ints[:1] - else: - if datefmt == "us": - month = ints[0] - day = ints[1] - else: - month = ints[1] - day = ints[0] - del ints[:2] - elif month: - if len(ints) > 1: - if ints[0] > 31: - year = ints[0] - day = ints[1] - else: - year = ints[1] - day = ints[0] - del ints[:2] - elif len(ints) > 2: - if ints[0] > 31: - year = ints[0] - if ints[1] > 12: - day = ints[1] - month = ints[2] - else: - day = ints[2] - month = ints[1] - if ints[1] > 31: - year = ints[1] - if ints[0] > 12 and ints[2] <= 12: - day = ints[0] - month = ints[2] - elif ints[2] > 12 and ints[0] <= 12: - day = ints[2] - month = ints[0] - elif ints[2] > 31: - year = ints[2] - if ints[0] > 12: - day = ints[0] - month = ints[1] - else: - if datefmt == "us": - day = ints[1] - month = ints[0] - else: - day = ints[0] - month = ints[1] - - elif ints[0] <= 12: - month = ints[0] - day = ints[1] - year = ints[2] - del ints[:3] - - if day is None: - # Use today's date. - year, month, day = localtime(time())[:3] - - year = _correctYear(year) - if year < 1000: - raise SyntaxError(st) - - leap = year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) - try: - if not day or day > _MONTH_LEN[leap][month]: - raise DateError(st) - except IndexError: - raise DateError(st) - - tod = 0 - if ints: - i = ints[0] - # Modify hour to reflect am/pm - if tm and (tm == 'pm') and i < 12: - i += 12 - if tm and (tm == 'am') and i == 12: - i = 0 - if i > 24: - raise TimeError(st) - tod = tod + int(i) * 3600 - del ints[0] - if ints: - i = ints[0] - if i > 60: - raise TimeError(st) - tod = tod + int(i) * 60 - del ints[0] - if ints: - i = ints[0] - if i > 60: - raise TimeError(st) - tod = tod + i - del ints[0] - if ints: - raise SyntaxError(st) - - tod_int = int(math.floor(tod)) - ms = tod - tod_int - hr, mn, sc = _calcHMS(tod_int, ms) - if not tz: - # Figure out what time zone it is in the local area - # on the given date. - x = _calcDependentSecond2(year, month, day, hr, mn, sc) - tz = self._calcTimezoneName(x, ms) - - return year, month, day, hr, mn, sc, tz - - # Internal methods - def _validDate(self, y, m, d): - if m < 1 or m > 12 or y < 0 or d < 1 or d > 31: - return 0 - return d <= _MONTH_LEN[ - (y % 4 == 0 and (y % 100 != 0 or y % 400 == 0))][m] - - def _validTime(self, h, m, s): - return h >= 0 and h <= 23 and m >= 0 and m <= 59 and s >= 0 and s < 60 - - def __getattr__(self, name): - if '%' in name: - return strftimeFormatter(self, name) - raise AttributeError(name) - - # Conversion and comparison methods - - def timeTime(self): - """Return the date/time as a floating-point number in UTC, - in the format used by the Python time module. - - Note that it is possible to create date/time values with - DateTime that have no meaningful value to the time module. - """ - return self._micros / 1000000.0 - - def toZone(self, z): - """Return a DateTime with the value as the current - object, represented in the indicated timezone. - """ - t, tz = self._t, _TZINFO._zmap[z.lower()] - micros = self.micros() - tznaive = False # you're performing a timzone change, can't be naive - - try: - # Try to use time module for speed. - yr, mo, dy, hr, mn, sc = safegmtime(t + _tzoffset(tz, t))[:6] - sc = self._second - return self.__class__(yr, mo, dy, hr, mn, sc, tz, t, - self._d, self.time, micros, tznaive) - except Exception: - # gmtime can't perform the calculation in the given range. - # Calculate the difference between the two time zones. - tzdiff = _tzoffset(tz, t) - _tzoffset(self._tz, t) - if tzdiff == 0: - return self - sc = self._second - ms = sc - math.floor(sc) - x = _calcDependentSecond2(self._year, self._month, self._day, - self._hour, self._minute, sc) - x_new = x + tzdiff - yr, mo, dy, hr, mn, sc = _calcYMDHMS(x_new, ms) - return self.__class__(yr, mo, dy, hr, mn, sc, tz, t, - self._d, self.time, micros, tznaive) - - def isFuture(self): - """Return true if this object represents a date/time - later than the time of the call. - """ - return (self._t > time()) - - def isPast(self): - """Return true if this object represents a date/time - earlier than the time of the call. - """ - return (self._t < time()) - - def isCurrentYear(self): - """Return true if this object represents a date/time - that falls within the current year, in the context - of this object's timezone representation. - """ - t = time() - return safegmtime(t + _tzoffset(self._tz, t))[0] == self._year - - def isCurrentMonth(self): - """Return true if this object represents a date/time - that falls within the current month, in the context - of this object's timezone representation. - """ - t = time() - gmt = safegmtime(t + _tzoffset(self._tz, t)) - return gmt[0] == self._year and gmt[1] == self._month - - def isCurrentDay(self): - """Return true if this object represents a date/time - that falls within the current day, in the context - of this object's timezone representation. - """ - t = time() - gmt = safegmtime(t + _tzoffset(self._tz, t)) - return (gmt[0] == self._year and gmt[1] == self._month and - gmt[2] == self._day) - - def isCurrentHour(self): - """Return true if this object represents a date/time - that falls within the current hour, in the context - of this object's timezone representation. - """ - t = time() - gmt = safegmtime(t + _tzoffset(self._tz, t)) - return (gmt[0] == self._year and gmt[1] == self._month and - gmt[2] == self._day and gmt[3] == self._hour) - - def isCurrentMinute(self): - """Return true if this object represents a date/time - that falls within the current minute, in the context - of this object's timezone representation. - """ - t = time() - gmt = safegmtime(t + _tzoffset(self._tz, t)) - return (gmt[0] == self._year and gmt[1] == self._month and - gmt[2] == self._day and gmt[3] == self._hour and - gmt[4] == self._minute) - - def earliestTime(self): - """Return a new DateTime object that represents the earliest - possible time (in whole seconds) that still falls within - the current object's day, in the object's timezone context. - """ - return self.__class__( - self._year, self._month, self._day, 0, 0, 0, self._tz) - - def latestTime(self): - """Return a new DateTime object that represents the latest - possible time (in whole seconds) that still falls within - the current object's day, in the object's timezone context. - """ - return self.__class__( - self._year, self._month, self._day, 23, 59, 59, self._tz) - - def greaterThan(self, t): - """Compare this DateTime object to another DateTime object - OR a floating point number such as that which is returned - by the Python time module. - - Returns true if the object represents a date/time greater - than the specified DateTime or time module style time. - - Revised to give more correct results through comparison of - long integer microseconds. - """ - if t is None: - return True - if isinstance(t, (float, int)): - return self._micros > long(t * 1000000) - try: - return self._micros > t._micros - except AttributeError: - return self._micros > t - - __gt__ = greaterThan - - def greaterThanEqualTo(self, t): - """Compare this DateTime object to another DateTime object - OR a floating point number such as that which is returned - by the Python time module. - - Returns true if the object represents a date/time greater - than or equal to the specified DateTime or time module style - time. - - Revised to give more correct results through comparison of - long integer microseconds. - """ - if t is None: - return True - if isinstance(t, (float, int)): - return self._micros >= long(t * 1000000) - try: - return self._micros >= t._micros - except AttributeError: - return self._micros >= t - - __ge__ = greaterThanEqualTo - - def equalTo(self, t): - """Compare this DateTime object to another DateTime object - OR a floating point number such as that which is returned - by the Python time module. - - Returns true if the object represents a date/time equal to - the specified DateTime or time module style time. - - Revised to give more correct results through comparison of - long integer microseconds. - """ - if t is None: - return False - if isinstance(t, (float, int)): - return self._micros == long(t * 1000000) - try: - return self._micros == t._micros - except AttributeError: - return self._micros == t - - def notEqualTo(self, t): - """Compare this DateTime object to another DateTime object - OR a floating point number such as that which is returned - by the Python time module. - - Returns true if the object represents a date/time not equal - to the specified DateTime or time module style time. - - Revised to give more correct results through comparison of - long integer microseconds. - """ - return not self.equalTo(t) - - def __eq__(self, t): - """Compare this DateTime object to another DateTime object. - Return True if their internal state is the same. Two objects - representing the same time in different timezones are regared as - unequal. Use the equalTo method if you are only interested in them - referring to the same moment in time. - """ - if not isinstance(t, DateTime): - return False - return (self._micros, self._tz) == (t._micros, t._tz) - - def __ne__(self, t): - return not self.__eq__(t) - - def lessThan(self, t): - """Compare this DateTime object to another DateTime object - OR a floating point number such as that which is returned - by the Python time module. - - Returns true if the object represents a date/time less than - the specified DateTime or time module style time. - - Revised to give more correct results through comparison of - long integer microseconds. - """ - if t is None: - return False - if isinstance(t, (float, int)): - return self._micros < long(t * 1000000) - try: - return self._micros < t._micros - except AttributeError: - return self._micros < t - - __lt__ = lessThan - - def lessThanEqualTo(self, t): - """Compare this DateTime object to another DateTime object - OR a floating point number such as that which is returned - by the Python time module. - - Returns true if the object represents a date/time less than - or equal to the specified DateTime or time module style time. - - Revised to give more correct results through comparison of - long integer microseconds. - """ - if t is None: - return False - if isinstance(t, (float, int)): - return self._micros <= long(t * 1000000) - try: - return self._micros <= t._micros - except AttributeError: - return self._micros <= t - - __le__ = lessThanEqualTo - - def isLeapYear(self): - """Return true if the current year (in the context of the - object's timezone) is a leap year. - """ - return (self._year % 4 == 0 and - (self._year % 100 != 0 or self._year % 400 == 0)) - - def dayOfYear(self): - """Return the day of the year, in context of the timezone - representation of the object. - """ - d = int(self._d + (_tzoffset(self._tz, self._t) / 86400.0)) - return int((d + jd1901) - _julianday(self._year, 1, 0)) - - # Component access - def parts(self): - """Return a tuple containing the calendar year, month, - day, hour, minute second and timezone of the object. - """ - return (self._year, self._month, self._day, self._hour, - self._minute, self._second, self._tz) - - def timezone(self): - """Return the timezone in which the object is represented.""" - return self._tz - - def tzoffset(self): - """Return the timezone offset for the objects timezone.""" - return _tzoffset(self._tz, self._t) - - def year(self): - """Return the calendar year of the object.""" - return self._year - - def month(self): - """Return the month of the object as an integer.""" - return self._month - - @property - def _fmon(self): - return _MONTHS[self._month] - - def Month(self): - """Return the full month name.""" - return self._fmon - - @property - def _amon(self): - return _MONTHS_A[self._month] - - def aMonth(self): - """Return the abbreviated month name.""" - return self._amon - - def Mon(self): - """Compatibility: see aMonth.""" - return self._amon - - @property - def _pmon(self): - return _MONTHS_P[self._month] - - def pMonth(self): - """Return the abbreviated (with period) month name.""" - return self._pmon - - def Mon_(self): - """Compatibility: see pMonth.""" - return self._pmon - - def day(self): - """Return the integer day.""" - return self._day - - @property - def _fday(self): - return _DAYS[self._dayoffset] - - def Day(self): - """Return the full name of the day of the week.""" - return self._fday - - def DayOfWeek(self): - """Compatibility: see Day.""" - return self._fday - - @property - def _aday(self): - return _DAYS_A[self._dayoffset] - - def aDay(self): - """Return the abbreviated name of the day of the week.""" - return self._aday - - @property - def _pday(self): - return _DAYS_P[self._dayoffset] - - def pDay(self): - """Return the abbreviated (with period) name of the day of the week.""" - return self._pday - - def Day_(self): - """Compatibility: see pDay.""" - return self._pday - - def dow(self): - """Return the integer day of the week, where Sunday is 0.""" - return self._dayoffset - - def dow_1(self): - """Return the integer day of the week, where Sunday is 1.""" - return self._dayoffset + 1 - - @property - def _pmhour(self): - hr = self._hour - if hr > 12: - return hr - 12 - return hr or 12 - - def h_12(self): - """Return the 12-hour clock representation of the hour.""" - return self._pmhour - - def h_24(self): - """Return the 24-hour clock representation of the hour.""" - return self._hour - - @property - def _pm(self): - hr = self._hour - if hr >= 12: - return 'pm' - return 'am' - - def ampm(self): - """Return the appropriate time modifier (am or pm).""" - return self._pm - - def hour(self): - """Return the 24-hour clock representation of the hour.""" - return self._hour - - def minute(self): - """Return the minute.""" - return self._minute - - def second(self): - """Return the second.""" - return self._second - - def millis(self): - """Return the millisecond since the epoch in GMT.""" - return self._micros // 1000 - - def micros(self): - """Return the microsecond since the epoch in GMT.""" - return self._micros - - def timezoneNaive(self): - """The Python datetime module introduces the idea of distinguishing - between timezone aware and timezone naive datetime values. For lossless - conversion to and from datetime.datetime we record this - information using True / False. DateTime makes no distinction, if we - don't have any information we return None here. - """ - try: - return self._timezone_naive - except AttributeError: - return None - - def strftime(self, format): - """Format the date/time using the *current timezone representation*.""" - x = _calcDependentSecond2(self._year, self._month, self._day, - self._hour, self._minute, self._second) - ltz = self._calcTimezoneName(x, 0) - tzdiff = _tzoffset(ltz, self._t) - _tzoffset(self._tz, self._t) - zself = self + tzdiff / 86400.0 - microseconds = int((zself._second - zself._nearsec) * 1000000) - unicode_format = False - if isinstance(format, explicit_unicode_type): - format = format.encode('utf-8') - unicode_format = True - ds = datetime(zself._year, zself._month, zself._day, zself._hour, - zself._minute, int(zself._nearsec), - microseconds).strftime(format) - if unicode_format: - return ds.decode('utf-8') - return ds - - # General formats from previous DateTime - def Date(self): - """Return the date string for the object.""" - return "%s/%2.2d/%2.2d" % (self._year, self._month, self._day) - - def Time(self): - """Return the time string for an object to the nearest second.""" - return '%2.2d:%2.2d:%2.2d' % (self._hour, self._minute, self._nearsec) - - def TimeMinutes(self): - """Return the time string for an object not showing seconds.""" - return '%2.2d:%2.2d' % (self._hour, self._minute) - - def AMPM(self): - """Return the time string for an object to the nearest second.""" - return '%2.2d:%2.2d:%2.2d %s' % ( - self._pmhour, self._minute, self._nearsec, self._pm) - - def AMPMMinutes(self): - """Return the time string for an object not showing seconds.""" - return '%2.2d:%2.2d %s' % (self._pmhour, self._minute, self._pm) - - def PreciseTime(self): - """Return the time string for the object.""" - return '%2.2d:%2.2d:%06.3f' % (self._hour, self._minute, self._second) - - def PreciseAMPM(self): - """Return the time string for the object.""" - return '%2.2d:%2.2d:%06.3f %s' % ( - self._pmhour, self._minute, self._second, self._pm) - - def yy(self): - """Return calendar year as a 2 digit string.""" - return str(self._year)[-2:] - - def mm(self): - """Return month as a 2 digit string.""" - return '%02d' % self._month - - def dd(self): - """Return day as a 2 digit string.""" - return '%02d' % self._day - - def rfc822(self): - """Return the date in RFC 822 format.""" - tzoffset = _tzoffset2rfc822zone(_tzoffset(self._tz, self._t)) - return '%s, %2.2d %s %d %2.2d:%2.2d:%2.2d %s' % ( - self._aday, self._day, self._amon, self._year, - self._hour, self._minute, self._nearsec, tzoffset) - - # New formats - def fCommon(self): - """Return a string representing the object's value - in the format: March 1, 1997 1:45 pm. - """ - return '%s %s, %4.4d %s:%2.2d %s' % ( - self._fmon, self._day, self._year, self._pmhour, - self._minute, self._pm) - - def fCommonZ(self): - """Return a string representing the object's value - in the format: March 1, 1997 1:45 pm US/Eastern. - """ - return '%s %s, %4.4d %d:%2.2d %s %s' % ( - self._fmon, self._day, self._year, self._pmhour, - self._minute, self._pm, self._tz) - - def aCommon(self): - """Return a string representing the object's value - in the format: Mar 1, 1997 1:45 pm. - """ - return '%s %s, %4.4d %s:%2.2d %s' % ( - self._amon, self._day, self._year, self._pmhour, - self._minute, self._pm) - - def aCommonZ(self): - """Return a string representing the object's value - in the format: Mar 1, 1997 1:45 pm US/Eastern. - """ - return '%s %s, %4.4d %d:%2.2d %s %s' % ( - self._amon, self._day, self._year, self._pmhour, - self._minute, self._pm, self._tz) - - def pCommon(self): - """Return a string representing the object's value - in the format: Mar. 1, 1997 1:45 pm. - """ - return '%s %s, %4.4d %s:%2.2d %s' % ( - self._pmon, self._day, self._year, self._pmhour, - self._minute, self._pm) - - def pCommonZ(self): - """Return a string representing the object's value - in the format: Mar. 1, 1997 1:45 pm US/Eastern. - """ - return '%s %s, %4.4d %d:%2.2d %s %s' % ( - self._pmon, self._day, self._year, self._pmhour, - self._minute, self._pm, self._tz) - - def ISO(self): - """Return the object in ISO standard format. - - Note: this is *not* ISO 8601-format! See the ISO8601 and - HTML4 methods below for ISO 8601-compliant output. - - Dates are output as: YYYY-MM-DD HH:MM:SS - """ - return "%.4d-%.2d-%.2d %.2d:%.2d:%.2d" % ( - self._year, self._month, self._day, - self._hour, self._minute, self._second) - - def ISO8601(self): - """Return the object in ISO 8601-compatible format containing the - date, time with seconds-precision and the time zone identifier. - - See: http://www.w3.org/TR/NOTE-datetime - - Dates are output as: YYYY-MM-DDTHH:MM:SSTZD - T is a literal character. - TZD is Time Zone Designator, format +HH:MM or -HH:MM - - If the instance is timezone naive (it was not specified with a timezone - when it was constructed) then the timezone is omitted. - - The HTML4 method below offers the same formatting, but converts - to UTC before returning the value and sets the TZD "Z". - """ - if self.timezoneNaive(): - return "%0.4d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d" % ( - self._year, self._month, self._day, - self._hour, self._minute, self._second) - tzoffset = _tzoffset2iso8601zone(_tzoffset(self._tz, self._t)) - return "%0.4d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d%s" % ( - self._year, self._month, self._day, - self._hour, self._minute, self._second, tzoffset) - - def HTML4(self): - """Return the object in the format used in the HTML4.0 specification, - one of the standard forms in ISO8601. - - See: http://www.w3.org/TR/NOTE-datetime - - Dates are output as: YYYY-MM-DDTHH:MM:SSZ - T, Z are literal characters. - The time is in UTC. - """ - newdate = self.toZone('UTC') - return "%0.4d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2dZ" % ( - newdate._year, newdate._month, newdate._day, - newdate._hour, newdate._minute, newdate._second) - - def asdatetime(self): - """Return a standard library datetime.datetime - """ - tznaive = self.timezoneNaive() - if tznaive: - tzinfo = None - else: - tzinfo = _TZINFO[self._tz].tzinfo - second = int(self._second) - microsec = self.micros() % 1000000 - dt = datetime(self._year, self._month, self._day, self._hour, - self._minute, second, microsec, tzinfo) - return dt - - def utcdatetime(self): - """Convert the time to UTC and return a timezone naive datetime object - """ - utc = self.toZone('UTC') - second = int(utc._second) - microsec = utc.micros() % 1000000 - dt = datetime(utc._year, utc._month, utc._day, utc._hour, - utc._minute, second, microsec) - return dt - - def __add__(self, other): - """A DateTime may be added to a number and a number may be - added to a DateTime; two DateTimes cannot be added. - """ - if hasattr(other, '_t'): - raise DateTimeError('Cannot add two DateTimes') - o = float(other) - tz = self._tz - omicros = round(o * 86400000000) - tmicros = self.micros() + omicros - t = tmicros / 1000000.0 - d = (tmicros + long(EPOCH * 1000000)) / 86400000000.0 - s = d - math.floor(d) - ms = t - math.floor(t) - x = _calcDependentSecond(tz, t) - yr, mo, dy, hr, mn, sc = _calcYMDHMS(x, ms) - return self.__class__(yr, mo, dy, hr, mn, sc, self._tz, - t, d, s, tmicros, self.timezoneNaive()) - - __radd__ = __add__ - - def __sub__(self, other): - """Either a DateTime or a number may be subtracted from a - DateTime, however, a DateTime may not be subtracted from - a number. - """ - if hasattr(other, '_d'): - return (self.micros() - other.micros()) / 86400000000.0 - else: - return self.__add__(-(other)) - - def __repr__(self): - """Convert a DateTime to a string that looks like a Python - expression. - """ - return '{}(\'{}\')'.format(self.__class__.__name__, str(self)) - - def __str__(self): - """Convert a DateTime to a string.""" - y, m, d = self._year, self._month, self._day - h, mn, s, t = self._hour, self._minute, self._second, self._tz - if s == int(s): - # A whole number of seconds -- suppress milliseconds. - return '%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s' % ( - y, m, d, h, mn, s, t) - else: - # s is already rounded to the nearest microsecond, and - # it's not a whole number of seconds. Be sure to print - # 2 digits before the decimal point. - return '%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%06.6f %s' % ( - y, m, d, h, mn, s, t) - - def __format__(self, fmt): - """Render a DateTime in an f-string.""" - if not isinstance(fmt, str): - raise TypeError("must be str, not %s" % type(fmt).__name__) - if len(fmt) != 0: - return self.strftime(fmt) - return str(self) - - def __hash__(self): - """Compute a hash value for a DateTime.""" - return int(((self._year % 100 * 12 + self._month) * 31 + - self._day + self.time) * 100) - - def __int__(self): - """Convert to an integer number of seconds since the epoch (gmt).""" - return int(self.micros() // 1000000) - - def __long__(self): - """Convert to a long-int number of seconds since the epoch (gmt).""" - return long(self.micros() // 1000000) # pragma: PY2 - - def __float__(self): - """Convert to floating-point number of seconds since the epoch (gmt). - """ - return self.micros() / 1000000.0 - - @property - def _t(self): - return self._micros / 1000000.0 - - def _parse_iso8601(self, s): - # preserve the previously implied contract - # who knows where this could be used... - return self._parse_iso8601_preserving_tznaive(s)[:7] - - def _parse_iso8601_preserving_tznaive(self, s): - try: - return self.__parse_iso8601(s) - except IndexError: - raise SyntaxError( - 'Not an ISO 8601 compliant date string: "%s"' % s) - - def __parse_iso8601(self, s): - """Parse an ISO 8601 compliant date. - - See: http://en.wikipedia.org/wiki/ISO_8601 - """ - month = day = week_day = 1 - year = hour = minute = seconds = hour_off = min_off = 0 - tznaive = True - - iso8601 = iso8601Match(s.strip()) - fields = iso8601 and iso8601.groupdict() or {} - if not iso8601 or fields.get('garbage'): - raise IndexError - - if fields['year']: - year = int(fields['year']) - if fields['month']: - month = int(fields['month']) - if fields['day']: - day = int(fields['day']) - - if fields['year_day']: - d = DateTime('%s-01-01' % year) + int(fields['year_day']) - 1 - month = d.month() - day = d.day() - - if fields['week']: - week = int(fields['week']) - if fields['week_day']: - week_day = int(fields['week_day']) - d = DateTime('%s-01-04' % year) - d = d - (d.dow() + 6) % 7 + week * 7 + week_day - 8 - month = d.month() - day = d.day() - - if fields['hour']: - hour = int(fields['hour']) - - if fields['minute']: - minute = int(fields['minute']) - elif fields['fraction']: - minute = 60.0 * float('0.%s' % fields['fraction']) - seconds, minute = math.modf(minute) - minute = int(minute) - seconds = 60.0 * seconds - # Avoid reprocess when handling seconds, bellow - fields['fraction'] = None - - if fields['second']: - seconds = int(fields['second']) - if fields['fraction']: - seconds = seconds + float('0.%s' % fields['fraction']) - elif fields['fraction']: - seconds = 60.0 * float('0.%s' % fields['fraction']) - - if fields['hour_off']: - hour_off = int(fields['hour_off']) - if fields['signal'] == '-': - hour_off *= -1 - - if fields['min_off']: - min_off = int(fields['min_off']) - - if fields['signal'] or fields['Z']: - tznaive = False - else: - tznaive = True - - # Differ from the specification here. To preserve backwards - # compatibility assume a default timezone == UTC. - tz = 'GMT%+03d%02d' % (hour_off, min_off) - - return year, month, day, hour, minute, seconds, tz, tznaive - - def JulianDay(self): - """Return the Julian day. - - See: https://www.tondering.dk/claus/cal/julperiod.php#formula - """ - a = (14 - self._month) // 12 - y = self._year + 4800 - a - m = self._month + (12 * a) - 3 - return (self._day + (153 * m + 2) // 5 + 365 * y + - y // 4 - y // 100 + y // 400 - 32045) - - def week(self): - """Return the week number according to ISO. - - See: https://www.tondering.dk/claus/cal/week.php#weekno - """ - J = self.JulianDay() - d4 = (J + 31741 - (J % 7)) % 146097 % 36524 % 1461 - L = d4 // 1460 - d1 = ((d4 - L) % 365) + L - return d1 // 7 + 1 - - def encode(self, out): - """Encode value for XML-RPC.""" - out.write('') - out.write(self.ISO8601()) - out.write('\n') - - -# Provide the _dt_reconstructor function here, in case something -# accidentally creates a reference to this function - -orig_reconstructor = copy_reg._reconstructor - - -def _dt_reconstructor(cls, base, state): - if cls is DateTime: - return cls(state) - return orig_reconstructor(cls, base, state) diff --git a/venv/Lib/site-packages/DateTime/DateTime.txt b/venv/Lib/site-packages/DateTime/DateTime.txt deleted file mode 100644 index aaa9f8f..0000000 --- a/venv/Lib/site-packages/DateTime/DateTime.txt +++ /dev/null @@ -1,785 +0,0 @@ -The DateTime package -==================== - -Encapsulation of date/time values. - - -Function Timezones() --------------------- - -Returns the list of recognized timezone names: - - >>> from DateTime import Timezones - >>> zones = set(Timezones()) - -Almost all of the standard pytz timezones are included, with the exception -of some commonly-used but ambiguous abbreviations, where historical Zope -usage conflicts with the name used by pytz: - - >>> import pytz - >>> [x for x in pytz.all_timezones if x not in zones] - ['CET', 'EET', 'EST', 'MET', 'MST', 'WET'] - -Class DateTime --------------- - -DateTime objects represent instants in time and provide interfaces for -controlling its representation without affecting the absolute value of -the object. - -DateTime objects may be created from a wide variety of string or -numeric data, or may be computed from other DateTime objects. -DateTimes support the ability to convert their representations to many -major timezones, as well as the ability to create a DateTime object -in the context of a given timezone. - -DateTime objects provide partial numerical behavior: - -* Two date-time objects can be subtracted to obtain a time, in days - between the two. - -* A date-time object and a positive or negative number may be added to - obtain a new date-time object that is the given number of days later - than the input date-time object. - -* A positive or negative number and a date-time object may be added to - obtain a new date-time object that is the given number of days later - than the input date-time object. - -* A positive or negative number may be subtracted from a date-time - object to obtain a new date-time object that is the given number of - days earlier than the input date-time object. - -DateTime objects may be converted to integer, long, or float numbers -of days since January 1, 1901, using the standard int, long, and float -functions (Compatibility Note: int, long and float return the number -of days since 1901 in GMT rather than local machine timezone). -DateTime objects also provide access to their value in a float format -usable with the Python time module, provided that the value of the -object falls in the range of the epoch-based time module. - -A DateTime object should be considered immutable; all conversion and numeric -operations return a new DateTime object rather than modify the current object. - -A DateTime object always maintains its value as an absolute UTC time, -and is represented in the context of some timezone based on the -arguments used to create the object. A DateTime object's methods -return values based on the timezone context. - -Note that in all cases the local machine timezone is used for -representation if no timezone is specified. - -Constructor for DateTime ------------------------- - -DateTime() returns a new date-time object. DateTimes may be created -with from zero to seven arguments: - -* If the function is called with no arguments, then the current date/ - time is returned, represented in the timezone of the local machine. - -* If the function is invoked with a single string argument which is a - recognized timezone name, an object representing the current time is - returned, represented in the specified timezone. - -* If the function is invoked with a single string argument - representing a valid date/time, an object representing that date/ - time will be returned. - - As a general rule, any date-time representation that is recognized - and unambiguous to a resident of North America is acceptable. (The - reason for this qualification is that in North America, a date like: - 2/1/1994 is interpreted as February 1, 1994, while in some parts of - the world, it is interpreted as January 2, 1994.) A date/ time - string consists of two components, a date component and an optional - time component, separated by one or more spaces. If the time - component is omitted, 12:00am is assumed. - - Any recognized timezone name specified as the final element of the - date/time string will be used for computing the date/time value. - (If you create a DateTime with the string, - "Mar 9, 1997 1:45pm US/Pacific", the value will essentially be the - same as if you had captured time.time() at the specified date and - time on a machine in that timezone). If no timezone is passed, then - the timezone configured on the local machine will be used, **except** - that if the date format matches ISO 8601 ('YYYY-MM-DD'), the instance - will use UTC / GMT+0 as the timezone. - - o Returns current date/time, represented in US/Eastern: - - >>> from DateTime import DateTime - >>> e = DateTime('US/Eastern') - >>> e.timezone() - 'US/Eastern' - - o Returns specified time, represented in local machine zone: - - >>> x = DateTime('1997/3/9 1:45pm') - >>> x.parts() # doctest: +ELLIPSIS - (1997, 3, 9, 13, 45, ...) - - o Specified time in local machine zone, verbose format: - - >>> y = DateTime('Mar 9, 1997 13:45:00') - >>> y.parts() # doctest: +ELLIPSIS - (1997, 3, 9, 13, 45, ...) - >>> y == x - True - - o Specified time in UTC via ISO 8601 rule: - - >>> z = DateTime('2014-03-24') - >>> z.parts() # doctest: +ELLIPSIS - (2014, 3, 24, 0, 0, ...) - >>> z.timezone() - 'GMT+0' - - The date component consists of year, month, and day values. The - year value must be a one-, two-, or four-digit integer. If a one- - or two-digit year is used, the year is assumed to be in the - twentieth century. The month may an integer, from 1 to 12, a month - name, or a month abbreviation, where a period may optionally follow - the abbreviation. The day must be an integer from 1 to the number of - days in the month. The year, month, and day values may be separated - by periods, hyphens, forward slashes, or spaces. Extra spaces are - permitted around the delimiters. Year, month, and day values may be - given in any order as long as it is possible to distinguish the - components. If all three components are numbers that are less than - 13, then a month-day-year ordering is assumed. - - The time component consists of hour, minute, and second values - separated by colons. The hour value must be an integer between 0 - and 23 inclusively. The minute value must be an integer between 0 - and 59 inclusively. The second value may be an integer value - between 0 and 59.999 inclusively. The second value or both the - minute and second values may be omitted. The time may be followed - by am or pm in upper or lower case, in which case a 12-hour clock is - assumed. - -* If the DateTime function is invoked with a single numeric argument, - the number is assumed to be either a floating point value such as - that returned by time.time(), or a number of days after January 1, - 1901 00:00:00 UTC. - - A DateTime object is returned that represents either the GMT value - of the time.time() float represented in the local machine's - timezone, or that number of days after January 1, 1901. Note that - the number of days after 1901 need to be expressed from the - viewpoint of the local machine's timezone. A negative argument will - yield a date-time value before 1901. - -* If the function is invoked with two numeric arguments, then the - first is taken to be an integer year and the second argument is - taken to be an offset in days from the beginning of the year, in the - context of the local machine timezone. The date-time value returned - is the given offset number of days from the beginning of the given - year, represented in the timezone of the local machine. The offset - may be positive or negative. Two-digit years are assumed to be in - the twentieth century. - -* If the function is invoked with two arguments, the first a float - representing a number of seconds past the epoch in GMT (such as - those returned by time.time()) and the second a string naming a - recognized timezone, a DateTime with a value of that GMT time will - be returned, represented in the given timezone. - - >>> import time - >>> t = time.time() - - Time t represented as US/Eastern: - - >>> now_east = DateTime(t, 'US/Eastern') - - Time t represented as US/Pacific: - - >>> now_west = DateTime(t, 'US/Pacific') - - Only their representations are different: - - >>> now_east.equalTo(now_west) - True - -* If the function is invoked with three or more numeric arguments, - then the first is taken to be an integer year, the second is taken - to be an integer month, and the third is taken to be an integer day. - If the combination of values is not valid, then a DateTimeError is - raised. One- or two-digit years up to 69 are assumed to be in the - 21st century, whereas values 70-99 are assumed to be 20th century. - The fourth, fifth, and sixth arguments are floating point, positive - or negative offsets in units of hours, minutes, and days, and - default to zero if not given. An optional string may be given as - the final argument to indicate timezone (the effect of this is as if - you had taken the value of time.time() at that time on a machine in - the specified timezone). - -If a string argument passed to the DateTime constructor cannot be -parsed, it will raise SyntaxError. Invalid date, time, or -timezone components will raise a DateTimeError. - -The module function Timezones() will return a list of the timezones -recognized by the DateTime module. Recognition of timezone names is -case-insensitive. - -Instance Methods for DateTime (IDateTime interface) ---------------------------------------------------- - -Conversion and comparison methods -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* ``timeTime()`` returns the date/time as a floating-point number in - UTC, in the format used by the Python time module. Note that it is - possible to create date /time values with DateTime that have no - meaningful value to the time module, and in such cases a - DateTimeError is raised. A DateTime object's value must generally - be between Jan 1, 1970 (or your local machine epoch) and Jan 2038 to - produce a valid time.time() style value. - - >>> dt = DateTime('Mar 9, 1997 13:45:00 US/Eastern') - >>> dt.timeTime() - 857933100.0 - - >>> DateTime('2040/01/01 UTC').timeTime() - 2208988800.0 - - >>> DateTime('1900/01/01 UTC').timeTime() - -2208988800.0 - -* ``toZone(z)`` returns a DateTime with the value as the current - object, represented in the indicated timezone: - - >>> dt.toZone('UTC') - DateTime('1997/03/09 18:45:00 UTC') - - >>> dt.toZone('UTC').equalTo(dt) - True - -* ``isFuture()`` returns true if this object represents a date/time - later than the time of the call: - - >>> dt.isFuture() - False - >>> DateTime('Jan 1 3000').isFuture() # not time-machine safe! - True - -* ``isPast()`` returns true if this object represents a date/time - earlier than the time of the call: - - >>> dt.isPast() - True - >>> DateTime('Jan 1 3000').isPast() # not time-machine safe! - False - -* ``isCurrentYear()`` returns true if this object represents a - date/time that falls within the current year, in the context of this - object's timezone representation: - - >>> dt.isCurrentYear() - False - >>> DateTime().isCurrentYear() - True - -* ``isCurrentMonth()`` returns true if this object represents a - date/time that falls within the current month, in the context of - this object's timezone representation: - - >>> dt.isCurrentMonth() - False - >>> DateTime().isCurrentMonth() - True - -* ``isCurrentDay()`` returns true if this object represents a - date/time that falls within the current day, in the context of this - object's timezone representation: - - >>> dt.isCurrentDay() - False - >>> DateTime().isCurrentDay() - True - -* ``isCurrentHour()`` returns true if this object represents a - date/time that falls within the current hour, in the context of this - object's timezone representation: - - >>> dt.isCurrentHour() - False - - >>> DateTime().isCurrentHour() - True - -* ``isCurrentMinute()`` returns true if this object represents a - date/time that falls within the current minute, in the context of - this object's timezone representation: - - >>> dt.isCurrentMinute() - False - >>> DateTime().isCurrentMinute() - True - -* ``isLeapYear()`` returns true if the current year (in the context of - the object's timezone) is a leap year: - - >>> dt.isLeapYear() - False - >>> DateTime('Mar 8 2004').isLeapYear() - True - -* ``earliestTime()`` returns a new DateTime object that represents the - earliest possible time (in whole seconds) that still falls within - the current object's day, in the object's timezone context: - - >>> dt.earliestTime() - DateTime('1997/03/09 00:00:00 US/Eastern') - -* ``latestTime()`` return a new DateTime object that represents the - latest possible time (in whole seconds) that still falls within the - current object's day, in the object's timezone context - - >>> dt.latestTime() - DateTime('1997/03/09 23:59:59 US/Eastern') - -Component access -~~~~~~~~~~~~~~~~ - -* ``parts()`` returns a tuple containing the calendar year, month, - day, hour, minute second and timezone of the object - - >>> dt.parts() # doctest: +ELLIPSIS - (1997, 3, 9, 13, 45, ... 'US/Eastern') - -* ``timezone()`` returns the timezone in which the object is represented: - - >>> dt.timezone() in Timezones() - True - -* ``tzoffset()`` returns the timezone offset for the objects timezone: - - >>> dt.tzoffset() - -18000 - -* ``year()`` returns the calendar year of the object: - - >>> dt.year() - 1997 - -* ``month()`` returns the month of the object as an integer: - - >>> dt.month() - 3 - -* ``Month()`` returns the full month name: - - >>> dt.Month() - 'March' - -* ``aMonth()`` returns the abbreviated month name: - - >>> dt.aMonth() - 'Mar' - -* ``pMonth()`` returns the abbreviated (with period) month name: - - >>> dt.pMonth() - 'Mar.' - -* ``day()`` returns the integer day: - - >>> dt.day() - 9 - -* ``Day()`` returns the full name of the day of the week: - - >>> dt.Day() - 'Sunday' - -* ``dayOfYear()`` returns the day of the year, in context of the - timezone representation of the object: - - >>> dt.dayOfYear() - 68 - -* ``aDay()`` returns the abbreviated name of the day of the week: - - >>> dt.aDay() - 'Sun' - -* ``pDay()`` returns the abbreviated (with period) name of the day of - the week: - - >>> dt.pDay() - 'Sun.' - -* ``dow()`` returns the integer day of the week, where Sunday is 0: - - >>> dt.dow() - 0 - -* ``dow_1()`` returns the integer day of the week, where sunday is 1: - - >>> dt.dow_1() - 1 - -* ``h_12()`` returns the 12-hour clock representation of the hour: - - >>> dt.h_12() - 1 - -* ``h_24()`` returns the 24-hour clock representation of the hour: - - >>> dt.h_24() - 13 - -* ``ampm()`` returns the appropriate time modifier (am or pm): - - >>> dt.ampm() - 'pm' - -* ``hour()`` returns the 24-hour clock representation of the hour: - - >>> dt.hour() - 13 - -* ``minute()`` returns the minute: - - >>> dt.minute() - 45 - -* ``second()`` returns the second: - - >>> dt.second() == 0 - True - -* ``millis()`` returns the milliseconds since the epoch in GMT. - - >>> dt.millis() == 857933100000 - True - -strftime() -~~~~~~~~~~ - -See ``tests/test_datetime.py``. - -General formats from previous DateTime -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -* ``Date()`` return the date string for the object: - - >>> dt.Date() - '1997/03/09' - -* ``Time()`` returns the time string for an object to the nearest - second: - - >>> dt.Time() - '13:45:00' - -* ``TimeMinutes()`` returns the time string for an object not showing - seconds: - - >>> dt.TimeMinutes() - '13:45' - -* ``AMPM()`` returns the time string for an object to the nearest second: - - >>> dt.AMPM() - '01:45:00 pm' - -* ``AMPMMinutes()`` returns the time string for an object not showing - seconds: - - >>> dt.AMPMMinutes() - '01:45 pm' - -* ``PreciseTime()`` returns the time string for the object: - - >>> dt.PreciseTime() - '13:45:00.000' - -* ``PreciseAMPM()`` returns the time string for the object: - - >>> dt.PreciseAMPM() - '01:45:00.000 pm' - -* ``yy()`` returns the calendar year as a 2 digit string - - >>> dt.yy() - '97' - -* ``mm()`` returns the month as a 2 digit string - - >>> dt.mm() - '03' - -* ``dd()`` returns the day as a 2 digit string: - - >>> dt.dd() - '09' - -* ``rfc822()`` returns the date in RFC 822 format: - - >>> dt.rfc822() - 'Sun, 09 Mar 1997 13:45:00 -0500' - -New formats -~~~~~~~~~~~ - -* ``fCommon()`` returns a string representing the object's value in - the format: March 9, 1997 1:45 pm: - - >>> dt.fCommon() - 'March 9, 1997 1:45 pm' - -* ``fCommonZ()`` returns a string representing the object's value in - the format: March 9, 1997 1:45 pm US/Eastern: - - >>> dt.fCommonZ() - 'March 9, 1997 1:45 pm US/Eastern' - -* ``aCommon()`` returns a string representing the object's value in - the format: Mar 9, 1997 1:45 pm: - - >>> dt.aCommon() - 'Mar 9, 1997 1:45 pm' - -* ``aCommonZ()`` return a string representing the object's value in - the format: Mar 9, 1997 1:45 pm US/Eastern: - - >>> dt.aCommonZ() - 'Mar 9, 1997 1:45 pm US/Eastern' - -* ``pCommon()`` returns a string representing the object's value in - the format Mar. 9, 1997 1:45 pm: - - >>> dt.pCommon() - 'Mar. 9, 1997 1:45 pm' - -* ``pCommonZ()`` returns a string representing the object's value in - the format: Mar. 9, 1997 1:45 pm US/Eastern: - - >>> dt.pCommonZ() - 'Mar. 9, 1997 1:45 pm US/Eastern' - -* ``ISO()`` returns a string with the date/time in ISO format. Note: - this is not ISO 8601-format! See the ISO8601 and HTML4 methods below - for ISO 8601-compliant output. Dates are output as: YYYY-MM-DD HH:MM:SS - - >>> dt.ISO() - '1997-03-09 13:45:00' - -* ``ISO8601()`` returns the object in ISO 8601-compatible format - containing the date, time with seconds-precision and the time zone - identifier - see http://www.w3.org/TR/NOTE-datetime. Dates are - output as: YYYY-MM-DDTHH:MM:SSTZD (T is a literal character, TZD is - Time Zone Designator, format +HH:MM or -HH:MM). - - The ``HTML4()`` method below offers the same formatting, but - converts to UTC before returning the value and sets the TZD"Z" - - >>> dt.ISO8601() - '1997-03-09T13:45:00-05:00' - - -* ``HTML4()`` returns the object in the format used in the HTML4.0 - specification, one of the standard forms in ISO8601. See - http://www.w3.org/TR/NOTE-datetime. Dates are output as: - YYYY-MM-DDTHH:MM:SSZ (T, Z are literal characters, the time is in - UTC.): - - >>> dt.HTML4() - '1997-03-09T18:45:00Z' - -* ``JulianDay()`` returns the Julian day according to - http://www.tondering.dk/claus/cal/node3.html#sec-calcjd - - >>> dt.JulianDay() - 2450517 - -* ``week()`` returns the week number according to ISO - see http://www.tondering.dk/claus/cal/node6.html#SECTION00670000000000000000 - - >>> dt.week() - 10 - -Deprecated API -~~~~~~~~~~~~~~ - -* DayOfWeek(): see Day() - -* Day_(): see pDay() - -* Mon(): see aMonth() - -* Mon_(): see pMonth - -General Services Provided by DateTime -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -DateTimes can be repr()'ed; the result will be a string indicating how -to make a DateTime object like this: - - >>> repr(dt) - "DateTime('1997/03/09 13:45:00 US/Eastern')" - -When we convert them into a string, we get a nicer string that could -actually be shown to a user: - - >>> str(dt) - '1997/03/09 13:45:00 US/Eastern' - -The hash value of a DateTime is based on the date and time and is -equal for different representations of the DateTime: - - >>> hash(dt) - 3618678 - >>> hash(dt.toZone('UTC')) - 3618678 - -DateTime objects can be compared to other DateTime objects OR floating -point numbers such as the ones which are returned by the Python time -module by using the equalTo method. Using this API, True is returned if the -object represents a date/time equal to the specified DateTime or time module -style time: - - >>> dt.equalTo(dt) - True - >>> dt.equalTo(dt.toZone('UTC')) - True - >>> dt.equalTo(dt.timeTime()) - True - >>> dt.equalTo(DateTime()) - False - -Same goes for inequalities: - - >>> dt.notEqualTo(dt) - False - >>> dt.notEqualTo(dt.toZone('UTC')) - False - >>> dt.notEqualTo(dt.timeTime()) - False - >>> dt.notEqualTo(DateTime()) - True - -Normal equality operations only work with DateTime objects and take the -timezone setting into account: - - >>> dt == dt - True - >>> dt == dt.toZone('UTC') - False - >>> dt == DateTime() - False - - >>> dt != dt - False - >>> dt != dt.toZone('UTC') - True - >>> dt != DateTime() - True - -But the other comparison operations compare the referenced moment in time and -not the representation itself: - - >>> dt > dt - False - >>> DateTime() > dt - True - >>> dt > DateTime().timeTime() - False - >>> DateTime().timeTime() > dt - True - - >>> dt.greaterThan(dt) - False - >>> DateTime().greaterThan(dt) - True - >>> dt.greaterThan(DateTime().timeTime()) - False - - >>> dt >= dt - True - >>> DateTime() >= dt - True - >>> dt >= DateTime().timeTime() - False - >>> DateTime().timeTime() >= dt - True - - >>> dt.greaterThanEqualTo(dt) - True - >>> DateTime().greaterThanEqualTo(dt) - True - >>> dt.greaterThanEqualTo(DateTime().timeTime()) - False - - >>> dt < dt - False - >>> DateTime() < dt - False - >>> dt < DateTime().timeTime() - True - >>> DateTime().timeTime() < dt - False - - >>> dt.lessThan(dt) - False - >>> DateTime().lessThan(dt) - False - >>> dt.lessThan(DateTime().timeTime()) - True - - >>> dt <= dt - True - >>> DateTime() <= dt - False - >>> dt <= DateTime().timeTime() - True - >>> DateTime().timeTime() <= dt - False - - >>> dt.lessThanEqualTo(dt) - True - >>> DateTime().lessThanEqualTo(dt) - False - >>> dt.lessThanEqualTo(DateTime().timeTime()) - True - -Numeric Services Provided by DateTime -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A DateTime may be added to a number and a number may be added to a -DateTime: - - >>> dt + 5 - DateTime('1997/03/14 13:45:00 US/Eastern') - >>> 5 + dt - DateTime('1997/03/14 13:45:00 US/Eastern') - -Two DateTimes cannot be added: - - >>> from DateTime.interfaces import DateTimeError - >>> try: - ... dt + dt - ... print('fail') - ... except DateTimeError: - ... print('ok') - ok - -Either a DateTime or a number may be subtracted from a DateTime, -however, a DateTime may not be subtracted from a number: - - >>> DateTime('1997/03/10 13:45 US/Eastern') - dt - 1.0 - >>> dt - 1 - DateTime('1997/03/08 13:45:00 US/Eastern') - >>> 1 - dt - Traceback (most recent call last): - ... - TypeError: unsupported operand type(s) for -: 'int' and 'DateTime' - -DateTimes can also be converted to integers (number of seconds since -the epoch) and floats: - - >>> int(dt) - 857933100 - >>> float(dt) - 857933100.0 diff --git a/venv/Lib/site-packages/DateTime/__init__.py b/venv/Lib/site-packages/DateTime/__init__.py deleted file mode 100644 index 4e2df6d..0000000 --- a/venv/Lib/site-packages/DateTime/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -############################################################################## -# -# Copyright (c) 2002 Zope Foundation and Contributors. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE -# -############################################################################## - -from .DateTime import DateTime -from .DateTime import Timezones - - -__all__ = ('DateTime', 'Timezones') diff --git a/venv/Lib/site-packages/DateTime/__pycache__/DateTime.cpython-310.pyc b/venv/Lib/site-packages/DateTime/__pycache__/DateTime.cpython-310.pyc deleted file mode 100644 index a724fea7476ba948d6b9e1997383edb6ce3b9764..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58873 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%0D{&l+u}8r^b$w}cHM%by{+ucMO9^Z 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 E0CB`U^Z)<= diff --git a/venv/Lib/site-packages/DateTime/__pycache__/interfaces.cpython-310.pyc b/venv/Lib/site-packages/DateTime/__pycache__/interfaces.cpython-310.pyc deleted file mode 100644 index 75c9926961a5b3b0e3c17908a38e626990716b4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17620 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 CM@J6; diff --git a/venv/Lib/site-packages/DateTime/__pycache__/pytz_support.cpython-310.pyc b/venv/Lib/site-packages/DateTime/__pycache__/pytz_support.cpython-310.pyc deleted file mode 100644 index e205ec9ad607f49c08fd1131c419929c36d7743d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10062 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 diff --git a/venv/Lib/site-packages/DateTime/interfaces.py b/venv/Lib/site-packages/DateTime/interfaces.py deleted file mode 100644 index 80e7707..0000000 --- a/venv/Lib/site-packages/DateTime/interfaces.py +++ /dev/null @@ -1,375 +0,0 @@ -############################################################################## -# -# Copyright (c) 2005 Zope Foundation and Contributors. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE -# -############################################################################## -from zope.interface import Interface - - -class DateTimeError(Exception): - pass - - -class SyntaxError(DateTimeError): - pass - - -class DateError(DateTimeError): - pass - - -class TimeError(DateTimeError): - pass - - -class IDateTime(Interface): - # Conversion and comparison methods - - def localZone(ltm=None): - """Returns the time zone on the given date. The time zone - can change according to daylight savings.""" - - def timeTime(): - """Return the date/time as a floating-point number in UTC, in - the format used by the Python time module. Note that it is - possible to create date/time values with DateTime that have no - meaningful value to the time module.""" - - def toZone(z): - """Return a DateTime with the value as the current object, - represented in the indicated timezone.""" - - def isFuture(): - """Return true if this object represents a date/time later - than the time of the call""" - - def isPast(): - """Return true if this object represents a date/time earlier - than the time of the call""" - - def isCurrentYear(): - """Return true if this object represents a date/time that - falls within the current year, in the context of this - object's timezone representation""" - - def isCurrentMonth(): - """Return true if this object represents a date/time that - falls within the current month, in the context of this - object's timezone representation""" - - def isCurrentDay(): - """Return true if this object represents a date/time that - falls within the current day, in the context of this object's - timezone representation""" - - def isCurrentHour(): - """Return true if this object represents a date/time that - falls within the current hour, in the context of this object's - timezone representation""" - - def isCurrentMinute(): - """Return true if this object represents a date/time that - falls within the current minute, in the context of this - object's timezone representation""" - - def isLeapYear(): - """Return true if the current year (in the context of the - object's timezone) is a leap year""" - - def earliestTime(): - """Return a new DateTime object that represents the earliest - possible time (in whole seconds) that still falls within the - current object's day, in the object's timezone context""" - - def latestTime(): - """Return a new DateTime object that represents the latest - possible time (in whole seconds) that still falls within the - current object's day, in the object's timezone context""" - - def greaterThan(t): - """Compare this DateTime object to another DateTime object OR - a floating point number such as that which is returned by the - Python time module. Returns true if the object represents a - date/time greater than the specified DateTime or time module - style time. Revised to give more correct results through - comparison of long integer milliseconds.""" - - __gt__ = greaterThan - - def greaterThanEqualTo(t): - """Compare this DateTime object to another DateTime object OR - a floating point number such as that which is returned by the - Python time module. Returns true if the object represents a - date/time greater than or equal to the specified DateTime or - time module style time. Revised to give more correct results - through comparison of long integer milliseconds.""" - - __ge__ = greaterThanEqualTo - - def equalTo(t): - """Compare this DateTime object to another DateTime object OR - a floating point number such as that which is returned by the - Python time module. Returns true if the object represents a - date/time equal to the specified DateTime or time module style - time. Revised to give more correct results through comparison - of long integer milliseconds.""" - - __eq__ = equalTo - - def notEqualTo(t): - """Compare this DateTime object to another DateTime object OR - a floating point number such as that which is returned by the - Python time module. Returns true if the object represents a - date/time not equal to the specified DateTime or time module - style time. Revised to give more correct results through - comparison of long integer milliseconds.""" - - __ne__ = notEqualTo - - def lessThan(t): - """Compare this DateTime object to another DateTime object OR - a floating point number such as that which is returned by the - Python time module. Returns true if the object represents a - date/time less than the specified DateTime or time module - style time. Revised to give more correct results through - comparison of long integer milliseconds.""" - - __lt__ = lessThan - - def lessThanEqualTo(t): - """Compare this DateTime object to another DateTime object OR - a floating point number such as that which is returned by the - Python time module. Returns true if the object represents a - date/time less than or equal to the specified DateTime or time - module style time. Revised to give more correct results - through comparison of long integer milliseconds.""" - - __le__ = lessThanEqualTo - - # Component access - - def parts(): - """Return a tuple containing the calendar year, month, day, - hour, minute second and timezone of the object""" - - def timezone(): - """Return the timezone in which the object is represented.""" - - def tzoffset(): - """Return the timezone offset for the objects timezone.""" - - def year(): - """Return the calendar year of the object""" - - def month(): - """Return the month of the object as an integer""" - - def Month(): - """Return the full month name""" - - def aMonth(): - """Return the abbreviated month name.""" - - def Mon(): - """Compatibility: see aMonth""" - - def pMonth(): - """Return the abbreviated (with period) month name.""" - - def Mon_(): - """Compatibility: see pMonth""" - - def day(): - """Return the integer day""" - - def Day(): - """Return the full name of the day of the week""" - - def DayOfWeek(): - """Compatibility: see Day""" - - def dayOfYear(): - """Return the day of the year, in context of the timezone - representation of the object""" - - def aDay(): - """Return the abbreviated name of the day of the week""" - - def pDay(): - """Return the abbreviated (with period) name of the day of the - week""" - - def Day_(): - """Compatibility: see pDay""" - - def dow(): - """Return the integer day of the week, where sunday is 0""" - - def dow_1(): - """Return the integer day of the week, where sunday is 1""" - - def h_12(): - """Return the 12-hour clock representation of the hour""" - - def h_24(): - """Return the 24-hour clock representation of the hour""" - - def ampm(): - """Return the appropriate time modifier (am or pm)""" - - def hour(): - """Return the 24-hour clock representation of the hour""" - - def minute(): - """Return the minute""" - - def second(): - """Return the second""" - - def millis(): - """Return the millisecond since the epoch in GMT.""" - - def strftime(format): - """Format the date/time using the *current timezone representation*.""" - - # General formats from previous DateTime - - def Date(): - """Return the date string for the object.""" - - def Time(): - """Return the time string for an object to the nearest second.""" - - def TimeMinutes(): - """Return the time string for an object not showing seconds.""" - - def AMPM(): - """Return the time string for an object to the nearest second.""" - - def AMPMMinutes(): - """Return the time string for an object not showing seconds.""" - - def PreciseTime(): - """Return the time string for the object.""" - - def PreciseAMPM(): - """Return the time string for the object.""" - - def yy(): - """Return calendar year as a 2 digit string""" - - def mm(): - """Return month as a 2 digit string""" - - def dd(): - """Return day as a 2 digit string""" - - def rfc822(): - """Return the date in RFC 822 format""" - - # New formats - - def fCommon(): - """Return a string representing the object's value in the - format: March 1, 1997 1:45 pm""" - - def fCommonZ(): - """Return a string representing the object's value in the - format: March 1, 1997 1:45 pm US/Eastern""" - - def aCommon(): - """Return a string representing the object's value in the - format: Mar 1, 1997 1:45 pm""" - - def aCommonZ(): - """Return a string representing the object's value in the - format: Mar 1, 1997 1:45 pm US/Eastern""" - - def pCommon(): - """Return a string representing the object's value in the - format: Mar. 1, 1997 1:45 pm""" - - def pCommonZ(): - """Return a string representing the object's value - in the format: Mar. 1, 1997 1:45 pm US/Eastern""" - - def ISO(): - """Return the object in ISO standard format. Note: this is - *not* ISO 8601-format! See the ISO8601 and HTML4 methods below - for ISO 8601-compliant output - - Dates are output as: YYYY-MM-DD HH:MM:SS - """ - - def ISO8601(): - """Return the object in ISO 8601-compatible format containing - the date, time with seconds-precision and the time zone - identifier - see http://www.w3.org/TR/NOTE-datetime - - Dates are output as: YYYY-MM-DDTHH:MM:SSTZD - T is a literal character. - TZD is Time Zone Designator, format +HH:MM or -HH:MM - - The HTML4 method below offers the same formatting, but - converts to UTC before returning the value and sets the TZD"Z" - """ - - def HTML4(): - """Return the object in the format used in the HTML4.0 - specification, one of the standard forms in ISO8601. See - http://www.w3.org/TR/NOTE-datetime - - Dates are output as: YYYY-MM-DDTHH:MM:SSZ - T, Z are literal characters. - The time is in UTC. - """ - - def JulianDay(): - """Return the Julian day according to - https://www.tondering.dk/claus/cal/julperiod.php#formula - """ - - def week(): - """Return the week number according to ISO. - - See https://www.tondering.dk/claus/cal/week.php#weekno - """ - - # Python operator and conversion API - - def __add__(other): - """A DateTime may be added to a number and a number may be - added to a DateTime; two DateTimes cannot be added.""" - - __radd__ = __add__ - - def __sub__(other): - """Either a DateTime or a number may be subtracted from a - DateTime, however, a DateTime may not be subtracted from a - number.""" - - def __repr__(): - """Convert a DateTime to a string that looks like a Python - expression.""" - - def __str__(): - """Convert a DateTime to a string.""" - - def __hash__(): - """Compute a hash value for a DateTime""" - - def __int__(): - """Convert to an integer number of seconds since the epoch (gmt)""" - - def __long__(): - """Convert to a long-int number of seconds since the epoch (gmt)""" - - def __float__(): - """Convert to floating-point number of seconds since the epoch (gmt)""" diff --git a/venv/Lib/site-packages/DateTime/pytz.txt b/venv/Lib/site-packages/DateTime/pytz.txt deleted file mode 100644 index 3a87338..0000000 --- a/venv/Lib/site-packages/DateTime/pytz.txt +++ /dev/null @@ -1,192 +0,0 @@ -Pytz Support -============ - -Allows the pytz package to be used for time zone information. The -advantage of using pytz is that it has a more complete and up to date -time zone and daylight savings time database. - -Usage ------ -You don't have to do anything special to make it work. - - >>> from DateTime import DateTime, Timezones - >>> d = DateTime('March 11, 2007 US/Eastern') - -Daylight Savings ----------------- -In 2007 daylight savings time in the US was changed. The Energy Policy -Act of 2005 mandates that DST will start on the second Sunday in March -and end on the first Sunday in November. - -In 2007, the start and stop dates are March 11 and November 4, -respectively. These dates are different from previous DST start and -stop dates. In 2006, the dates were the first Sunday in April (April -2, 2006) and the last Sunday in October (October 29, 2006). - -Let's make sure that DateTime can deal with this, since the primary -motivation to use pytz for time zone information is the fact that it -is kept up to date with daylight savings changes. - - >>> DateTime('March 11, 2007 US/Eastern').tzoffset() - -18000 - >>> DateTime('March 12, 2007 US/Eastern').tzoffset() - -14400 - >>> DateTime('November 4, 2007 US/Eastern').tzoffset() - -14400 - >>> DateTime('November 5, 2007 US/Eastern').tzoffset() - -18000 - -Let's compare this to 2006. - - >>> DateTime('April 2, 2006 US/Eastern').tzoffset() - -18000 - >>> DateTime('April 3, 2006 US/Eastern').tzoffset() - -14400 - >>> DateTime('October 29, 2006 US/Eastern').tzoffset() - -14400 - >>> DateTime('October 30, 2006 US/Eastern').tzoffset() - -18000 - -Time Zones ---------- -DateTime can use pytz's large database of time zones. Here are some -examples: - - >>> d = DateTime('Pacific/Kwajalein') - >>> d = DateTime('America/Shiprock') - >>> d = DateTime('Africa/Ouagadougou') - -Of course pytz doesn't know about everything. - - >>> from DateTime.interfaces import SyntaxError - >>> try: - ... d = DateTime('July 21, 1969 Moon/Eastern') - ... print('fail') - ... except SyntaxError: - ... print('ok') - ok - -You can still use zone names that DateTime defines that aren't part of -the pytz database. - - >>> d = DateTime('eet') - >>> d = DateTime('iceland') - -These time zones use DateTimes database. So it's preferable to use the -official time zone name. - -One trickiness is that DateTime supports some zone name -abbreviations. Some of these map to pytz names, so these abbreviations -will give you time zone date from pytz. Notable among abbreviations -that work this way are 'est', 'cst', 'mst', and 'pst'. - -Let's verify that 'est' picks up the 2007 daylight savings time changes. - - >>> DateTime('March 11, 2007 est').tzoffset() - -18000 - >>> DateTime('March 12, 2007 est').tzoffset() - -14400 - >>> DateTime('November 4, 2007 est').tzoffset() - -14400 - >>> DateTime('November 5, 2007 est').tzoffset() - -18000 - -You can get a list of time zones supported by calling the Timezones() function. - - >>> Timezones() #doctest: +ELLIPSIS - ['Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', ...] - -Note that you can mess with this list without hurting things. - - >>> t = Timezones() - >>> t.remove('US/Eastern') - >>> d = DateTime('US/Eastern') - - -Internal Components -------------------- - -The following are tests of internal components. - -Cache -~~~~~ - -The DateTime class uses a new time zone cache. - - >>> from DateTime.DateTime import _TZINFO - >>> _TZINFO #doctest: +ELLIPSIS - - -The cache maps time zone names to time zone instances. - - >>> cache = _TZINFO - >>> tz = cache['GMT+730'] - >>> tz = cache['US/Mountain'] - -The cache also must provide a few attributes for use by the DateTime -class. - -The _zlst attribute is a list of supported time zone names. - - >>> cache._zlst #doctest: +ELLIPSIS - ['Africa/Abidjan'... 'Africa/Accra'... 'IDLE'... 'NZST'... 'NZT'...] - -The _zidx attribute is a list of lower-case and possibly abbreviated -time zone names that can be mapped to official zone names. - - >>> 'australia/yancowinna' in cache._zidx - True - >>> 'europe/isle_of_man' in cache._zidx - True - >>> 'gmt+0500' in cache._zidx - True - -Note that there are more items in _zidx than in _zlst since there are -multiple names for some time zones. - - >>> len(cache._zidx) > len(cache._zlst) - True - -Each entry in _zlst should also be present in _zidx in lower case form. - - >>> for name in cache._zlst: - ... if not name.lower() in cache._zidx: - ... print("Error %s not in _zidx" % name.lower()) - -The _zmap attribute maps the names in _zidx to official names in _zlst. - - >>> cache._zmap['africa/abidjan'] - 'Africa/Abidjan' - >>> cache._zmap['gmt+1'] - 'GMT+1' - >>> cache._zmap['gmt+0100'] - 'GMT+1' - >>> cache._zmap['utc'] - 'UTC' - -Let's make sure that _zmap and _zidx agree. - - >>> idx = set(cache._zidx) - >>> keys = set(cache._zmap.keys()) - >>> idx == keys - True - -Timezone objects -~~~~~~~~~~~~~~~~ -The timezone instances have only one public method info(). It returns -a tuple of (offset, is_dst, name). The method takes a timestamp, which -is used to determine dst information. - - >>> t1 = DateTime('November 4, 00:00 2007 US/Mountain').timeTime() - >>> t2 = DateTime('November 4, 02:00 2007 US/Mountain').timeTime() - >>> tz.info(t1) - (-21600, 1, 'MDT') - >>> tz.info(t2) - (-25200, 0, 'MST') - -If you don't pass any arguments to info it provides daylight savings -time information as of today. - - >>> tz.info() in ((-21600, 1, 'MDT'), (-25200, 0, 'MST')) - True - diff --git a/venv/Lib/site-packages/DateTime/pytz_support.py b/venv/Lib/site-packages/DateTime/pytz_support.py deleted file mode 100644 index 4acf324..0000000 --- a/venv/Lib/site-packages/DateTime/pytz_support.py +++ /dev/null @@ -1,269 +0,0 @@ -############################################################################## -# -# Copyright (c) 2007 Zope Foundation and Contributors. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE -# -############################################################################## - -from datetime import datetime -from datetime import timedelta - -import pytz -import pytz.reference -from pytz.tzinfo import StaticTzInfo -from pytz.tzinfo import memorized_timedelta - -from .interfaces import DateTimeError - - -EPOCH = datetime.fromtimestamp(0, tz=pytz.utc) - -_numeric_timezone_data = { - 'GMT': ('GMT', 0, 1, [], '', [(0, 0, 0)], 'GMT\000'), - 'GMT+0': ('GMT+0', 0, 1, [], '', [(0, 0, 0)], 'GMT+0000\000'), - 'GMT+1': ('GMT+1', 0, 1, [], '', [(3600, 0, 0)], 'GMT+0100\000'), - 'GMT+2': ('GMT+2', 0, 1, [], '', [(7200, 0, 0)], 'GMT+0200\000'), - 'GMT+3': ('GMT+3', 0, 1, [], '', [(10800, 0, 0)], 'GMT+0300\000'), - 'GMT+4': ('GMT+4', 0, 1, [], '', [(14400, 0, 0)], 'GMT+0400\000'), - 'GMT+5': ('GMT+5', 0, 1, [], '', [(18000, 0, 0)], 'GMT+0500\000'), - 'GMT+6': ('GMT+6', 0, 1, [], '', [(21600, 0, 0)], 'GMT+0600\000'), - 'GMT+7': ('GMT+7', 0, 1, [], '', [(25200, 0, 0)], 'GMT+0700\000'), - 'GMT+8': ('GMT+8', 0, 1, [], '', [(28800, 0, 0)], 'GMT+0800\000'), - 'GMT+9': ('GMT+9', 0, 1, [], '', [(32400, 0, 0)], 'GMT+0900\000'), - 'GMT+10': ('GMT+10', 0, 1, [], '', [(36000, 0, 0)], 'GMT+1000\000'), - 'GMT+11': ('GMT+11', 0, 1, [], '', [(39600, 0, 0)], 'GMT+1100\000'), - 'GMT+12': ('GMT+12', 0, 1, [], '', [(43200, 0, 0)], 'GMT+1200\000'), - 'GMT+13': ('GMT+13', 0, 1, [], '', [(46800, 0, 0)], 'GMT+1300\000'), - - 'GMT-1': ('GMT-1', 0, 1, [], '', [(-3600, 0, 0)], 'GMT-0100\000'), - 'GMT-2': ('GMT-2', 0, 1, [], '', [(-7200, 0, 0)], 'GMT-0200\000'), - 'GMT-3': ('GMT-3', 0, 1, [], '', [(-10800, 0, 0)], 'GMT-0300\000'), - 'GMT-4': ('GMT-4', 0, 1, [], '', [(-14400, 0, 0)], 'GMT-0400\000'), - 'GMT-5': ('GMT-5', 0, 1, [], '', [(-18000, 0, 0)], 'GMT-0500\000'), - 'GMT-6': ('GMT-6', 0, 1, [], '', [(-21600, 0, 0)], 'GMT-0600\000'), - 'GMT-7': ('GMT-7', 0, 1, [], '', [(-25200, 0, 0)], 'GMT-0700\000'), - 'GMT-8': ('GMT-8', 0, 1, [], '', [(-28800, 0, 0)], 'GMT-0800\000'), - 'GMT-9': ('GMT-9', 0, 1, [], '', [(-32400, 0, 0)], 'GMT-0900\000'), - 'GMT-10': ('GMT-10', 0, 1, [], '', [(-36000, 0, 0)], 'GMT-1000\000'), - 'GMT-11': ('GMT-11', 0, 1, [], '', [(-39600, 0, 0)], 'GMT-1100\000'), - 'GMT-12': ('GMT-12', 0, 1, [], '', [(-43200, 0, 0)], 'GMT-1200\000'), - - 'GMT+0130': ('GMT+0130', 0, 1, [], '', [(5400, 0, 0)], 'GMT+0130\000'), - 'GMT+0230': ('GMT+0230', 0, 1, [], '', [(9000, 0, 0)], 'GMT+0230\000'), - 'GMT+0330': ('GMT+0330', 0, 1, [], '', [(12600, 0, 0)], 'GMT+0330\000'), - 'GMT+0430': ('GMT+0430', 0, 1, [], '', [(16200, 0, 0)], 'GMT+0430\000'), - 'GMT+0530': ('GMT+0530', 0, 1, [], '', [(19800, 0, 0)], 'GMT+0530\000'), - 'GMT+0630': ('GMT+0630', 0, 1, [], '', [(23400, 0, 0)], 'GMT+0630\000'), - 'GMT+0730': ('GMT+0730', 0, 1, [], '', [(27000, 0, 0)], 'GMT+0730\000'), - 'GMT+0830': ('GMT+0830', 0, 1, [], '', [(30600, 0, 0)], 'GMT+0830\000'), - 'GMT+0930': ('GMT+0930', 0, 1, [], '', [(34200, 0, 0)], 'GMT+0930\000'), - 'GMT+1030': ('GMT+1030', 0, 1, [], '', [(37800, 0, 0)], 'GMT+1030\000'), - 'GMT+1130': ('GMT+1130', 0, 1, [], '', [(41400, 0, 0)], 'GMT+1130\000'), - 'GMT+1230': ('GMT+1230', 0, 1, [], '', [(45000, 0, 0)], 'GMT+1230\000'), - - 'GMT-0130': ('GMT-0130', 0, 1, [], '', [(-5400, 0, 0)], 'GMT-0130\000'), - 'GMT-0230': ('GMT-0230', 0, 1, [], '', [(-9000, 0, 0)], 'GMT-0230\000'), - 'GMT-0330': ('GMT-0330', 0, 1, [], '', [(-12600, 0, 0)], 'GMT-0330\000'), - 'GMT-0430': ('GMT-0430', 0, 1, [], '', [(-16200, 0, 0)], 'GMT-0430\000'), - 'GMT-0530': ('GMT-0530', 0, 1, [], '', [(-19800, 0, 0)], 'GMT-0530\000'), - 'GMT-0630': ('GMT-0630', 0, 1, [], '', [(-23400, 0, 0)], 'GMT-0630\000'), - 'GMT-0730': ('GMT-0730', 0, 1, [], '', [(-27000, 0, 0)], 'GMT-0730\000'), - 'GMT-0830': ('GMT-0830', 0, 1, [], '', [(-30600, 0, 0)], 'GMT-0830\000'), - 'GMT-0930': ('GMT-0930', 0, 1, [], '', [(-34200, 0, 0)], 'GMT-0930\000'), - 'GMT-1030': ('GMT-1030', 0, 1, [], '', [(-37800, 0, 0)], 'GMT-1030\000'), - 'GMT-1130': ('GMT-1130', 0, 1, [], '', [(-41400, 0, 0)], 'GMT-1130\000'), - 'GMT-1230': ('GMT-1230', 0, 1, [], '', [(-45000, 0, 0)], 'GMT-1230\000'), -} - -# These are the timezones not in pytz.common_timezones -_old_zlst = [ - 'AST', 'AT', 'BST', 'BT', 'CCT', - 'CET', 'CST', 'Cuba', 'EADT', 'EAST', - 'EEST', 'EET', 'EST', 'Egypt', 'FST', - 'FWT', 'GB-Eire', 'GMT+0100', 'GMT+0130', 'GMT+0200', - 'GMT+0230', 'GMT+0300', 'GMT+0330', 'GMT+0400', 'GMT+0430', - 'GMT+0500', 'GMT+0530', 'GMT+0600', 'GMT+0630', 'GMT+0700', - 'GMT+0730', 'GMT+0800', 'GMT+0830', 'GMT+0900', 'GMT+0930', - 'GMT+1', 'GMT+1000', 'GMT+1030', 'GMT+1100', 'GMT+1130', - 'GMT+1200', 'GMT+1230', 'GMT+1300', 'GMT-0100', 'GMT-0130', - 'GMT-0200', 'GMT-0300', 'GMT-0400', 'GMT-0500', 'GMT-0600', - 'GMT-0630', 'GMT-0700', 'GMT-0730', 'GMT-0800', 'GMT-0830', - 'GMT-0900', 'GMT-0930', 'GMT-1000', 'GMT-1030', 'GMT-1100', - 'GMT-1130', 'GMT-1200', 'GMT-1230', 'GST', 'Greenwich', - 'Hongkong', 'IDLE', 'IDLW', 'Iceland', 'Iran', - 'Israel', 'JST', 'Jamaica', 'Japan', 'MEST', - 'MET', 'MEWT', 'MST', 'NT', 'NZDT', - 'NZST', 'NZT', 'PST', 'Poland', 'SST', - 'SWT', 'Singapore', 'Turkey', 'UCT', 'UT', - 'Universal', 'WADT', 'WAST', 'WAT', 'WET', - 'ZP4', 'ZP5', 'ZP6', -] - -_old_zmap = { - 'aest': 'GMT+10', 'aedt': 'GMT+11', - 'aus eastern standard time': 'GMT+10', - 'sydney standard time': 'GMT+10', - 'tasmania standard time': 'GMT+10', - 'e. australia standard time': 'GMT+10', - 'aus central standard time': 'GMT+0930', - 'cen. australia standard time': 'GMT+0930', - 'w. australia standard time': 'GMT+8', - - 'central europe standard time': 'GMT+1', - 'eastern standard time': 'US/Eastern', - 'us eastern standard time': 'US/Eastern', - 'central standard time': 'US/Central', - 'mountain standard time': 'US/Mountain', - 'pacific standard time': 'US/Pacific', - 'mst': 'US/Mountain', 'pst': 'US/Pacific', - 'cst': 'US/Central', 'est': 'US/Eastern', - - 'gmt+0000': 'GMT+0', 'gmt+0': 'GMT+0', - - 'gmt+0100': 'GMT+1', 'gmt+0200': 'GMT+2', 'gmt+0300': 'GMT+3', - 'gmt+0400': 'GMT+4', 'gmt+0500': 'GMT+5', 'gmt+0600': 'GMT+6', - 'gmt+0700': 'GMT+7', 'gmt+0800': 'GMT+8', 'gmt+0900': 'GMT+9', - 'gmt+1000': 'GMT+10', 'gmt+1100': 'GMT+11', 'gmt+1200': 'GMT+12', - 'gmt+1300': 'GMT+13', - 'gmt-0100': 'GMT-1', 'gmt-0200': 'GMT-2', 'gmt-0300': 'GMT-3', - 'gmt-0400': 'GMT-4', 'gmt-0500': 'GMT-5', 'gmt-0600': 'GMT-6', - 'gmt-0700': 'GMT-7', 'gmt-0800': 'GMT-8', 'gmt-0900': 'GMT-9', - 'gmt-1000': 'GMT-10', 'gmt-1100': 'GMT-11', 'gmt-1200': 'GMT-12', - - 'gmt+1': 'GMT+1', 'gmt+2': 'GMT+2', 'gmt+3': 'GMT+3', - 'gmt+4': 'GMT+4', 'gmt+5': 'GMT+5', 'gmt+6': 'GMT+6', - 'gmt+7': 'GMT+7', 'gmt+8': 'GMT+8', 'gmt+9': 'GMT+9', - 'gmt+10': 'GMT+10', 'gmt+11': 'GMT+11', 'gmt+12': 'GMT+12', - 'gmt+13': 'GMT+13', - 'gmt-1': 'GMT-1', 'gmt-2': 'GMT-2', 'gmt-3': 'GMT-3', - 'gmt-4': 'GMT-4', 'gmt-5': 'GMT-5', 'gmt-6': 'GMT-6', - 'gmt-7': 'GMT-7', 'gmt-8': 'GMT-8', 'gmt-9': 'GMT-9', - 'gmt-10': 'GMT-10', 'gmt-11': 'GMT-11', 'gmt-12': 'GMT-12', - - 'gmt+130': 'GMT+0130', 'gmt+0130': 'GMT+0130', - 'gmt+230': 'GMT+0230', 'gmt+0230': 'GMT+0230', - 'gmt+330': 'GMT+0330', 'gmt+0330': 'GMT+0330', - 'gmt+430': 'GMT+0430', 'gmt+0430': 'GMT+0430', - 'gmt+530': 'GMT+0530', 'gmt+0530': 'GMT+0530', - 'gmt+630': 'GMT+0630', 'gmt+0630': 'GMT+0630', - 'gmt+730': 'GMT+0730', 'gmt+0730': 'GMT+0730', - 'gmt+830': 'GMT+0830', 'gmt+0830': 'GMT+0830', - 'gmt+930': 'GMT+0930', 'gmt+0930': 'GMT+0930', - 'gmt+1030': 'GMT+1030', - 'gmt+1130': 'GMT+1130', - 'gmt+1230': 'GMT+1230', - - 'gmt-130': 'GMT-0130', 'gmt-0130': 'GMT-0130', - 'gmt-230': 'GMT-0230', 'gmt-0230': 'GMT-0230', - 'gmt-330': 'GMT-0330', 'gmt-0330': 'GMT-0330', - 'gmt-430': 'GMT-0430', 'gmt-0430': 'GMT-0430', - 'gmt-530': 'GMT-0530', 'gmt-0530': 'GMT-0530', - 'gmt-630': 'GMT-0630', 'gmt-0630': 'GMT-0630', - 'gmt-730': 'GMT-0730', 'gmt-0730': 'GMT-0730', - 'gmt-830': 'GMT-0830', 'gmt-0830': 'GMT-0830', - 'gmt-930': 'GMT-0930', 'gmt-0930': 'GMT-0930', - 'gmt-1030': 'GMT-1030', - 'gmt-1130': 'GMT-1130', - 'gmt-1230': 'GMT-1230', - - 'ut': 'Universal', - 'bst': 'GMT+1', 'mest': 'GMT+2', 'sst': 'GMT+2', - 'fst': 'GMT+2', 'wadt': 'GMT+8', 'eadt': 'GMT+11', 'nzdt': 'GMT+13', - 'wet': 'GMT', 'wat': 'GMT+1', 'at': 'GMT-2', 'ast': 'GMT-4', - 'nt': 'GMT-11', 'idlw': 'GMT-12', 'cet': 'GMT+1', 'cest': 'GMT+2', - 'met': 'GMT+1', - 'mewt': 'GMT+1', 'swt': 'GMT+1', 'fwt': 'GMT+1', 'eet': 'GMT+2', - 'eest': 'GMT+3', - 'bt': 'GMT+3', 'zp4': 'GMT+4', 'zp5': 'GMT+5', 'zp6': 'GMT+6', - 'wast': 'GMT+7', 'cct': 'GMT+8', 'jst': 'GMT+9', 'east': 'GMT+10', - 'gst': 'GMT+10', 'nzt': 'GMT+12', 'nzst': 'GMT+12', 'idle': 'GMT+12', - 'ret': 'GMT+4', 'ist': 'GMT+0530', 'edt': 'GMT-4', - -} - - -# some timezone definitions of the "-0400" are not working -# when upgrading -for hour in range(0, 13): - hour = hour - fhour = str(hour) - if len(fhour) == 1: - fhour = '0' + fhour - _old_zmap['-%s00' % fhour] = 'GMT-%i' % hour - _old_zmap['+%s00' % fhour] = 'GMT+%i' % hour - - -def _p(zone): - return _numeric_timezones[zone] - - -def _static_timezone_factory(data): - zone = data[0] - cls = type(zone, (StaticTzInfo,), dict( - __reduce__=lambda _: (_p, (zone, )), - zone=zone, - _utcoffset=memorized_timedelta(data[5][0][0]), - _tzname=data[6][:-1])) # strip the trailing null - return cls() - - -_numeric_timezones = {key: _static_timezone_factory(data) - for key, data in _numeric_timezone_data.items()} - - -class Timezone: - """ - Timezone information returned by PytzCache.__getitem__ - Adapts datetime.tzinfo object to DateTime._timezone interface - """ - - def __init__(self, tzinfo): - self.tzinfo = tzinfo - - def info(self, t=None): - if t is None: - dt = datetime.now(tz=pytz.utc) - else: - # can't use utcfromtimestamp past 2038 - dt = EPOCH + timedelta(0, t) - - # need to normalize tzinfo for the datetime to deal with - # daylight savings time. - normalized_dt = self.tzinfo.normalize(dt.astimezone(self.tzinfo)) - normalized_tzinfo = normalized_dt.tzinfo - - offset = normalized_tzinfo.utcoffset(normalized_dt) - secs = offset.days * 24 * 60 * 60 + offset.seconds - dst = normalized_tzinfo.dst(normalized_dt) - if dst == timedelta(0): - is_dst = 0 - else: - is_dst = 1 - return secs, is_dst, normalized_tzinfo.tzname(normalized_dt) - - -class PytzCache: - """ - Reimplementation of the DateTime._cache class that uses for timezone info - """ - - _zlst = pytz.common_timezones + _old_zlst # used by DateTime.TimeZones - _zmap = {name.lower(): name for name in pytz.all_timezones} - _zmap.update(_old_zmap) # These must take priority - _zidx = _zmap.keys() - - def __getitem__(self, key): - name = self._zmap.get(key.lower(), key) # fallback to key - try: - return Timezone(pytz.timezone(name)) - except pytz.UnknownTimeZoneError: - try: - return Timezone(_numeric_timezones[name]) - except KeyError: - raise DateTimeError('Unrecognized timezone: %s' % key) diff --git a/venv/Lib/site-packages/DateTime/tests/__init__.py b/venv/Lib/site-packages/DateTime/tests/__init__.py deleted file mode 100644 index e67bcb6..0000000 --- a/venv/Lib/site-packages/DateTime/tests/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Foundation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## - -# This file is needed to make this a package. diff --git a/venv/Lib/site-packages/DateTime/tests/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/DateTime/tests/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index ea39a6ab8b14d254b6a81e50c2c028e717900321..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmd1j<>g`kf?4-vGgdP(FgylvkO3o*;{e3PEI=ZKA(%mv(QhR~5l9$8{PK6UiU}=F zEh>&FNYBqrjd4jW&MwI>i1Bf8ElbRaDND^Oi}A@!iYd-4N!2Y#OwLYBPc4pdNi0bX s$;?gFFG(#fDb|mV&&GhH><1QKBnXn==k0yq?ro*rcFtM>7b-m+LAPs4oMnLhmo53$YwMhHTY~0 z*O7EYt}R^mqyGH~b zwTJE*_l)$&XNT+_71%Y>$6g7jKGpw)fa{fGy)gr4bpvsc2awM~wE2t~Q zm293l>0-fN%x>DX!&}?#da;nnZEof5O}pS`-CVJ-!nZa5U|s?j@n5z8RNz|RzOi^e z;Pm3I0Uj(}oWH(Yww?0zt+nE&eSN_$-*k&x*RL#Gx|PjezhxJ0UB8mMalM>#?eVSb z%FXPWUB2%3a?-WSZdqW)AKb*&b}jm`e0KAO%6{T`cEAL%0!}}Ynss&i>h`|Avc?7c zmlFVXfD{DkF+e${3Id~+vQ!9ZNQG4dX_#||G@@d_bZ@Qqa_(JQy}7ztw%zKpauYAg zT|8HaZ{`XWbTn>f%WiztDQ?D>mo84M1o1Bahu8eSi2w2t05`B>DC0e2Cy+6AOh6Db zUS)DVBVL1JL5H}l4QHBOpULPK*M?ei3z)jGV9hGq`PEw3t79>@F&j=Fn~P>LxkAp( zWTw~|zM;>E8P(yYmrVFoR){(Ohu8kBe;CHiPGAF_cDRzq4Cf${`=)aUNzGJl`)hkD z?uzc#In?-&jfIWs;pVs2Yjl0Ba} zaU0{RS?Nn}z1i_SK~;7?j`lSL8r8w(*Pv{1EJ|#%FPTg&mdR`uRVB~szD%Z6$>zP1 zNG79-E18T#%5aVooFq6+&={Lsae&Ss07<#byJ)~NqGr^J2K$0ivVzQ(AI|Xw{FlFp z>1&X`GC|@&6;u{dEC3Zo8d4DzMH<%33rnC^_2E9M`qco^9yO>AAdRVmY6xksI;4h? z_Nl|_2-1FaRE;1VP{-79q=V{&I*IgvI;Bn{J*b{gail})N%a)cL+WYu4ANmWs-8u9 zSUsnnM|wn!sTYtQRcF*$q$6rvO&~p{CRGCIag|glq$kvrnnrq3&8S(Vr_?z$hxD{M zujY|Hp?*Yt3~5|_TzvxRlj=ov0qIlfCG|4Wr`1KZfbwo}OF#?}^!}@L2z+;u0nuy0=%IAx>%kgsM#`tC~pU;);m104~Z)KgF2&wW!y_u^{ZWG!0 z?f7cZiBpc`3TqR4WWswr0E=UhT5q-t(d1s@QmloXVx^$cX2z|V8CA0=Kx<+Bnsg+y znOkv+<@-U+--76N4ItIDJU!;Rq6aP$LC$#6I%%9VhVffH(lUP&8L#RJnX3Ooz8J#4 zJWuiFLiyoT+<~mPYq;i)v1{DLs=a3@>n5a#Af2)!w73@s+o%O!d1EPU&L$i-J7zf% zB(<0x>XK8jYr(SX)GP}Bj$Eym$a=Z5mP{q4-oUfM5M$ca2292Qm&MeYBVcqP$Ge^Lgan2J+zlVACBLtnK*^t-8 z#iHx?@-wXaB0x3Xv3E^XyLPa=f#==8ZlFO}$~X#*8UI22TO(jyn%qESm=DZi2r~!` zNo%(LEV9m{pOl&GU0nNxpXbl7zqt0q7ys~6-#p!OVJ-HZZ)|-$cH+VwSIXWGIMXE8 zJqK0Pzyq-!t!IWOsZ)U}0ur@OFuOb|;^D6Fg7hWC=iK8nH!X-MPY>D0zGp3_^1Yi(&^1lWfE}1^}hV zO_rUryl<#s!sms?h!@wXthhyIs(?ymQe)UOjd1JlA4Q`h!A`W++&~K+gJ_7j6g)nK z3ynutMEWkUaR+;byI6QTrqBPiR;(9DEwq|1W?g3jPkJIt2K14JGW}=pRGG>|*z7Y7 z7?0`r^uCVQ^^nzl9oGZ^VaDzUT}vj`;#6}en(zCAWGTr7!+m6ZE-5{DZ;iZ-*E&lC z&k_iqAT2&_4rjiAN@a4QFqr>w$U-M9*3I9LNmFd%RC zFn|8+jagb!to`_*-$SpDT&SK%B@&6rZw<=WsDpjC7z5ijSEi+ zf)X>LCC^8o-`y}|Q&66;F!2#gI@lGbe#ct1>gubxxHh*px%9uE?71)&)f0OaZ*)FI zKwVR$l5>q$R|v?lAnWTQNOSCQ`p`w;T!6-DGW;tX% zh(?YZoz&T;=UWifLJZHNWuF+3QaF^|3&pt2NU}mI-xj#VT`1$WI`U)N?p%$^ZFgfe~k z!PVD-a7c|2ktV*t6amOi!TQ!vk302ERu6EYa;vMqi3hyZ6NRwrw7K(Y?(1WnL&U+k zIueCR-9)2Ih{ObIY`zEY@Cil}(cMtnJq!x<=Od6PQU4zAgC6K_Aobl%)HP_kO2HSYOtn5J9Gu?4H&>%KMab>F;uyqyAyRs+;ip?W{KWJC2n#N1vn5{1aKP*>jv zRqH)A?k(lm#(VdCXBc-re%Ys}e=pJ?y!aq0%pf_Ltm>=OWXf3s{q1ohoVHSl)YMp? zrd?V2y=#sQ2JbAbXA8BVrW-NUEEQ|fyj?C!>7ak*7sU!iZP7tB&%kpzn}?l;TOHxA zwLWbOc`FM8Qn}W%w7q3ta-5>maXk-{(fFpC%%%gew?nf{RWOJ;B7ax5VWopa$9;3r*+N_QBZ7%qcq_MZ zGjG>IsPYr%qjyB54@Z@1$~ z*m*`b4;QC)2ZUj^isAP->>Qn#x>vs|9zMJ*c+hGeMo&y&bpMx_7!phbp$9;7|A2?%3GhLdOHUc za2-I$6G{lmnt%|yW7XG0$XgTUPDs{-#gwA3bflzRo597gVD%KJ;oM{*Ihjbw#$bAW zW_IG--1+#K#8e{jsN(6VM--1IQ&ZConi>m>0u3LQo58M1n?81lY3}fyFA}s-+^J@C z3&j;G*ox(_y$0=_BDT4AiyH8q#8pIa>*S(c4*qI7gQ48Jj~n5B`|L(791 z-)0H7a_*L0I`#nHx0?CSB?O^kqs&(euEKKN>6IhrZp25%^xY&0Lia0D5rfQ%R) z)Nc9G>DR4gaeI}Xc;&?pes+0z`O|?w<;KK=NFLs`!g#VS(d@!XQQ3}gxR1)vWUJ~4 zpG+~YCK_wXG|h*x{<_fW;Bjest}BH)?*nP9KUjj0q$IqXx) zkvgRu?L;XfO_Xx1K`F=EDCI<>`8uVXY@?J@bxJwiLMhH)0P3Bu5fdoXD6)Udi zTz$EXBKqnS@d&xLznSg?@+A@o*z6Nnn&&4I_)EnT=jQPT>(tatB6Uu9ZSpa^_GB}! zRS@juOm-E!l?pk(DZHee`Te(wViS7wHUxk!vPU1 zJ&tW6z~n|Hm&Z!ZWMah|8?Y$GO6HQ z==>@1rZtl-XT%+Gy={K2`uwK4qpDkD`%qTbUbMYd{F(+t6gH+1R^my3$qt5zdjZkl zX{*I%rh~~&oU*XJMo7nEn0$n3E{jSvvz%;KC?dqjQaZK9L2I7^+-vxSspatg;i6{C zh=ORgKB5F}e9@~nc%JPIxb zm}_=}GKX{_LhZO0z^JVg0Vw8FJz%Ujfr!nc*tE*bT054C>@S7bE}Ey9oULi@9%odz^+?p#hrWYSv~Jo!H`)!zMm-k>Mgk9#=q`l`bW6&aRm*Wn|07P zwRG{+G*`W-6D!RCx`hlJQSw z3vIQoUR%n2{{4rD>d*~M$6uDa%3DYG zzqo~UKgtfs5`J};4`Oz-iMCTc1X**erx_f zmweKAr}_uF&bu+LLtXNRyW}74l7FP0--@@RUGhh|iJd+-r`;IpRDJ%_W!9a`A^sLgDvep(Q4cao-W`RIvLn)94;IU59 zshgOeN>Ev@9z!eBlL_Qc$CJ~@olnlNV0@}NfTCG3_9UgMyl^}*GoDB-C1?%AUv-$h zXv<7LV5{x9XY>P|iolN9R#Q>je}Pvt(xE|N;?)>?Ii5)3PrUN8a+!`YJCQ_Y#H)}F z>n!>!60_BVfGI>|G>t{F>SN)yKRwt~iy1ACG2={A7COx=xJd<7UgJ8;M^#HE2Q6=C zdTF(vudHWykF#;1XGJiuv5jU%J^zEPg;Ww}?Zr+57A)XaEt$)Dcw#1vnA6!oTA z)Lx)FkW3LXKtUhd^Y5fPv*Ssidv+`HvMnqiLY9dXT z6qph?C2%?&%9V=?Zh8O-AELn#adqh)?|xyaeP^(n|}ky;ZY{ zTXvz=12?70=L&XNyLv)y1!tye!OiTJ^E#TVh00s`oU1)N)@{V*j75Z|YUXMI{|eq9 zK3%hz)C`p#KzMv5?`C+6D6{!)JM9dx+fYX_0!I1_U^7r2!ixqF0TVM$KBTkpBqDyS zKdzqKzn^G4*fM9_Yu2?mg&SyLI_QT1=LqLwbRH!NwKbQanaJ^DgFQ)8j|V|1u3-*t zu8$n4kCgc`7s15`WWA6b{Hq>u(>B%H)GEko>9GutC89%7)Z{r&0iuOg^i?8S+ zj3P~8c_YLN=ab|+BFp2XQSIO>YJ08)E!SMD1-&5oT`U;13-zLY!~(VP97^Olq;)jH-pS3naN{}RFVzSbj9hz7r~-bR%+yo-okA>IMISs~o%WK3FFF)zE{Ie)2Gs#TwI#+ySZI z+sFfdGu5D1*W+VCA_#(WMlOZ{NI?SZy@v<}iikjmXbM%4QK!5a=73#fzcft^rq zKn=l;GPG+pg{mJ~bnXGw*ubt=&ck{wl#1z#gq7&NBq(0IEHsa5SpXL`v<^us3$F zv6oJVoz<1ORLc1qtUU%$)8VyrxYQ!qJoeFuvt2?#+RDQ2B^+LY_|oC*8}!gPSEX=0 zlbUXX^wq*DcMAvqJg1}%;Y2JSA_3TPIUUaA$~aNt4D-EhZb=Cyd+YK=^lO6aiIynx zc>g~fWFQFwAh5#1CfC@otTe8(XF5j0>Bjc0C%#wK6P+jG`@KjvAEfUm?jU>$>G?as zYA;rrXER+5N+7d^)6hK@oaNhbUuu_Px49xiu&=@<$$C69@}4OxgJF^(kLg*Du2G7W z!k+Iq3g2<=+gS6t-zNATz?dl$?EDh?3#P@%mg~KfxY~OHpc?hh2k>e_{%ZZ+Q8Wfi zX7e~39f1;HuWq`YS*6x<>D?83i^bZ=r(MZ1vyG@t1ZHF^m_UV-wEGUao}i3=O`mwv zuc0KyDKr=mU*{x}<7!>cgsASrR>PvA6Ze_km?(ib_5LDrlP~>H6r|%_8 z-|JG=;=S`v(HZBT0eEOm59kmq98{9Ht!9HN45*onY=KFkc+2@sKKjoI+SZ14d1C_d z8I9b``u5hkUARsh58wff<33>e}oAZg>q3a9ibEG6_T&sPOr|7y?-R9{R( zxr|>d=JRmT;P7IuT&~#hr>EzpUoY_>Ici*nGU+NZesWn;Hw%4*7I5 zff3ryYIX%G>TlrvpaL>wl;?`zTar$GoDe2J4_KCC|NcWntzd2X@x-n2{t#eJQaVF1M>G)2V19l*#^ z?b^XMgSrvj0G5|eaZE-dOh?EU!N~_l-x(j>93NHj(O2h3--wTrCKE=4LpJk#FFQ6Mg`$K2+k31yE!@fPBn(ef8?=@)|F|$hL_Kr`%Ok{ zN3hu`4p2fb{qbDRIvi~IT_S>LXQ*YAryHK?js*Xq78G!)k*I__o^3(_1`O5Q^R02f z2ydasP{MtE?g#QY(ioK3ymW|8vNb$;lfz_eN#qrtMA?owdoW?X7JMgddgRNt;bd z#?-jq+&G&XM*!}4c7;-Oyi&+9Qltg_6i)Sh6`86}fvO%+B-DmDW~kka3peisRoII* zqL_jT0@EwXcZ5!5RY$axgh6Y1Se*7nlbJZ5C2`eTOQB=KlNpXd zYm>7%9im-OQ)UNg3+70;b(6%y`YW2J(Xh>_*MFQ#(68^g3jJfl zUMu1#R2CHr?rw!=Ai^J|A-xd+&+c9Zv51q>vJE&lo=m_l+q8ucEAfQQ_-y%5K%8+; zId?nmb4HSFCWDU+lx=9zVuTZWVS7_)v8uM`R>|zoO(wylV8EW4=W(T}iRrm>v&lKC zE@zU}(Z{`9-Yur{E)7+m?$89kOR$1t>5!`;&9On?u2w>&YyH0PU1XG(J{d*5(fK-n zFQ(;)UzWLTd_)4M8{!=;yy}UOuaW{Oxp-!ZN1-2=hP`^01iEvd0b^i?VC#-=YoXqL zyp;|^VY{!&ww=};G6*Uc&3ycDfQq=Gjqq-ij(=K1L}`Vq zU!H;Ls-Hm{*mlcy0~=l~`B4YkZ7~jF`@8`I;YP2tkL^9$ffI$Q9o~aaHtmMQnbNZp z;WIlz+gM?|N4q=GjXw55^}Z)69}WW2b=c#E?)IyG=pHeztpT(b+lirG_)ahSOUGlM zw9_N)$ou8KukF5PM;z&mx*G#K;&N})_H%^y4KC)s1Jcpw$^Sl3yhoeh9(CY7?ih0m znDv(B1^&9(#lF z9hXUmvRW=-fk(y^%ckXWnwK**)2+(w3~y)KSA}q6SP8M7_*H=NU*}qwK%3ksaNkVG z_+Bx3%K?Mq*lEX@3*Geq#P1OGjSd{Usnr&m=YpUbBGZgPLND{7yB%-;^25W zTh6U4rGJAsCLzX5Vv#D0Y{ojc6TBx{@Q0@xy8jj2___jCf*-u%Z&G>B4~d9Q;FW`y zD1SrCa!4aM3Vf_VgFOYq&DnTrF8;|1V?_{s0)mGOfED%9!csbnVnp*e-^Q!c7V6l7 z;_+#pSrb?3Agw`f@hYV4Ktjr$G+H4+H0*QB-z9pqcBfCXfVp-cucjxuqlbnMo?r1| z-l(>Nv1$P?Yyy#wP{*;XyKtJRqXd9tPuArpdXl+us3z51TLRmf^}$ot?|SY)7T zUvl!9gsT+Ip0nt?958ot-M%c)TzTJE>&nklXrXy8uE)wR3ha7Em%I_{Z5wvlulbt< zsCd84(f$_#va57#%PHQFp@Yk%QFY&7 z>U&z!kaq@Is2U$?svC@PHcwnQdCsO^9gH%&=o;WixWz|<}X;WI(^MYMf)AH`Xqw8;9!}8su)jA zAz~7OGv4xuw@&namXq2XAy^B-$XE+&_g;Fag6}cXAc#Z#h~uTpuYKw0!(F--&DgSM z8HTYihJT*$TMyy!e@`?_7Py z`7SH{JAywT_|F7;1b;~IUkUyj!T%s=EO)u;W8TvMFX6xJ07SVFk3~b#Fn)WH9ze>U zLHvgSnIDdxMV*NJG98W{0_>Fs zwfaKx{uR8s{zLX$Ut*j~EU-X6aEE8sOcxyEuI0iVj?XiOweI{Lj_TtY=bDxEp1B6I z26kNdFop2>KA$s+D;!G%A9Jilyl-(U%m`iHZLw_;UFX~(|rrYmCL!jEf3?%kv~9Y6XuEZns`3I zw9xzyNd3%=3iVTi2>-G3zmPF@+WE_T_OB7}G)gUsox00KgRh(+2zQJH?5);z&``i3 z-xWR6`5v!0;Pk;d4*Uy;2?v9X6%QZd!mtgN$kt7fd~!+YOnBfreb5tYM7 z?!;Miqs*WI=T}&EihvqdI@*E;89~#q>ja0-o9YimeuDE;z5oDP5$#DsZPJFGYW5+1 f*n~l_58MC_gWwT!7!Cw@hk`=~1E2GM`{w@-R3unO diff --git a/venv/Lib/site-packages/DateTime/tests/julian_testdata.txt b/venv/Lib/site-packages/DateTime/tests/julian_testdata.txt deleted file mode 100644 index 386c3da..0000000 --- a/venv/Lib/site-packages/DateTime/tests/julian_testdata.txt +++ /dev/null @@ -1,57 +0,0 @@ -1970-01-01 (1970, 1, 4) -1970-01-02 (1970, 1, 5) -1970-01-30 (1970, 5, 5) -1970-01-31 (1970, 5, 6) -1970-02-01 (1970, 5, 7) -1970-02-02 (1970, 6, 1) -1970-02-28 (1970, 9, 6) -1970-03-01 (1970, 9, 7) -1970-03-30 (1970, 14, 1) -1970-03-31 (1970, 14, 2) -1970-04-01 (1970, 14, 3) -1970-09-30 (1970, 40, 3) -1970-10-01 (1970, 40, 4) -1970-10-02 (1970, 40, 5) -1970-10-03 (1970, 40, 6) -1970-10-04 (1970, 40, 7) -1970-10-05 (1970, 41, 1) -1971-01-02 (1970, 53, 6) -1971-01-03 (1970, 53, 7) -1971-01-04 (1971, 1, 1) -1971-01-05 (1971, 1, 2) -1971-12-31 (1971, 52, 5) -1972-01-01 (1971, 52, 6) -1972-01-02 (1971, 52, 7) -1972-01-03 (1972, 1, 1) -1972-01-04 (1972, 1, 2) -1972-12-30 (1972, 52, 6) -1972-12-31 (1972, 52, 7) -1973-01-01 (1973, 1, 1) -1973-01-02 (1973, 1, 2) -1973-12-29 (1973, 52, 6) -1973-12-30 (1973, 52, 7) -1973-12-31 (1974, 1, 1) -1974-01-01 (1974, 1, 2) -1998-12-30 (1998, 53, 3) -1998-12-31 (1998, 53, 4) -1999-01-01 (1998, 53, 5) -1999-01-02 (1998, 53, 6) -1999-01-03 (1998, 53, 7) -1999-01-04 (1999, 1, 1) -1999-01-05 (1999, 1, 2) -1999-12-30 (1999, 52, 4) -1999-12-31 (1999, 52, 5) -2000-01-01 (1999, 52, 6) -2000-01-02 (1999, 52, 7) -2000-01-03 (2000, 1, 1) -2000-01-04 (2000, 1, 2) -2000-01-05 (2000, 1, 3) -2000-01-06 (2000, 1, 4) -2000-01-07 (2000, 1, 5) -2000-01-08 (2000, 1, 6) -2000-01-09 (2000, 1, 7) -2000-01-10 (2000, 2, 1) -2019-12-28 (2019, 52, 6) -2019-12-29 (2019, 52, 7) -2019-12-30 (2020, 1, 1) -2019-12-31 (2020, 1, 2) diff --git a/venv/Lib/site-packages/DateTime/tests/test_datetime.py b/venv/Lib/site-packages/DateTime/tests/test_datetime.py deleted file mode 100644 index f4c2644..0000000 --- a/venv/Lib/site-packages/DateTime/tests/test_datetime.py +++ /dev/null @@ -1,764 +0,0 @@ -############################################################################## -# -# Copyright (c) 2003 Zope Foundation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## - -import math -import os -import pickle -import platform -import sys -import time -import unittest -from datetime import date -from datetime import datetime -from datetime import timedelta -from datetime import tzinfo - -import pytz - -from DateTime import DateTime -from DateTime.DateTime import _findLocalTimeZoneName - - -try: - __file__ -except NameError: # pragma: no cover - f = sys.argv[0] -else: - f = __file__ - -IS_PYPY = getattr(platform, 'python_implementation', lambda: None)() == 'PyPy' - -DATADIR = os.path.dirname(os.path.abspath(f)) -del f - -ZERO = timedelta(0) - - -class FixedOffset(tzinfo): - """Fixed offset in minutes east from UTC.""" - - def __init__(self, offset, name): - self.__offset = timedelta(minutes=offset) - self.__name = name - - def utcoffset(self, dt): - return self.__offset - - def tzname(self, dt): - return self.__name - - def dst(self, dt): - return ZERO - - -class DateTimeTests(unittest.TestCase): - - def _compare(self, dt1, dt2): - '''Compares the internal representation of dt1 with - the representation in dt2. Allows sub-millisecond variations. - Primarily for testing.''' - self.assertEqual(round(dt1._t, 3), round(dt2._t, 3)) - self.assertEqual(round(dt1._d, 9), round(dt2._d, 9)) - self.assertEqual(round(dt1.time, 9), round(dt2.time, 9)) - self.assertEqual(dt1.millis(), dt2.millis()) - self.assertEqual(dt1._micros, dt2._micros) - - def testBug1203(self): - # 01:59:60 occurred in old DateTime - dt = DateTime(7200, 'GMT') - self.assertTrue(str(dt).find('60') < 0, dt) - - def testDSTInEffect(self): - # Checks GMT offset for a DST date in the US/Eastern time zone - dt = DateTime(2000, 5, 9, 15, 0, 0, 'US/Eastern') - self.assertEqual(dt.toZone('GMT').hour(), 19, - (dt, dt.toZone('GMT'))) - - def testDSTNotInEffect(self): - # Checks GMT offset for a non-DST date in the US/Eastern time zone - dt = DateTime(2000, 11, 9, 15, 0, 0, 'US/Eastern') - self.assertEqual(dt.toZone('GMT').hour(), 20, - (dt, dt.toZone('GMT'))) - - def testAddPrecision(self): - # Precision of serial additions - dt = DateTime() - self.assertEqual(str(dt + 0.10 + 3.14 + 6.76 - 10), str(dt), - dt) - # checks problem reported in - # https://github.com/zopefoundation/DateTime/issues/41 - dt = DateTime(2038, 10, 7, 8, 52, 44.959840, "UTC") - self.assertEqual(str(dt + 0.10 + 3.14 + 6.76 - 10), str(dt), - dt) - - def testConsistentSecondMicroRounding(self): - dt = DateTime(2038, 10, 7, 8, 52, 44.9598398, "UTC") - self.assertEqual(int(dt.second() * 1000000), - dt.micros() % 60000000) - - def testConstructor3(self): - # Constructor from date/time string - dt = DateTime() - dt1s = '%d/%d/%d %d:%d:%f %s' % ( - dt.year(), - dt.month(), - dt.day(), - dt.hour(), - dt.minute(), - dt.second(), - dt.timezone()) - dt1 = DateTime(dt1s) - # Compare representations as it's the - # only way to compare the dates to the same accuracy - self.assertEqual(repr(dt), repr(dt1)) - - def testConstructor4(self): - # Constructor from time float - dt = DateTime() - dt1 = DateTime(float(dt)) - self._compare(dt, dt1) - - def testConstructor5(self): - # Constructor from time float and timezone - dt = DateTime() - dt1 = DateTime(float(dt), dt.timezone()) - self.assertEqual(str(dt), str(dt1), (dt, dt1)) - dt1 = DateTime(float(dt), str(dt.timezone())) - self.assertEqual(str(dt), str(dt1), (dt, dt1)) - - def testConstructor6(self): - # Constructor from year and julian date - # This test must normalize the time zone, or it *will* break when - # DST changes! - dt1 = DateTime(2000, 5.500000578705) - dt = DateTime('2000/1/5 12:00:00.050 pm %s' % dt1.localZone()) - self._compare(dt, dt1) - - def testConstructor7(self): - # Constructor from parts - dt = DateTime() - dt1 = DateTime( - dt.year(), - dt.month(), - dt.day(), - dt.hour(), - dt.minute(), - dt.second(), - dt.timezone()) - # Compare representations as it's the - # only way to compare the dates to the same accuracy - self.assertEqual(repr(dt), repr(dt1)) - - def testDayOfWeek(self): - # Compare to the datetime.date value to make it locale independent - expected = date(2000, 6, 16).strftime('%A') - # strftime() used to always be passed a day of week of 0 - dt = DateTime('2000/6/16') - s = dt.strftime('%A') - self.assertEqual(s, expected, (dt, s)) - - def testOldDate(self): - # Fails when an 1800 date is displayed with negative signs - dt = DateTime('1830/5/6 12:31:46.213 pm') - dt1 = dt.toZone('GMT+6') - self.assertTrue(str(dt1).find('-') < 0, (dt, dt1)) - - def testSubtraction(self): - # Reconstruction of a DateTime from its parts, with subtraction - # this also tests the accuracy of addition and reconstruction - dt = DateTime() - dt1 = dt - 3.141592653 - dt2 = DateTime( - dt.year(), - dt.month(), - dt.day(), - dt.hour(), - dt.minute(), - dt.second()) - dt3 = dt2 - 3.141592653 - self.assertEqual(dt1, dt3, (dt, dt1, dt2, dt3)) - - def testTZ1add(self): - # Time zone manipulation: add to a date - dt = DateTime('1997/3/8 1:45am GMT-4') - dt1 = DateTime('1997/3/9 1:45pm GMT+8') - self.assertTrue((dt + 1.0).equalTo(dt1)) - - def testTZ1sub(self): - # Time zone manipulation: subtract from a date - dt = DateTime('1997/3/8 1:45am GMT-4') - dt1 = DateTime('1997/3/9 1:45pm GMT+8') - self.assertTrue((dt1 - 1.0).equalTo(dt)) - - def testTZ1diff(self): - # Time zone manipulation: diff two dates - dt = DateTime('1997/3/8 1:45am GMT-4') - dt1 = DateTime('1997/3/9 1:45pm GMT+8') - self.assertEqual(dt1 - dt, 1.0, (dt, dt1)) - - def test_compare_methods(self): - # Compare two dates using several methods - dt = DateTime('1997/1/1') - dt1 = DateTime('1997/2/2') - self.assertTrue(dt1.greaterThan(dt)) - self.assertTrue(dt1.greaterThanEqualTo(dt)) - self.assertTrue(dt.lessThan(dt1)) - self.assertTrue(dt.lessThanEqualTo(dt1)) - self.assertTrue(dt.notEqualTo(dt1)) - self.assertFalse(dt.equalTo(dt1)) - # Compare a date to float - dt = DateTime(1.0) - self.assertTrue(dt == DateTime(1.0)) # testing __eq__ - self.assertFalse(dt != DateTime(1.0)) # testing __ne__ - self.assertFalse(dt.greaterThan(1.0)) - self.assertTrue(dt.greaterThanEqualTo(1.0)) - self.assertFalse(dt.lessThan(1.0)) - self.assertTrue(dt.lessThanEqualTo(1.0)) - self.assertFalse(dt.notEqualTo(1.0)) - self.assertTrue(dt.equalTo(1.0)) - # Compare a date to int - dt = DateTime(1) - self.assertEqual(dt, DateTime(1.0)) - self.assertTrue(dt == DateTime(1)) # testing __eq__ - self.assertFalse(dt != DateTime(1)) # testing __ne__ - self.assertFalse(dt.greaterThan(1)) - self.assertTrue(dt.greaterThanEqualTo(1)) - self.assertFalse(dt.lessThan(1)) - self.assertTrue(dt.lessThanEqualTo(1)) - self.assertFalse(dt.notEqualTo(1)) - self.assertTrue(dt.equalTo(1)) - # Compare a date to string; there is no implicit type conversion - # but behavior if consistent as when comparing, for example, an int - # and a string. - dt = DateTime("2023") - self.assertFalse(dt == "2023") # testing __eq__ - self.assertTrue(dt != "2023") # testing __ne__ - self.assertRaises(TypeError, dt.greaterThan, "2023") - self.assertRaises(TypeError, dt.greaterThanEqualTo, "2023") - self.assertRaises(TypeError, dt.lessThan, "2023") - self.assertRaises(TypeError, dt.lessThanEqualTo, "2023") - self.assertTrue(dt.notEqualTo("2023")) - self.assertFalse(dt.equalTo("2023")) - - def test_compare_methods_none(self): - # Compare a date to None - for dt in (DateTime('1997/1/1'), DateTime(0)): - self.assertTrue(dt.greaterThan(None)) - self.assertTrue(dt.greaterThanEqualTo(None)) - self.assertFalse(dt.lessThan(None)) - self.assertFalse(dt.lessThanEqualTo(None)) - self.assertTrue(dt.notEqualTo(None)) - self.assertFalse(dt.equalTo(None)) - - def test_pickle(self): - dt = DateTime() - data = pickle.dumps(dt, 1) - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_with_tz(self): - dt = DateTime('2002/5/2 8:00am GMT+8') - data = pickle.dumps(dt, 1) - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_asdatetime_with_tz(self): - dt = DateTime('2002/5/2 8:00am GMT+8') - data = pickle.dumps(dt.asdatetime(), 1) - new = DateTime(pickle.loads(data)) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_with_numerical_tz(self): - for dt_str in ('2007/01/02 12:34:56.789 +0300', - '2007/01/02 12:34:56.789 +0430', - '2007/01/02 12:34:56.789 -1234'): - dt = DateTime(dt_str) - data = pickle.dumps(dt, 1) - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_with_micros(self): - dt = DateTime('2002/5/2 8:00:14.123 GMT+8') - data = pickle.dumps(dt, 1) - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_old(self): - dt = DateTime('2002/5/2 8:00am GMT+0') - data = ( - '(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05' - '_amonq\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq' - '\x08h\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU' - '\x04Thu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU\x02amq' - '\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq\x12K\x00U' - '\x07_microsq\x13L1020326400000000L\nU\x02_dq\x14G@\xe2\x12j\xaa' - '\xaa\xaa\xabU\x07_secondq\x15G\x00\x00\x00\x00\x00\x00\x00\x00U' - '\x03_tzq\x16U\x05GMT+0q\x17U\x06_monthq\x18K\x05U' - '\x0f_timezone_naiveq\x19I00\nU\x04_dayq\x1aK\x02U\x05_yearq' - '\x1bM\xd2\x07U\x08_nearsecq\x1cG\x00\x00\x00\x00\x00\x00\x00' - '\x00U\x07_pmhourq\x1dK\x08U\n_dayoffsetq\x1eK\x04U\x04timeq' - '\x1fG?\xd5UUUV\x00\x00ub.') - data = data.encode('latin-1') - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_old_without_micros(self): - dt = DateTime('2002/5/2 8:00am GMT+0') - data = ( - '(cDateTime.DateTime\nDateTime\nq\x01Noq\x02}q\x03(U\x05' - '_amonq\x04U\x03Mayq\x05U\x05_adayq\x06U\x03Thuq\x07U\x05_pmonq' - '\x08h\x05U\x05_hourq\tK\x08U\x05_fmonq\nh\x05U\x05_pdayq\x0bU' - '\x04Thu.q\x0cU\x05_fdayq\rU\x08Thursdayq\x0eU\x03_pmq\x0fU' - '\x02amq\x10U\x02_tq\x11GA\xcehy\x00\x00\x00\x00U\x07_minuteq' - '\x12K\x00U\x02_dq\x13G@\xe2\x12j\xaa\xaa\xaa\xabU\x07_secondq' - '\x14G\x00\x00\x00\x00\x00\x00\x00\x00U\x03_tzq\x15U\x05GMT+0q' - '\x16U\x06_monthq\x17K\x05U\x0f_timezone_naiveq\x18I00\nU' - '\x04_dayq\x19K\x02U\x05_yearq\x1aM\xd2\x07U\x08_nearsecq' - '\x1bG\x00\x00\x00\x00\x00\x00\x00\x00U\x07_pmhourq\x1cK\x08U' - '\n_dayoffsetq\x1dK\x04U\x04timeq\x1eG?\xd5UUUV\x00\x00ub.') - data = data.encode('latin-1') - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_dates_after_2038(self): - dt = DateTime('2039/09/02 07:07:6.235027 GMT+1') - data = pickle.dumps(dt, 1) - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def test_pickle_old_with_micros_as_float(self): - dt = DateTime('2002/5/2 8:00am GMT+0') - data = ( - 'ccopy_reg\n_reconstructor\nq\x00(cDateTime.DateTime\nDateTime' - '\nq\x01c__builtin__\nobject\nq\x02Ntq\x03Rq\x04(GA\xcehy\x00\x00' - '\x00\x00I00\nX\x05\x00\x00\x00GMT+0q\x05tq\x06b.') - data = data.encode('latin-1') - new = pickle.loads(data) - for key in DateTime.__slots__: - self.assertEqual(getattr(dt, key), getattr(new, key)) - - def testTZ2(self): - # Time zone manipulation test 2 - dt = DateTime() - dt1 = dt.toZone('GMT') - s = dt.second() - s1 = dt1.second() - self.assertEqual(s, s1, (dt, dt1, s, s1)) - - def testTZDiffDaylight(self): - # Diff dates across daylight savings dates - dt = DateTime('2000/6/8 1:45am US/Eastern') - dt1 = DateTime('2000/12/8 12:45am US/Eastern') - self.assertEqual(dt1 - dt, 183, (dt, dt1, dt1 - dt)) - - def testY10KDate(self): - # Comparison of a Y10K date and a Y2K date - dt = DateTime('10213/09/21') - dt1 = DateTime(2000, 1, 1) - - dsec = (dt.millis() - dt1.millis()) / 1000.0 - ddays = math.floor((dsec / 86400.0) + 0.5) - - self.assertEqual(ddays, 3000000, ddays) - - def test_tzoffset(self): - # Test time-zone given as an offset - - # GMT - dt = DateTime('Tue, 10 Sep 2001 09:41:03 GMT') - self.assertEqual(dt.tzoffset(), 0) - - # Timezone by name, a timezone that hasn't got daylightsaving. - dt = DateTime('Tue, 2 Mar 2001 09:41:03 GMT+3') - self.assertEqual(dt.tzoffset(), 10800) - - # Timezone by name, has daylightsaving but is not in effect. - dt = DateTime('Tue, 21 Jan 2001 09:41:03 PST') - self.assertEqual(dt.tzoffset(), -28800) - - # Timezone by name, with daylightsaving in effect - dt = DateTime('Tue, 24 Aug 2001 09:41:03 PST') - self.assertEqual(dt.tzoffset(), -25200) - - # A negative numerical timezone - dt = DateTime('Tue, 24 Jul 2001 09:41:03 -0400') - self.assertEqual(dt.tzoffset(), -14400) - - # A positive numerical timzone - dt = DateTime('Tue, 6 Dec 1966 01:41:03 +0200') - self.assertEqual(dt.tzoffset(), 7200) - - # A negative numerical timezone with minutes. - dt = DateTime('Tue, 24 Jul 2001 09:41:03 -0637') - self.assertEqual(dt.tzoffset(), -23820) - - # A positive numerical timezone with minutes. - dt = DateTime('Tue, 24 Jul 2001 09:41:03 +0425') - self.assertEqual(dt.tzoffset(), 15900) - - def testISO8601(self): - # ISO8601 reference dates - ref0 = DateTime('2002/5/2 8:00am GMT') - ref1 = DateTime('2002/5/2 8:00am US/Eastern') - ref2 = DateTime('2006/11/6 10:30 GMT') - ref3 = DateTime('2004/06/14 14:30:15 GMT-3') - ref4 = DateTime('2006/01/01 GMT') - - # Basic tests - # Though this is timezone naive and according to specification should - # be interpreted in the local timezone, to preserve backwards - # compatibility with previously expected behaviour. - isoDt = DateTime('2002-05-02T08:00:00') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002-05-02T08:00:00Z') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002-05-02T08:00:00+00:00') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002-05-02T08:00:00-04:00') - self.assertTrue(ref1.equalTo(isoDt)) - isoDt = DateTime('2002-05-02 08:00:00-04:00') - self.assertTrue(ref1.equalTo(isoDt)) - - # Bug 1386: the colon in the timezone offset is optional - isoDt = DateTime('2002-05-02T08:00:00-0400') - self.assertTrue(ref1.equalTo(isoDt)) - - # Bug 2191: date reduced formats - isoDt = DateTime('2006-01-01') - self.assertTrue(ref4.equalTo(isoDt)) - isoDt = DateTime('200601-01') - self.assertTrue(ref4.equalTo(isoDt)) - isoDt = DateTime('20060101') - self.assertTrue(ref4.equalTo(isoDt)) - isoDt = DateTime('2006-01') - self.assertTrue(ref4.equalTo(isoDt)) - isoDt = DateTime('200601') - self.assertTrue(ref4.equalTo(isoDt)) - isoDt = DateTime('2006') - self.assertTrue(ref4.equalTo(isoDt)) - - # Bug 2191: date/time separators are also optional - isoDt = DateTime('20020502T08:00:00') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002-05-02T080000') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('20020502T080000') - self.assertTrue(ref0.equalTo(isoDt)) - - # Bug 2191: timezones with only one digit for hour - isoDt = DateTime('20020502T080000+0') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('20020502 080000-4') - self.assertTrue(ref1.equalTo(isoDt)) - isoDt = DateTime('20020502T080000-400') - self.assertTrue(ref1.equalTo(isoDt)) - isoDt = DateTime('20020502T080000-4:00') - self.assertTrue(ref1.equalTo(isoDt)) - - # Bug 2191: optional seconds/minutes - isoDt = DateTime('2002-05-02T0800') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002-05-02T08') - self.assertTrue(ref0.equalTo(isoDt)) - - # Bug 2191: week format - isoDt = DateTime('2002-W18-4T0800') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002-W184T0800') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002W18-4T0800') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002W184T08') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2004-W25-1T14:30:15-03:00') - self.assertTrue(ref3.equalTo(isoDt)) - isoDt = DateTime('2004-W25T14:30:15-03:00') - self.assertTrue(ref3.equalTo(isoDt)) - - # Bug 2191: day of year format - isoDt = DateTime('2002-122T0800') - self.assertTrue(ref0.equalTo(isoDt)) - isoDt = DateTime('2002122T0800') - self.assertTrue(ref0.equalTo(isoDt)) - - # Bug 2191: hours/minutes fractions - isoDt = DateTime('2006-11-06T10.5') - self.assertTrue(ref2.equalTo(isoDt)) - isoDt = DateTime('2006-11-06T10,5') - self.assertTrue(ref2.equalTo(isoDt)) - isoDt = DateTime('20040614T1430.25-3') - self.assertTrue(ref3.equalTo(isoDt)) - isoDt = DateTime('2004-06-14T1430,25-3') - self.assertTrue(ref3.equalTo(isoDt)) - isoDt = DateTime('2004-06-14T14:30.25-3') - self.assertTrue(ref3.equalTo(isoDt)) - isoDt = DateTime('20040614T14:30,25-3') - self.assertTrue(ref3.equalTo(isoDt)) - - # ISO8601 standard format - iso8601_string = '2002-05-02T08:00:00-04:00' - iso8601DT = DateTime(iso8601_string) - self.assertEqual(iso8601_string, iso8601DT.ISO8601()) - - # ISO format with no timezone - isoDt = DateTime('2006-01-01 00:00:00') - self.assertTrue(ref4.equalTo(isoDt)) - - def testJulianWeek(self): - # Check JulianDayWeek function - fn = os.path.join(DATADIR, 'julian_testdata.txt') - with open(fn) as fd: - lines = fd.readlines() - for line in lines: - d = DateTime(line[:10]) - result_from_mx = tuple(map(int, line[12:-2].split(','))) - self.assertEqual(result_from_mx[1], d.week()) - - def testCopyConstructor(self): - d = DateTime('2004/04/04') - self.assertEqual(DateTime(d), d) - self.assertEqual(str(DateTime(d)), str(d)) - d2 = DateTime('1999/04/12 01:00:00') - self.assertEqual(DateTime(d2), d2) - self.assertEqual(str(DateTime(d2)), str(d2)) - - def testCopyConstructorPreservesTimezone(self): - # test for https://bugs.launchpad.net/zope2/+bug/200007 - # This always worked in the local timezone, so we need at least - # two tests with different zones to be sure at least one of them - # is not local. - d = DateTime('2004/04/04') - self.assertEqual(DateTime(d).timezone(), d.timezone()) - d2 = DateTime('2008/04/25 12:00:00 EST') - self.assertEqual(DateTime(d2).timezone(), d2.timezone()) - self.assertEqual(str(DateTime(d2)), str(d2)) - d3 = DateTime('2008/04/25 12:00:00 PST') - self.assertEqual(DateTime(d3).timezone(), d3.timezone()) - self.assertEqual(str(DateTime(d3)), str(d3)) - - def testRFC822(self): - # rfc822 conversion - dt = DateTime('2002-05-02T08:00:00+00:00') - self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 +0000') - - dt = DateTime('2002-05-02T08:00:00+02:00') - self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 +0200') - - dt = DateTime('2002-05-02T08:00:00-02:00') - self.assertEqual(dt.rfc822(), 'Thu, 02 May 2002 08:00:00 -0200') - - # Checking that conversion from local time is working. - dt = DateTime() - dts = dt.rfc822().split(' ') - times = dts[4].split(':') - _isDST = time.localtime(time.time())[8] - if _isDST: - offset = time.altzone - else: - offset = time.timezone - self.assertEqual(dts[0], dt.aDay() + ',') - self.assertEqual(int(dts[1]), dt.day()) - self.assertEqual(dts[2], dt.aMonth()) - self.assertEqual(int(dts[3]), dt.year()) - self.assertEqual(int(times[0]), dt.h_24()) - self.assertEqual(int(times[1]), dt.minute()) - self.assertEqual(int(times[2]), int(dt.second())) - self.assertEqual(dts[5], "%+03d%02d" % divmod((-offset / 60), 60)) - - def testInternationalDateformat(self): - for year in (1990, 2001, 2020): - for month in (1, 12): - for day in (1, 12, 28, 31): - try: - d_us = DateTime("%d/%d/%d" % (year, month, day)) - except Exception: - continue - - d_int = DateTime("%d.%d.%d" % (day, month, year), - datefmt="international") - self.assertEqual(d_us, d_int) - - d_int = DateTime("%d/%d/%d" % (day, month, year), - datefmt="international") - self.assertEqual(d_us, d_int) - - def test_intl_format_hyphen(self): - d_jan = DateTime('2011-01-11 GMT') - d_nov = DateTime('2011-11-01 GMT') - d_us = DateTime('11-01-2011 GMT') - d_int = DateTime('11-01-2011 GMT', datefmt="international") - self.assertNotEqual(d_us, d_int) - self.assertEqual(d_us, d_nov) - self.assertEqual(d_int, d_jan) - - def test_calcTimezoneName(self): - from DateTime.interfaces import TimeError - timezone_dependent_epoch = 2177452800 - try: - DateTime()._calcTimezoneName(timezone_dependent_epoch, 0) - except TimeError: - self.fail('Zope Collector issue #484 (negative time bug): ' - 'TimeError raised') - - def testStrftimeTZhandling(self): - # strftime timezone testing - # This is a test for collector issue #1127 - format = '%Y-%m-%d %H:%M %Z' - dt = DateTime('Wed, 19 Nov 2003 18:32:07 -0215') - dt_string = dt.strftime(format) - dt_local = dt.toZone(_findLocalTimeZoneName(0)) - dt_localstring = dt_local.strftime(format) - self.assertEqual(dt_string, dt_localstring) - - def testStrftimeFarDates(self): - # Checks strftime in dates <= 1900 or >= 2038 - dt = DateTime('1900/01/30') - self.assertEqual(dt.strftime('%d/%m/%Y'), '30/01/1900') - dt = DateTime('2040/01/30') - self.assertEqual(dt.strftime('%d/%m/%Y'), '30/01/2040') - - def testZoneInFarDates(self): - # Checks time zone in dates <= 1900 or >= 2038 - dt1 = DateTime('2040/01/30 14:33 GMT+1') - dt2 = DateTime('2040/01/30 11:33 GMT-2') - self.assertEqual(dt1.strftime('%d/%m/%Y %H:%M'), - dt2.strftime('%d/%m/%Y %H:%M')) - - @unittest.skipIf( - IS_PYPY, - "Using Non-Ascii characters for strftime doesn't work in PyPy" - "https://bitbucket.org/pypy/pypy/issues/2161/pypy3-strftime-does-not-accept-unicode" # noqa: E501 line too long - ) - def testStrftimeStr(self): - dt = DateTime('2002-05-02T08:00:00+00:00') - uchar = b'\xc3\xa0'.decode('utf-8') - ok = dt.strftime('Le %d/%m/%Y a %Hh%M').replace('a', uchar) - ustr = b'Le %d/%m/%Y \xc3\xa0 %Hh%M'.decode('utf-8') - self.assertEqual(dt.strftime(ustr), ok) - - def testTimezoneNaiveHandling(self): - # checks that we assign timezone naivity correctly - dt = DateTime('2007-10-04T08:00:00+00:00') - self.assertFalse(dt.timezoneNaive(), - 'error with naivity handling in __parse_iso8601') - dt = DateTime('2007-10-04T08:00:00Z') - self.assertFalse(dt.timezoneNaive(), - 'error with naivity handling in __parse_iso8601') - dt = DateTime('2007-10-04T08:00:00') - self.assertTrue(dt.timezoneNaive(), - 'error with naivity handling in __parse_iso8601') - dt = DateTime('2007/10/04 15:12:33.487618 GMT+1') - self.assertFalse(dt.timezoneNaive(), - 'error with naivity handling in _parse') - dt = DateTime('2007/10/04 15:12:33.487618') - self.assertTrue(dt.timezoneNaive(), - 'error with naivity handling in _parse') - dt = DateTime() - self.assertFalse(dt.timezoneNaive(), - 'error with naivity for current time') - s = '2007-10-04T08:00:00' - dt = DateTime(s) - self.assertEqual(s, dt.ISO8601()) - s = '2007-10-04T08:00:00+00:00' - dt = DateTime(s) - self.assertEqual(s, dt.ISO8601()) - - def testConversions(self): - sdt0 = datetime.now() # this is a timezone naive datetime - dt0 = DateTime(sdt0) - self.assertTrue(dt0.timezoneNaive(), (sdt0, dt0)) - sdt1 = datetime(2007, 10, 4, 18, 14, 42, 580, pytz.utc) - dt1 = DateTime(sdt1) - self.assertFalse(dt1.timezoneNaive(), (sdt1, dt1)) - - # convert back - sdt2 = dt0.asdatetime() - self.assertEqual(sdt0, sdt2) - sdt3 = dt1.utcdatetime() # this returns a timezone naive datetime - self.assertEqual(sdt1.hour, sdt3.hour) - - dt4 = DateTime('2007-10-04T10:00:00+05:00') - sdt4 = datetime(2007, 10, 4, 5, 0) - self.assertEqual(dt4.utcdatetime(), sdt4) - self.assertEqual(dt4.asdatetime(), sdt4.replace(tzinfo=pytz.utc)) - - dt5 = DateTime('2007-10-23 10:00:00 US/Eastern') - tz = pytz.timezone('US/Eastern') - sdt5 = datetime(2007, 10, 23, 10, 0, tzinfo=tz) - dt6 = DateTime(sdt5) - self.assertEqual(dt5.asdatetime(), sdt5) - self.assertEqual(dt6.asdatetime(), sdt5) - self.assertEqual(dt5, dt6) - self.assertEqual(dt5.asdatetime().tzinfo, tz) - self.assertEqual(dt6.asdatetime().tzinfo, tz) - - def testBasicTZ(self): - # psycopg2 supplies it's own tzinfo instances, with no `zone` attribute - tz = FixedOffset(60, 'GMT+1') - dt1 = datetime(2008, 8, 5, 12, 0, tzinfo=tz) - DT = DateTime(dt1) - dt2 = DT.asdatetime() - offset1 = dt1.tzinfo.utcoffset(dt1) - offset2 = dt2.tzinfo.utcoffset(dt2) - self.assertEqual(offset1, offset2) - - def testEDTTimezone(self): - # should be able to parse EDT timezones: see lp:599856. - dt = DateTime("Mon, 28 Jun 2010 10:12:25 EDT") - self.assertEqual(dt.Day(), 'Monday') - self.assertEqual(dt.day(), 28) - self.assertEqual(dt.Month(), 'June') - self.assertEqual(dt.timezone(), 'GMT-4') - - def testParseISO8601(self): - parsed = DateTime()._parse_iso8601('2010-10-10') - self.assertEqual(parsed, (2010, 10, 10, 0, 0, 0, 'GMT+0000')) - - def test_interface(self): - from DateTime.interfaces import IDateTime - self.assertTrue(IDateTime.providedBy(DateTime())) - - def test_security(self): - dt = DateTime() - self.assertEqual(dt.__roles__, None) - self.assertEqual(dt.__allow_access_to_unprotected_subobjects__, 1) - - def test_format(self): - dt = DateTime(1968, 3, 10, 23, 45, 0, 'Europe/Vienna') - fmt = '%d.%m.%Y %H:%M' - result = dt.strftime(fmt) - unformatted_result = '1968/03/10 23:45:00 Europe/Vienna' - self.assertEqual(result, f'{dt:%d.%m.%Y %H:%M}') - self.assertEqual(unformatted_result, f'{dt}') - self.assertEqual(unformatted_result, f'{dt}') - self.assertEqual(result, f'{dt:{fmt}}') - self.assertEqual(unformatted_result, f'{dt:}') - self.assertEqual(unformatted_result, f'{dt}') - - -def test_suite(): - import doctest - return unittest.TestSuite([ - unittest.defaultTestLoader.loadTestsFromTestCase(DateTimeTests), - doctest.DocFileSuite('DateTime.txt', package='DateTime'), - doctest.DocFileSuite('pytz.txt', package='DateTime'), - ]) diff --git a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER b/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt b/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt deleted file mode 100644 index 9d227a0..0000000 --- a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt +++ /dev/null @@ -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. diff --git a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA b/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA deleted file mode 100644 index 82261f2..0000000 --- a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/METADATA +++ /dev/null @@ -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 -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("") -Markup('<script>alert(document.cookie);</script>') - ->>> # wrap in Markup to mark text "safe" and prevent escaping ->>> Markup("Hello") -Markup('hello') - ->>> escape(Markup("Hello")) -Markup('hello') - ->>> # Markup is a str subclass ->>> # methods and operators escape their arguments ->>> template = Markup("Hello {name}") ->>> template.format(name='"World"') -Markup('Hello "World"') -``` - -## 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 diff --git a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD b/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD deleted file mode 100644 index 0c652a7..0000000 --- a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/RECORD +++ /dev/null @@ -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=IqiWNwTSPPvorR7mTezuRY2eqj__44JKKkjOiewDX64,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-310.pyc,, -markupsafe/__pycache__/_native.cpython-310.pyc,, -markupsafe/_native.py,sha256=2ptkJ40yCcp9kq3L1NqpgjfpZB-obniYKFFKUOkHh4Q,218 -markupsafe/_speedups.c,sha256=SglUjn40ti9YgQAO--OgkSyv9tXq9vvaHyVhQows4Ok,4353 -markupsafe/_speedups.cp310-win_amd64.pyd,sha256=RTvh-UzJTX7J_4j-A5jZmnqwRKBe0pQiDPd_j60jft8,13312 -markupsafe/_speedups.pyi,sha256=LSDmXYOefH4HVpAXuL8sl7AttLw0oXh1njVoVZp2wqQ,42 -markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL b/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL deleted file mode 100644 index c4388f8..0000000 --- a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (75.2.0) -Root-Is-Purelib: false -Tag: cp310-cp310-win_amd64 - diff --git a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt b/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt deleted file mode 100644 index 75bf729..0000000 --- a/venv/Lib/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -markupsafe diff --git a/venv/Lib/site-packages/__pycache__/pathlib.cpython-310.pyc b/venv/Lib/site-packages/__pycache__/pathlib.cpython-310.pyc deleted file mode 100644 index 7720b0e7f7bbe13ad62dc2f45b642992bcdaf499..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36192 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 diff --git a/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc b/venv/Lib/site-packages/_distutils_hack/__pycache__/override.cpython-310.pyc deleted file mode 100644 index e5c44bbfb4333b2e85e93c9ff4307351f9eb4099..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224 zcmd1j<>g`kf}8hbGjxFTV-N=!FabFZKwK;UBvKht7@8RuFfL?ZWJqBQX3%7c;*U?s zEG{W6$;>H^&qz$p_S0m##T6f)nOl%wR1zN_#hsELpI??*RFs*Lx{{#?WE`0I72s?Y z6Iz^FR2)-~o}Zf<bQ=D0ns#^dwIWax8I0nr& ceVEaD1(mlrY;yBcN^?@}7(wm@*(AUK05=9dxBvhE diff --git a/venv/Lib/site-packages/_distutils_hack/override.py b/venv/Lib/site-packages/_distutils_hack/override.py deleted file mode 100644 index 2cc433a..0000000 --- a/venv/Lib/site-packages/_distutils_hack/override.py +++ /dev/null @@ -1 +0,0 @@ -__import__('_distutils_hack').do_override() diff --git a/venv/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER b/venv/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/blinker-1.9.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt b/venv/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt deleted file mode 100644 index 79c9825..0000000 --- a/venv/Lib/site-packages/blinker-1.9.0.dist-info/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2010 Jason Kirtland - -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. diff --git a/venv/Lib/site-packages/blinker-1.9.0.dist-info/METADATA b/venv/Lib/site-packages/blinker-1.9.0.dist-info/METADATA deleted file mode 100644 index 6d343f5..0000000 --- a/venv/Lib/site-packages/blinker-1.9.0.dist-info/METADATA +++ /dev/null @@ -1,60 +0,0 @@ -Metadata-Version: 2.3 -Name: blinker -Version: 1.9.0 -Summary: Fast, simple object-to-object and broadcast signaling -Author: Jason Kirtland -Maintainer-email: Pallets Ecosystem -Requires-Python: >=3.9 -Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Typing :: Typed -Project-URL: Chat, https://discord.gg/pallets -Project-URL: Documentation, https://blinker.readthedocs.io -Project-URL: Source, https://github.com/pallets-eco/blinker/ - -# Blinker - -Blinker provides a fast dispatching system that allows any number of -interested parties to subscribe to events, or "signals". - - -## Pallets Community Ecosystem - -> [!IMPORTANT]\ -> This project is part of the Pallets Community Ecosystem. Pallets is the open -> source organization that maintains Flask; Pallets-Eco enables community -> maintenance of related projects. If you are interested in helping maintain -> this project, please reach out on [the Pallets Discord server][discord]. -> -> [discord]: https://discord.gg/pallets - - -## Example - -Signal receivers can subscribe to specific senders or receive signals -sent by any sender. - -```pycon ->>> from blinker import signal ->>> started = signal('round-started') ->>> def each(round): -... print(f"Round {round}") -... ->>> started.connect(each) - ->>> def round_two(round): -... print("This is round two.") -... ->>> started.connect(round_two, sender=2) - ->>> for round in range(1, 4): -... started.send(round) -... -Round 1! -Round 2! -This is round two. -Round 3! -``` - diff --git a/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD b/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD deleted file mode 100644 index e6ed9e3..0000000 --- a/venv/Lib/site-packages/blinker-1.9.0.dist-info/RECORD +++ /dev/null @@ -1,12 +0,0 @@ -blinker-1.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -blinker-1.9.0.dist-info/LICENSE.txt,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054 -blinker-1.9.0.dist-info/METADATA,sha256=uIRiM8wjjbHkCtbCyTvctU37IAZk0kEe5kxAld1dvzA,1633 -blinker-1.9.0.dist-info/RECORD,, -blinker-1.9.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 -blinker/__init__.py,sha256=I2EdZqpy4LyjX17Hn1yzJGWCjeLaVaPzsMgHkLfj_cQ,317 -blinker/__pycache__/__init__.cpython-310.pyc,, -blinker/__pycache__/_utilities.cpython-310.pyc,, -blinker/__pycache__/base.cpython-310.pyc,, -blinker/_utilities.py,sha256=0J7eeXXTUx0Ivf8asfpx0ycVkp0Eqfqnj117x2mYX9E,1675 -blinker/base.py,sha256=QpDuvXXcwJF49lUBcH5BiST46Rz9wSG7VW_p7N_027M,19132 -blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL b/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL deleted file mode 100644 index e3c6fee..0000000 --- a/venv/Lib/site-packages/blinker-1.9.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.10.1 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/Lib/site-packages/blinker/__init__.py b/venv/Lib/site-packages/blinker/__init__.py deleted file mode 100644 index 1772fa4..0000000 --- a/venv/Lib/site-packages/blinker/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from __future__ import annotations - -from .base import ANY -from .base import default_namespace -from .base import NamedSignal -from .base import Namespace -from .base import Signal -from .base import signal - -__all__ = [ - "ANY", - "default_namespace", - "NamedSignal", - "Namespace", - "Signal", - "signal", -] diff --git a/venv/Lib/site-packages/blinker/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/blinker/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 6af01e4823adbe652b7948163fae456c8a147c6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463 zcmaKoyH3L}6o&0woJ(5?9)Jhv01Rvh5Qri%R9z|tEKA14Zm{Y&QJhrbb=Y{NEDTJ2 z1tyMzsF*mGet-Y5eQcjf*pbjJ3s9cQzfq)BN(tqcWPL+T#5AQVMZDJnuG2a%}^xWlb&65jqBwFzl8pA7CcCkJXe7fdL#>A6n+3hB?A#;=B`vkzQJv5Yy`EW zM-TgD`7jJJ^*+L|?Z{Dm#|?f%hLdJJy{DtiJW=ZBMDFq|)w@c|wds9(dzD*Tpem;T zT`C)>RkPMIwTw6G$%bY6Qx(BxOvmIEIVRG_bxiM)ZKCOfoLgh^mi}gqVMY8p8AD_* z=vHV;7tU1;H5v+8xr`O!HDjS&*=eq%hcp{pcR{N;#!}Rou?uqf!{#^Lmr6+09Uhbe z(S0V=kuHbb7tg*sPV(-tD2}@?vR+qZT09;m=}~eZRJWIB#gULt*hpu2rZb_U;fY)T zA$Qea!=tHAm9teA;ywG(7x-^tdf{obpFv%06FCpt3u-I~t;$g% z@0*QW20}gE0;uvB%Zf}h7Qjy7Z9YBiT#K%0DFyu1Kp1}`6$+N1Pp1;)D(pe*ZCL(8 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 diff --git a/venv/Lib/site-packages/blinker/_utilities.py b/venv/Lib/site-packages/blinker/_utilities.py deleted file mode 100644 index 000c902..0000000 --- a/venv/Lib/site-packages/blinker/_utilities.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import annotations - -import collections.abc as c -import inspect -import typing as t -from weakref import ref -from weakref import WeakMethod - -T = t.TypeVar("T") - - -class Symbol: - """A constant symbol, nicer than ``object()``. Repeated calls return the - same instance. - - >>> Symbol('foo') is Symbol('foo') - True - >>> Symbol('foo') - foo - """ - - symbols: t.ClassVar[dict[str, Symbol]] = {} - - def __new__(cls, name: str) -> Symbol: - if name in cls.symbols: - return cls.symbols[name] - - obj = super().__new__(cls) - cls.symbols[name] = obj - return obj - - def __init__(self, name: str) -> None: - self.name = name - - def __repr__(self) -> str: - return self.name - - def __getnewargs__(self) -> tuple[t.Any, ...]: - return (self.name,) - - -def make_id(obj: object) -> c.Hashable: - """Get a stable identifier for a receiver or sender, to be used as a dict - key or in a set. - """ - if inspect.ismethod(obj): - # The id of a bound method is not stable, but the id of the unbound - # function and instance are. - return id(obj.__func__), id(obj.__self__) - - if isinstance(obj, (str, int)): - # Instances with the same value always compare equal and have the same - # hash, even if the id may change. - return obj - - # Assume other types are not hashable but will always be the same instance. - return id(obj) - - -def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]: - if inspect.ismethod(obj): - return WeakMethod(obj, callback) # type: ignore[arg-type, return-value] - - return ref(obj, callback) diff --git a/venv/Lib/site-packages/blinker/base.py b/venv/Lib/site-packages/blinker/base.py deleted file mode 100644 index d051b94..0000000 --- a/venv/Lib/site-packages/blinker/base.py +++ /dev/null @@ -1,512 +0,0 @@ -from __future__ import annotations - -import collections.abc as c -import sys -import typing as t -import weakref -from collections import defaultdict -from contextlib import contextmanager -from functools import cached_property -from inspect import iscoroutinefunction - -from ._utilities import make_id -from ._utilities import make_ref -from ._utilities import Symbol - -F = t.TypeVar("F", bound=c.Callable[..., t.Any]) - -ANY = Symbol("ANY") -"""Symbol for "any sender".""" - -ANY_ID = 0 - - -class Signal: - """A notification emitter. - - :param doc: The docstring for the signal. - """ - - ANY = ANY - """An alias for the :data:`~blinker.ANY` sender symbol.""" - - set_class: type[set[t.Any]] = set - """The set class to use for tracking connected receivers and senders. - Python's ``set`` is unordered. If receivers must be dispatched in the order - they were connected, an ordered set implementation can be used. - - .. versionadded:: 1.7 - """ - - @cached_property - def receiver_connected(self) -> Signal: - """Emitted at the end of each :meth:`connect` call. - - The signal sender is the signal instance, and the :meth:`connect` - arguments are passed through: ``receiver``, ``sender``, and ``weak``. - - .. versionadded:: 1.2 - """ - return Signal(doc="Emitted after a receiver connects.") - - @cached_property - def receiver_disconnected(self) -> Signal: - """Emitted at the end of each :meth:`disconnect` call. - - The sender is the signal instance, and the :meth:`disconnect` arguments - are passed through: ``receiver`` and ``sender``. - - This signal is emitted **only** when :meth:`disconnect` is called - explicitly. This signal cannot be emitted by an automatic disconnect - when a weakly referenced receiver or sender goes out of scope, as the - instance is no longer be available to be used as the sender for this - signal. - - An alternative approach is available by subscribing to - :attr:`receiver_connected` and setting up a custom weakref cleanup - callback on weak receivers and senders. - - .. versionadded:: 1.2 - """ - return Signal(doc="Emitted after a receiver disconnects.") - - def __init__(self, doc: str | None = None) -> None: - if doc: - self.__doc__ = doc - - self.receivers: dict[ - t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any] - ] = {} - """The map of connected receivers. Useful to quickly check if any - receivers are connected to the signal: ``if s.receivers:``. The - structure and data is not part of the public API, but checking its - boolean value is. - """ - - self.is_muted: bool = False - self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) - self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class) - self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {} - - def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F: - """Connect ``receiver`` to be called when the signal is sent by - ``sender``. - - :param receiver: The callable to call when :meth:`send` is called with - the given ``sender``, passing ``sender`` as a positional argument - along with any extra keyword arguments. - :param sender: Any object or :data:`ANY`. ``receiver`` will only be - called when :meth:`send` is called with this sender. If ``ANY``, the - receiver will be called for any sender. A receiver may be connected - to multiple senders by calling :meth:`connect` multiple times. - :param weak: Track the receiver with a :mod:`weakref`. The receiver will - be automatically disconnected when it is garbage collected. When - connecting a receiver defined within a function, set to ``False``, - otherwise it will be disconnected when the function scope ends. - """ - receiver_id = make_id(receiver) - sender_id = ANY_ID if sender is ANY else make_id(sender) - - if weak: - self.receivers[receiver_id] = make_ref( - receiver, self._make_cleanup_receiver(receiver_id) - ) - else: - self.receivers[receiver_id] = receiver - - self._by_sender[sender_id].add(receiver_id) - self._by_receiver[receiver_id].add(sender_id) - - if sender is not ANY and sender_id not in self._weak_senders: - # store a cleanup for weakref-able senders - try: - self._weak_senders[sender_id] = make_ref( - sender, self._make_cleanup_sender(sender_id) - ) - except TypeError: - pass - - if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers: - try: - self.receiver_connected.send( - self, receiver=receiver, sender=sender, weak=weak - ) - except TypeError: - # TODO no explanation or test for this - self.disconnect(receiver, sender) - raise - - return receiver - - def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]: - """Connect the decorated function to be called when the signal is sent - by ``sender``. - - The decorated function will be called when :meth:`send` is called with - the given ``sender``, passing ``sender`` as a positional argument along - with any extra keyword arguments. - - :param sender: Any object or :data:`ANY`. ``receiver`` will only be - called when :meth:`send` is called with this sender. If ``ANY``, the - receiver will be called for any sender. A receiver may be connected - to multiple senders by calling :meth:`connect` multiple times. - :param weak: Track the receiver with a :mod:`weakref`. The receiver will - be automatically disconnected when it is garbage collected. When - connecting a receiver defined within a function, set to ``False``, - otherwise it will be disconnected when the function scope ends.= - - .. versionadded:: 1.1 - """ - - def decorator(fn: F) -> F: - self.connect(fn, sender, weak) - return fn - - return decorator - - @contextmanager - def connected_to( - self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY - ) -> c.Generator[None, None, None]: - """A context manager that temporarily connects ``receiver`` to the - signal while a ``with`` block executes. When the block exits, the - receiver is disconnected. Useful for tests. - - :param receiver: The callable to call when :meth:`send` is called with - the given ``sender``, passing ``sender`` as a positional argument - along with any extra keyword arguments. - :param sender: Any object or :data:`ANY`. ``receiver`` will only be - called when :meth:`send` is called with this sender. If ``ANY``, the - receiver will be called for any sender. - - .. versionadded:: 1.1 - """ - self.connect(receiver, sender=sender, weak=False) - - try: - yield None - finally: - self.disconnect(receiver) - - @contextmanager - def muted(self) -> c.Generator[None, None, None]: - """A context manager that temporarily disables the signal. No receivers - will be called if the signal is sent, until the ``with`` block exits. - Useful for tests. - """ - self.is_muted = True - - try: - yield None - finally: - self.is_muted = False - - def send( - self, - sender: t.Any | None = None, - /, - *, - _async_wrapper: c.Callable[ - [c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any] - ] - | None = None, - **kwargs: t.Any, - ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: - """Call all receivers that are connected to the given ``sender`` - or :data:`ANY`. Each receiver is called with ``sender`` as a positional - argument along with any extra keyword arguments. Return a list of - ``(receiver, return value)`` tuples. - - The order receivers are called is undefined, but can be influenced by - setting :attr:`set_class`. - - If a receiver raises an exception, that exception will propagate up. - This makes debugging straightforward, with an assumption that correctly - implemented receivers will not raise. - - :param sender: Call receivers connected to this sender, in addition to - those connected to :data:`ANY`. - :param _async_wrapper: Will be called on any receivers that are async - coroutines to turn them into sync callables. For example, could run - the receiver with an event loop. - :param kwargs: Extra keyword arguments to pass to each receiver. - - .. versionchanged:: 1.7 - Added the ``_async_wrapper`` argument. - """ - if self.is_muted: - return [] - - results = [] - - for receiver in self.receivers_for(sender): - if iscoroutinefunction(receiver): - if _async_wrapper is None: - raise RuntimeError("Cannot send to a coroutine function.") - - result = _async_wrapper(receiver)(sender, **kwargs) - else: - result = receiver(sender, **kwargs) - - results.append((receiver, result)) - - return results - - async def send_async( - self, - sender: t.Any | None = None, - /, - *, - _sync_wrapper: c.Callable[ - [c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]] - ] - | None = None, - **kwargs: t.Any, - ) -> list[tuple[c.Callable[..., t.Any], t.Any]]: - """Await all receivers that are connected to the given ``sender`` - or :data:`ANY`. Each receiver is called with ``sender`` as a positional - argument along with any extra keyword arguments. Return a list of - ``(receiver, return value)`` tuples. - - The order receivers are called is undefined, but can be influenced by - setting :attr:`set_class`. - - If a receiver raises an exception, that exception will propagate up. - This makes debugging straightforward, with an assumption that correctly - implemented receivers will not raise. - - :param sender: Call receivers connected to this sender, in addition to - those connected to :data:`ANY`. - :param _sync_wrapper: Will be called on any receivers that are sync - callables to turn them into async coroutines. For example, - could call the receiver in a thread. - :param kwargs: Extra keyword arguments to pass to each receiver. - - .. versionadded:: 1.7 - """ - if self.is_muted: - return [] - - results = [] - - for receiver in self.receivers_for(sender): - if not iscoroutinefunction(receiver): - if _sync_wrapper is None: - raise RuntimeError("Cannot send to a non-coroutine function.") - - result = await _sync_wrapper(receiver)(sender, **kwargs) - else: - result = await receiver(sender, **kwargs) - - results.append((receiver, result)) - - return results - - def has_receivers_for(self, sender: t.Any) -> bool: - """Check if there is at least one receiver that will be called with the - given ``sender``. A receiver connected to :data:`ANY` will always be - called, regardless of sender. Does not check if weakly referenced - receivers are still live. See :meth:`receivers_for` for a stronger - search. - - :param sender: Check for receivers connected to this sender, in addition - to those connected to :data:`ANY`. - """ - if not self.receivers: - return False - - if self._by_sender[ANY_ID]: - return True - - if sender is ANY: - return False - - return make_id(sender) in self._by_sender - - def receivers_for( - self, sender: t.Any - ) -> c.Generator[c.Callable[..., t.Any], None, None]: - """Yield each receiver to be called for ``sender``, in addition to those - to be called for :data:`ANY`. Weakly referenced receivers that are not - live will be disconnected and skipped. - - :param sender: Yield receivers connected to this sender, in addition - to those connected to :data:`ANY`. - """ - # TODO: test receivers_for(ANY) - if not self.receivers: - return - - sender_id = make_id(sender) - - if sender_id in self._by_sender: - ids = self._by_sender[ANY_ID] | self._by_sender[sender_id] - else: - ids = self._by_sender[ANY_ID].copy() - - for receiver_id in ids: - receiver = self.receivers.get(receiver_id) - - if receiver is None: - continue - - if isinstance(receiver, weakref.ref): - strong = receiver() - - if strong is None: - self._disconnect(receiver_id, ANY_ID) - continue - - yield strong - else: - yield receiver - - def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None: - """Disconnect ``receiver`` from being called when the signal is sent by - ``sender``. - - :param receiver: A connected receiver callable. - :param sender: Disconnect from only this sender. By default, disconnect - from all senders. - """ - sender_id: c.Hashable - - if sender is ANY: - sender_id = ANY_ID - else: - sender_id = make_id(sender) - - receiver_id = make_id(receiver) - self._disconnect(receiver_id, sender_id) - - if ( - "receiver_disconnected" in self.__dict__ - and self.receiver_disconnected.receivers - ): - self.receiver_disconnected.send(self, receiver=receiver, sender=sender) - - def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None: - if sender_id == ANY_ID: - if self._by_receiver.pop(receiver_id, None) is not None: - for bucket in self._by_sender.values(): - bucket.discard(receiver_id) - - self.receivers.pop(receiver_id, None) - else: - self._by_sender[sender_id].discard(receiver_id) - self._by_receiver[receiver_id].discard(sender_id) - - def _make_cleanup_receiver( - self, receiver_id: c.Hashable - ) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]: - """Create a callback function to disconnect a weakly referenced - receiver when it is garbage collected. - """ - - def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None: - # If the interpreter is shutting down, disconnecting can result in a - # weird ignored exception. Don't call it in that case. - if not sys.is_finalizing(): - self._disconnect(receiver_id, ANY_ID) - - return cleanup - - def _make_cleanup_sender( - self, sender_id: c.Hashable - ) -> c.Callable[[weakref.ref[t.Any]], None]: - """Create a callback function to disconnect all receivers for a weakly - referenced sender when it is garbage collected. - """ - assert sender_id != ANY_ID - - def cleanup(ref: weakref.ref[t.Any]) -> None: - self._weak_senders.pop(sender_id, None) - - for receiver_id in self._by_sender.pop(sender_id, ()): - self._by_receiver[receiver_id].discard(sender_id) - - return cleanup - - def _cleanup_bookkeeping(self) -> None: - """Prune unused sender/receiver bookkeeping. Not threadsafe. - - Connecting & disconnecting leaves behind a small amount of bookkeeping - data. Typical workloads using Blinker, for example in most web apps, - Flask, CLI scripts, etc., are not adversely affected by this - bookkeeping. - - With a long-running process performing dynamic signal routing with high - volume, e.g. connecting to function closures, senders are all unique - object instances. Doing all of this over and over may cause memory usage - to grow due to extraneous bookkeeping. (An empty ``set`` for each stale - sender/receiver pair.) - - This method will prune that bookkeeping away, with the caveat that such - pruning is not threadsafe. The risk is that cleanup of a fully - disconnected receiver/sender pair occurs while another thread is - connecting that same pair. If you are in the highly dynamic, unique - receiver/sender situation that has lead you to this method, that failure - mode is perhaps not a big deal for you. - """ - for mapping in (self._by_sender, self._by_receiver): - for ident, bucket in list(mapping.items()): - if not bucket: - mapping.pop(ident, None) - - def _clear_state(self) -> None: - """Disconnect all receivers and senders. Useful for tests.""" - self._weak_senders.clear() - self.receivers.clear() - self._by_sender.clear() - self._by_receiver.clear() - - -class NamedSignal(Signal): - """A named generic notification emitter. The name is not used by the signal - itself, but matches the key in the :class:`Namespace` that it belongs to. - - :param name: The name of the signal within the namespace. - :param doc: The docstring for the signal. - """ - - def __init__(self, name: str, doc: str | None = None) -> None: - super().__init__(doc) - - #: The name of this signal. - self.name: str = name - - def __repr__(self) -> str: - base = super().__repr__() - return f"{base[:-1]}; {self.name!r}>" # noqa: E702 - - -class Namespace(dict[str, NamedSignal]): - """A dict mapping names to signals.""" - - def signal(self, name: str, doc: str | None = None) -> NamedSignal: - """Return the :class:`NamedSignal` for the given ``name``, creating it - if required. Repeated calls with the same name return the same signal. - - :param name: The name of the signal. - :param doc: The docstring of the signal. - """ - if name not in self: - self[name] = NamedSignal(name, doc) - - return self[name] - - -class _PNamespaceSignal(t.Protocol): - def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ... - - -default_namespace: Namespace = Namespace() -"""A default :class:`Namespace` for creating named signals. :func:`signal` -creates a :class:`NamedSignal` in this namespace. -""" - -signal: _PNamespaceSignal = default_namespace.signal -"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given -``name``, creating it if required. Repeated calls with the same name return the -same signal. -""" diff --git a/venv/Lib/site-packages/blinker/py.typed b/venv/Lib/site-packages/blinker/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/bson/__init__.py b/venv/Lib/site-packages/bson/__init__.py deleted file mode 100644 index 790ac06..0000000 --- a/venv/Lib/site-packages/bson/__init__.py +++ /dev/null @@ -1,1484 +0,0 @@ -# Copyright 2009-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""BSON (Binary JSON) encoding and decoding. - -The mapping from Python types to BSON types is as follows: - -======================================= ============= =================== -Python Type BSON Type Supported Direction -======================================= ============= =================== -None null both -bool boolean both -int [#int]_ int32 / int64 py -> bson -:class:`bson.int64.Int64` int64 both -float number (real) both -str string both -list array both -dict object both -:class:`~bson.son.SON` object both -:py:class:`~collections.abc.Mapping` object py -> bson -:class:`~bson.raw_bson.RawBSONDocument` object both [#raw]_ -datetime.datetime [#dt]_ [#dt2]_ UTC datetime both -:class:`~bson.datetime_ms.DatetimeMS` UTC datetime both [#dt3]_ -:class:`~bson.regex.Regex` regex both -compiled re [#re]_ regex py -> bson -:class:`~bson.binary.Binary` binary both -:py:class:`uuid.UUID` [#uuid]_ binary both -:class:`~bson.objectid.ObjectId` oid both -:class:`~bson.dbref.DBRef` dbref both -:class:`~bson.dbref.DBRef` dbpointer bson -> py -None undefined bson -> py -:class:`~bson.code.Code` code both -str symbol bson -> py -bytes [#bytes]_ binary both -:class:`~bson.timestamp.Timestamp` timestamp both -:class:`~bson.decimal128.Decimal128` decimal128 both -:class:`~bson.min_key.MinKey` min key both -:class:`~bson.max_key.MaxKey` max key both -======================================= ============= =================== - -.. [#int] A Python int will be saved as a BSON int32 or BSON int64 depending - on its size. A BSON int32 will always decode to a Python int. A BSON - int64 will always decode to a :class:`~bson.int64.Int64`. -.. [#raw] Decoding a bson object to :class:`~bson.raw_bson.RawBSONDocument` can be - optionally configured via :attr:`~bson.codec_options.CodecOptions.document_class`. -.. [#dt] datetime.datetime instances are encoded with millisecond precision so - the microsecond field is truncated. -.. [#dt2] all datetime.datetime instances are encoded as UTC. By default, they - are decoded as *naive* but timezone aware datetimes are also supported. - See :doc:`/examples/datetimes` for examples. -.. [#dt3] To enable decoding a bson UTC datetime to a :class:`~bson.datetime_ms.DatetimeMS` - instance see :ref:`handling-out-of-range-datetimes`. -.. [#uuid] For :py:class:`uuid.UUID` encoding and decoding behavior see :doc:`/examples/uuid`. -.. [#re] :class:`~bson.regex.Regex` instances and regular expression - objects from ``re.compile()`` are both saved as BSON regular expressions. - BSON regular expressions are decoded as :class:`~bson.regex.Regex` - instances. -.. [#bytes] The bytes type is encoded as BSON binary with - subtype 0. It will be decoded back to bytes. -""" -from __future__ import annotations - -import datetime -import itertools -import os -import re -import struct -import sys -import uuid -from codecs import utf_8_decode as _utf_8_decode -from codecs import utf_8_encode as _utf_8_encode -from collections import abc as _abc -from typing import ( - IO, - TYPE_CHECKING, - Any, - BinaryIO, - Callable, - Generator, - Iterator, - Mapping, - MutableMapping, - NoReturn, - Optional, - Sequence, - Tuple, - Type, - TypeVar, - Union, - cast, - overload, -) - -from bson.binary import ( - ALL_UUID_SUBTYPES, - CSHARP_LEGACY, - JAVA_LEGACY, - OLD_UUID_SUBTYPE, - STANDARD, - UUID_SUBTYPE, - Binary, - UuidRepresentation, -) -from bson.code import Code -from bson.codec_options import ( - DEFAULT_CODEC_OPTIONS, - CodecOptions, - DatetimeConversion, - _raw_document_class, -) -from bson.datetime_ms import ( - EPOCH_AWARE, - EPOCH_NAIVE, - DatetimeMS, - _datetime_to_millis, - _millis_to_datetime, -) -from bson.dbref import DBRef -from bson.decimal128 import Decimal128 -from bson.errors import InvalidBSON, InvalidDocument, InvalidStringData -from bson.int64 import Int64 -from bson.max_key import MaxKey -from bson.min_key import MinKey -from bson.objectid import ObjectId -from bson.regex import Regex -from bson.son import RE_TYPE, SON -from bson.timestamp import Timestamp -from bson.tz_util import utc - -# Import some modules for type-checking only. -if TYPE_CHECKING: - from bson.raw_bson import RawBSONDocument - from bson.typings import _DocumentType, _ReadableBuffer - -try: - from bson import _cbson # type: ignore[attr-defined] - - _USE_C = True -except ImportError: - _USE_C = False - -__all__ = [ - "ALL_UUID_SUBTYPES", - "CSHARP_LEGACY", - "JAVA_LEGACY", - "OLD_UUID_SUBTYPE", - "STANDARD", - "UUID_SUBTYPE", - "Binary", - "UuidRepresentation", - "Code", - "DEFAULT_CODEC_OPTIONS", - "CodecOptions", - "DBRef", - "Decimal128", - "InvalidBSON", - "InvalidDocument", - "InvalidStringData", - "Int64", - "MaxKey", - "MinKey", - "ObjectId", - "Regex", - "RE_TYPE", - "SON", - "Timestamp", - "utc", - "EPOCH_AWARE", - "EPOCH_NAIVE", - "BSONNUM", - "BSONSTR", - "BSONOBJ", - "BSONARR", - "BSONBIN", - "BSONUND", - "BSONOID", - "BSONBOO", - "BSONDAT", - "BSONNUL", - "BSONRGX", - "BSONREF", - "BSONCOD", - "BSONSYM", - "BSONCWS", - "BSONINT", - "BSONTIM", - "BSONLON", - "BSONDEC", - "BSONMIN", - "BSONMAX", - "get_data_and_view", - "gen_list_name", - "encode", - "decode", - "decode_all", - "decode_iter", - "decode_file_iter", - "is_valid", - "BSON", - "has_c", - "DatetimeConversion", - "DatetimeMS", -] - -BSONNUM = b"\x01" # Floating point -BSONSTR = b"\x02" # UTF-8 string -BSONOBJ = b"\x03" # Embedded document -BSONARR = b"\x04" # Array -BSONBIN = b"\x05" # Binary -BSONUND = b"\x06" # Undefined -BSONOID = b"\x07" # ObjectId -BSONBOO = b"\x08" # Boolean -BSONDAT = b"\x09" # UTC Datetime -BSONNUL = b"\x0A" # Null -BSONRGX = b"\x0B" # Regex -BSONREF = b"\x0C" # DBRef -BSONCOD = b"\x0D" # Javascript code -BSONSYM = b"\x0E" # Symbol -BSONCWS = b"\x0F" # Javascript code with scope -BSONINT = b"\x10" # 32bit int -BSONTIM = b"\x11" # Timestamp -BSONLON = b"\x12" # 64bit int -BSONDEC = b"\x13" # Decimal128 -BSONMIN = b"\xFF" # Min key -BSONMAX = b"\x7F" # Max key - - -_UNPACK_FLOAT_FROM = struct.Struct(" Tuple[Any, memoryview]: - if isinstance(data, (bytes, bytearray)): - return data, memoryview(data) - view = memoryview(data) - return view.tobytes(), view - - -def _raise_unknown_type(element_type: int, element_name: str) -> NoReturn: - """Unknown type helper.""" - raise InvalidBSON( - "Detected unknown BSON type {!r} for fieldname '{}'. Are " - "you using the latest driver version?".format(chr(element_type).encode(), element_name) - ) - - -def _get_int( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[int, int]: - """Decode a BSON int32 to python int.""" - return _UNPACK_INT_FROM(data, position)[0], position + 4 - - -def _get_c_string(data: Any, view: Any, position: int, opts: CodecOptions[Any]) -> Tuple[str, int]: - """Decode a BSON 'C' string to python str.""" - end = data.index(b"\x00", position) - return _utf_8_decode(view[position:end], opts.unicode_decode_error_handler, True)[0], end + 1 - - -def _get_float( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[float, int]: - """Decode a BSON double to python float.""" - return _UNPACK_FLOAT_FROM(data, position)[0], position + 8 - - -def _get_string( - data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], dummy: Any -) -> Tuple[str, int]: - """Decode a BSON string to python str.""" - length = _UNPACK_INT_FROM(data, position)[0] - position += 4 - if length < 1 or obj_end - position < length: - raise InvalidBSON("invalid string length") - end = position + length - 1 - if data[end] != 0: - raise InvalidBSON("invalid end of string") - return _utf_8_decode(view[position:end], opts.unicode_decode_error_handler, True)[0], end + 1 - - -def _get_object_size(data: Any, position: int, obj_end: int) -> Tuple[int, int]: - """Validate and return a BSON document's size.""" - try: - obj_size = _UNPACK_INT_FROM(data, position)[0] - except struct.error as exc: - raise InvalidBSON(str(exc)) from None - end = position + obj_size - 1 - if end >= obj_end: - raise InvalidBSON("invalid object length") - if data[end] != 0: - raise InvalidBSON("bad eoo") - # If this is the top-level document, validate the total size too. - if position == 0 and obj_size != obj_end: - raise InvalidBSON("invalid object length") - return obj_size, end - - -def _get_object( - data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], dummy: Any -) -> Tuple[Any, int]: - """Decode a BSON subdocument to opts.document_class or bson.dbref.DBRef.""" - obj_size, end = _get_object_size(data, position, obj_end) - if _raw_document_class(opts.document_class): - return (opts.document_class(data[position : end + 1], opts), position + obj_size) - - obj = _elements_to_dict(data, view, position + 4, end, opts) - - position += obj_size - # If DBRef validation fails, return a normal doc. - if ( - isinstance(obj.get("$ref"), str) - and "$id" in obj - and isinstance(obj.get("$db"), (str, type(None))) - ): - return (DBRef(obj.pop("$ref"), obj.pop("$id", None), obj.pop("$db", None), obj), position) - return obj, position - - -def _get_array( - data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], element_name: str -) -> Tuple[Any, int]: - """Decode a BSON array to python list.""" - size = _UNPACK_INT_FROM(data, position)[0] - end = position + size - 1 - if data[end] != 0: - raise InvalidBSON("bad eoo") - - position += 4 - end -= 1 - result: list[Any] = [] - - # Avoid doing global and attribute lookups in the loop. - append = result.append - index = data.index - getter = _ELEMENT_GETTER - decoder_map = opts.type_registry._decoder_map - - while position < end: - element_type = data[position] - # Just skip the keys. - position = index(b"\x00", position) + 1 - try: - value, position = getter[element_type]( - data, view, position, obj_end, opts, element_name - ) - except KeyError: - _raise_unknown_type(element_type, element_name) - - if decoder_map: - custom_decoder = decoder_map.get(type(value)) - if custom_decoder is not None: - value = custom_decoder(value) - - append(value) - - if position != end + 1: - raise InvalidBSON("bad array length") - return result, position + 1 - - -def _get_binary( - data: Any, _view: Any, position: int, obj_end: int, opts: CodecOptions[Any], dummy1: Any -) -> Tuple[Union[Binary, uuid.UUID], int]: - """Decode a BSON binary to bson.binary.Binary or python UUID.""" - length, subtype = _UNPACK_LENGTH_SUBTYPE_FROM(data, position) - position += 5 - if subtype == 2: - length2 = _UNPACK_INT_FROM(data, position)[0] - position += 4 - if length2 != length - 4: - raise InvalidBSON("invalid binary (st 2) - lengths don't match!") - length = length2 - end = position + length - if length < 0 or end > obj_end: - raise InvalidBSON("bad binary object length") - - # Convert UUID subtypes to native UUIDs. - if subtype in ALL_UUID_SUBTYPES: - uuid_rep = opts.uuid_representation - binary_value = Binary(data[position:end], subtype) - if ( - (uuid_rep == UuidRepresentation.UNSPECIFIED) - or (subtype == UUID_SUBTYPE and uuid_rep != STANDARD) - or (subtype == OLD_UUID_SUBTYPE and uuid_rep == STANDARD) - ): - return binary_value, end - return binary_value.as_uuid(uuid_rep), end - - # Decode subtype 0 to 'bytes'. - if subtype == 0: - value = data[position:end] - else: - value = Binary(data[position:end], subtype) - - return value, end - - -def _get_oid( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[ObjectId, int]: - """Decode a BSON ObjectId to bson.objectid.ObjectId.""" - end = position + 12 - return ObjectId(data[position:end]), end - - -def _get_boolean( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[bool, int]: - """Decode a BSON true/false to python True/False.""" - end = position + 1 - boolean_byte = data[position:end] - if boolean_byte == b"\x00": - return False, end - elif boolean_byte == b"\x01": - return True, end - raise InvalidBSON("invalid boolean value: %r" % boolean_byte) - - -def _get_date( - data: Any, _view: Any, position: int, dummy0: int, opts: CodecOptions[Any], dummy1: Any -) -> Tuple[Union[datetime.datetime, DatetimeMS], int]: - """Decode a BSON datetime to python datetime.datetime.""" - return _millis_to_datetime(_UNPACK_LONG_FROM(data, position)[0], opts), position + 8 - - -def _get_code( - data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], element_name: str -) -> Tuple[Code, int]: - """Decode a BSON code to bson.code.Code.""" - code, position = _get_string(data, view, position, obj_end, opts, element_name) - return Code(code), position - - -def _get_code_w_scope( - data: Any, view: Any, position: int, _obj_end: int, opts: CodecOptions[Any], element_name: str -) -> Tuple[Code, int]: - """Decode a BSON code_w_scope to bson.code.Code.""" - code_end = position + _UNPACK_INT_FROM(data, position)[0] - code, position = _get_string(data, view, position + 4, code_end, opts, element_name) - scope, position = _get_object(data, view, position, code_end, opts, element_name) - if position != code_end: - raise InvalidBSON("scope outside of javascript code boundaries") - return Code(code, scope), position - - -def _get_regex( - data: Any, view: Any, position: int, dummy0: Any, opts: CodecOptions[Any], dummy1: Any -) -> Tuple[Regex[Any], int]: - """Decode a BSON regex to bson.regex.Regex or a python pattern object.""" - pattern, position = _get_c_string(data, view, position, opts) - bson_flags, position = _get_c_string(data, view, position, opts) - bson_re = Regex(pattern, bson_flags) - return bson_re, position - - -def _get_ref( - data: Any, view: Any, position: int, obj_end: int, opts: CodecOptions[Any], element_name: str -) -> Tuple[DBRef, int]: - """Decode (deprecated) BSON DBPointer to bson.dbref.DBRef.""" - collection, position = _get_string(data, view, position, obj_end, opts, element_name) - oid, position = _get_oid(data, view, position, obj_end, opts, element_name) - return DBRef(collection, oid), position - - -def _get_timestamp( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[Timestamp, int]: - """Decode a BSON timestamp to bson.timestamp.Timestamp.""" - inc, timestamp = _UNPACK_TIMESTAMP_FROM(data, position) - return Timestamp(timestamp, inc), position + 8 - - -def _get_int64( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[Int64, int]: - """Decode a BSON int64 to bson.int64.Int64.""" - return Int64(_UNPACK_LONG_FROM(data, position)[0]), position + 8 - - -def _get_decimal128( - data: Any, _view: Any, position: int, dummy0: Any, dummy1: Any, dummy2: Any -) -> Tuple[Decimal128, int]: - """Decode a BSON decimal128 to bson.decimal128.Decimal128.""" - end = position + 16 - return Decimal128.from_bid(data[position:end]), end - - -# Each decoder function's signature is: -# - data: bytes -# - view: memoryview that references `data` -# - position: int, beginning of object in 'data' to decode -# - obj_end: int, end of object to decode in 'data' if variable-length type -# - opts: a CodecOptions -_ELEMENT_GETTER: dict[int, Callable[..., Tuple[Any, int]]] = { - ord(BSONNUM): _get_float, - ord(BSONSTR): _get_string, - ord(BSONOBJ): _get_object, - ord(BSONARR): _get_array, - ord(BSONBIN): _get_binary, - ord(BSONUND): lambda u, v, w, x, y, z: (None, w), # noqa: ARG005 # Deprecated undefined - ord(BSONOID): _get_oid, - ord(BSONBOO): _get_boolean, - ord(BSONDAT): _get_date, - ord(BSONNUL): lambda u, v, w, x, y, z: (None, w), # noqa: ARG005 - ord(BSONRGX): _get_regex, - ord(BSONREF): _get_ref, # Deprecated DBPointer - ord(BSONCOD): _get_code, - ord(BSONSYM): _get_string, # Deprecated symbol - ord(BSONCWS): _get_code_w_scope, - ord(BSONINT): _get_int, - ord(BSONTIM): _get_timestamp, - ord(BSONLON): _get_int64, - ord(BSONDEC): _get_decimal128, - ord(BSONMIN): lambda u, v, w, x, y, z: (MinKey(), w), # noqa: ARG005 - ord(BSONMAX): lambda u, v, w, x, y, z: (MaxKey(), w), # noqa: ARG005 -} - - -if _USE_C: - - def _element_to_dict( - data: Any, - view: Any, # noqa: ARG001 - position: int, - obj_end: int, - opts: CodecOptions[Any], - raw_array: bool = False, - ) -> Tuple[str, Any, int]: - return cast( - "Tuple[str, Any, int]", - _cbson._element_to_dict(data, position, obj_end, opts, raw_array), - ) - -else: - - def _element_to_dict( - data: Any, - view: Any, - position: int, - obj_end: int, - opts: CodecOptions[Any], - raw_array: bool = False, - ) -> Tuple[str, Any, int]: - """Decode a single key, value pair.""" - element_type = data[position] - position += 1 - element_name, position = _get_c_string(data, view, position, opts) - if raw_array and element_type == ord(BSONARR): - _, end = _get_object_size(data, position, len(data)) - return element_name, view[position : end + 1], end + 1 - try: - value, position = _ELEMENT_GETTER[element_type]( - data, view, position, obj_end, opts, element_name - ) - except KeyError: - _raise_unknown_type(element_type, element_name) - - if opts.type_registry._decoder_map: - custom_decoder = opts.type_registry._decoder_map.get(type(value)) - if custom_decoder is not None: - value = custom_decoder(value) - - return element_name, value, position - - -_T = TypeVar("_T", bound=MutableMapping[str, Any]) - - -def _raw_to_dict( - data: Any, - position: int, - obj_end: int, - opts: CodecOptions[RawBSONDocument], - result: _T, - raw_array: bool = False, -) -> _T: - data, view = get_data_and_view(data) - return cast( - _T, _elements_to_dict(data, view, position, obj_end, opts, result, raw_array=raw_array) - ) - - -def _elements_to_dict( - data: Any, - view: Any, - position: int, - obj_end: int, - opts: CodecOptions[Any], - result: Any = None, - raw_array: bool = False, -) -> Any: - """Decode a BSON document into result.""" - if result is None: - result = opts.document_class() - end = obj_end - 1 - while position < end: - key, value, position = _element_to_dict( - data, view, position, obj_end, opts, raw_array=raw_array - ) - result[key] = value - if position != obj_end: - raise InvalidBSON("bad object or element length") - return result - - -def _bson_to_dict(data: Any, opts: CodecOptions[_DocumentType]) -> _DocumentType: - """Decode a BSON string to document_class.""" - data, view = get_data_and_view(data) - try: - if _raw_document_class(opts.document_class): - return opts.document_class(data, opts) # type:ignore[call-arg] - _, end = _get_object_size(data, 0, len(data)) - return cast("_DocumentType", _elements_to_dict(data, view, 4, end, opts)) - except InvalidBSON: - raise - except Exception: - # Change exception type to InvalidBSON but preserve traceback. - _, exc_value, exc_tb = sys.exc_info() - raise InvalidBSON(str(exc_value)).with_traceback(exc_tb) from None - - -if _USE_C: - _bson_to_dict = _cbson._bson_to_dict - - -_PACK_FLOAT = struct.Struct(" Generator[bytes, None, None]: - """Generate "keys" for encoded lists in the sequence - b"0\x00", b"1\x00", b"2\x00", ... - - The first 1000 keys are returned from a pre-built cache. All - subsequent keys are generated on the fly. - """ - yield from _LIST_NAMES - - counter = itertools.count(1000) - while True: - yield (str(next(counter)) + "\x00").encode("utf8") - - -def _make_c_string_check(string: Union[str, bytes]) -> bytes: - """Make a 'C' string, checking for embedded NUL characters.""" - if isinstance(string, bytes): - if b"\x00" in string: - raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character") - try: - _utf_8_decode(string, None, True) - return string + b"\x00" - except UnicodeError: - raise InvalidStringData( - "strings in documents must be valid UTF-8: %r" % string - ) from None - else: - if "\x00" in string: - raise InvalidDocument("BSON keys / regex patterns must not contain a NUL character") - return _utf_8_encode(string)[0] + b"\x00" - - -def _make_c_string(string: Union[str, bytes]) -> bytes: - """Make a 'C' string.""" - if isinstance(string, bytes): - try: - _utf_8_decode(string, None, True) - return string + b"\x00" - except UnicodeError: - raise InvalidStringData( - "strings in documents must be valid UTF-8: %r" % string - ) from None - else: - return _utf_8_encode(string)[0] + b"\x00" - - -def _make_name(string: str) -> bytes: - """Make a 'C' string suitable for a BSON key.""" - if "\x00" in string: - raise InvalidDocument("BSON keys must not contain a NUL character") - return _utf_8_encode(string)[0] + b"\x00" - - -def _encode_float(name: bytes, value: float, dummy0: Any, dummy1: Any) -> bytes: - """Encode a float.""" - return b"\x01" + name + _PACK_FLOAT(value) - - -def _encode_bytes(name: bytes, value: bytes, dummy0: Any, dummy1: Any) -> bytes: - """Encode a python bytes.""" - # Python3 special case. Store 'bytes' as BSON binary subtype 0. - return b"\x05" + name + _PACK_INT(len(value)) + b"\x00" + value - - -def _encode_mapping(name: bytes, value: Any, check_keys: bool, opts: CodecOptions[Any]) -> bytes: - """Encode a mapping type.""" - if _raw_document_class(value): - return b"\x03" + name + cast(bytes, value.raw) - data = b"".join([_element_to_bson(key, val, check_keys, opts) for key, val in value.items()]) - return b"\x03" + name + _PACK_INT(len(data) + 5) + data + b"\x00" - - -def _encode_dbref(name: bytes, value: DBRef, check_keys: bool, opts: CodecOptions[Any]) -> bytes: - """Encode bson.dbref.DBRef.""" - buf = bytearray(b"\x03" + name + b"\x00\x00\x00\x00") - begin = len(buf) - 4 - - buf += _name_value_to_bson(b"$ref\x00", value.collection, check_keys, opts) - buf += _name_value_to_bson(b"$id\x00", value.id, check_keys, opts) - if value.database is not None: - buf += _name_value_to_bson(b"$db\x00", value.database, check_keys, opts) - for key, val in value._DBRef__kwargs.items(): - buf += _element_to_bson(key, val, check_keys, opts) - - buf += b"\x00" - buf[begin : begin + 4] = _PACK_INT(len(buf) - begin) - return bytes(buf) - - -def _encode_list( - name: bytes, value: Sequence[Any], check_keys: bool, opts: CodecOptions[Any] -) -> bytes: - """Encode a list/tuple.""" - lname = gen_list_name() - data = b"".join([_name_value_to_bson(next(lname), item, check_keys, opts) for item in value]) - return b"\x04" + name + _PACK_INT(len(data) + 5) + data + b"\x00" - - -def _encode_text(name: bytes, value: str, dummy0: Any, dummy1: Any) -> bytes: - """Encode a python str.""" - bvalue = _utf_8_encode(value)[0] - return b"\x02" + name + _PACK_INT(len(bvalue) + 1) + bvalue + b"\x00" - - -def _encode_binary(name: bytes, value: Binary, dummy0: Any, dummy1: Any) -> bytes: - """Encode bson.binary.Binary.""" - subtype = value.subtype - if subtype == 2: - value = _PACK_INT(len(value)) + value # type: ignore - return b"\x05" + name + _PACK_LENGTH_SUBTYPE(len(value), subtype) + value - - -def _encode_uuid(name: bytes, value: uuid.UUID, dummy: Any, opts: CodecOptions[Any]) -> bytes: - """Encode uuid.UUID.""" - uuid_representation = opts.uuid_representation - binval = Binary.from_uuid(value, uuid_representation=uuid_representation) - return _encode_binary(name, binval, dummy, opts) - - -def _encode_objectid(name: bytes, value: ObjectId, dummy: Any, dummy1: Any) -> bytes: - """Encode bson.objectid.ObjectId.""" - return b"\x07" + name + value.binary - - -def _encode_bool(name: bytes, value: bool, dummy0: Any, dummy1: Any) -> bytes: - """Encode a python boolean (True/False).""" - return b"\x08" + name + (value and b"\x01" or b"\x00") - - -def _encode_datetime(name: bytes, value: datetime.datetime, dummy0: Any, dummy1: Any) -> bytes: - """Encode datetime.datetime.""" - millis = _datetime_to_millis(value) - return b"\x09" + name + _PACK_LONG(millis) - - -def _encode_datetime_ms(name: bytes, value: DatetimeMS, dummy0: Any, dummy1: Any) -> bytes: - """Encode datetime.datetime.""" - millis = int(value) - return b"\x09" + name + _PACK_LONG(millis) - - -def _encode_none(name: bytes, dummy0: Any, dummy1: Any, dummy2: Any) -> bytes: - """Encode python None.""" - return b"\x0A" + name - - -def _encode_regex(name: bytes, value: Regex[Any], dummy0: Any, dummy1: Any) -> bytes: - """Encode a python regex or bson.regex.Regex.""" - flags = value.flags - # Python 3 common case - if flags == re.UNICODE: - return b"\x0B" + name + _make_c_string_check(value.pattern) + b"u\x00" - elif flags == 0: - return b"\x0B" + name + _make_c_string_check(value.pattern) + b"\x00" - else: - sflags = b"" - if flags & re.IGNORECASE: - sflags += b"i" - if flags & re.LOCALE: - sflags += b"l" - if flags & re.MULTILINE: - sflags += b"m" - if flags & re.DOTALL: - sflags += b"s" - if flags & re.UNICODE: - sflags += b"u" - if flags & re.VERBOSE: - sflags += b"x" - sflags += b"\x00" - return b"\x0B" + name + _make_c_string_check(value.pattern) + sflags - - -def _encode_code(name: bytes, value: Code, dummy: Any, opts: CodecOptions[Any]) -> bytes: - """Encode bson.code.Code.""" - cstring = _make_c_string(value) - cstrlen = len(cstring) - if value.scope is None: - return b"\x0D" + name + _PACK_INT(cstrlen) + cstring - scope = _dict_to_bson(value.scope, False, opts, False) - full_length = _PACK_INT(8 + cstrlen + len(scope)) - return b"\x0F" + name + full_length + _PACK_INT(cstrlen) + cstring + scope - - -def _encode_int(name: bytes, value: int, dummy0: Any, dummy1: Any) -> bytes: - """Encode a python int.""" - if -2147483648 <= value <= 2147483647: - return b"\x10" + name + _PACK_INT(value) - else: - try: - return b"\x12" + name + _PACK_LONG(value) - except struct.error: - raise OverflowError("BSON can only handle up to 8-byte ints") from None - - -def _encode_timestamp(name: bytes, value: Any, dummy0: Any, dummy1: Any) -> bytes: - """Encode bson.timestamp.Timestamp.""" - return b"\x11" + name + _PACK_TIMESTAMP(value.inc, value.time) - - -def _encode_long(name: bytes, value: Any, dummy0: Any, dummy1: Any) -> bytes: - """Encode a bson.int64.Int64.""" - try: - return b"\x12" + name + _PACK_LONG(value) - except struct.error: - raise OverflowError("BSON can only handle up to 8-byte ints") from None - - -def _encode_decimal128(name: bytes, value: Decimal128, dummy0: Any, dummy1: Any) -> bytes: - """Encode bson.decimal128.Decimal128.""" - return b"\x13" + name + value.bid - - -def _encode_minkey(name: bytes, dummy0: Any, dummy1: Any, dummy2: Any) -> bytes: - """Encode bson.min_key.MinKey.""" - return b"\xFF" + name - - -def _encode_maxkey(name: bytes, dummy0: Any, dummy1: Any, dummy2: Any) -> bytes: - """Encode bson.max_key.MaxKey.""" - return b"\x7F" + name - - -# Each encoder function's signature is: -# - name: utf-8 bytes -# - value: a Python data type, e.g. a Python int for _encode_int -# - check_keys: bool, whether to check for invalid names -# - opts: a CodecOptions -_ENCODERS = { - bool: _encode_bool, - bytes: _encode_bytes, - datetime.datetime: _encode_datetime, - DatetimeMS: _encode_datetime_ms, - dict: _encode_mapping, - float: _encode_float, - int: _encode_int, - list: _encode_list, - str: _encode_text, - tuple: _encode_list, - type(None): _encode_none, - uuid.UUID: _encode_uuid, - Binary: _encode_binary, - Int64: _encode_long, - Code: _encode_code, - DBRef: _encode_dbref, - MaxKey: _encode_maxkey, - MinKey: _encode_minkey, - ObjectId: _encode_objectid, - Regex: _encode_regex, - RE_TYPE: _encode_regex, - SON: _encode_mapping, - Timestamp: _encode_timestamp, - Decimal128: _encode_decimal128, - # Special case. This will never be looked up directly. - _abc.Mapping: _encode_mapping, -} - -# Map each _type_marker to its encoder for faster lookup. -_MARKERS = {} -for _typ in _ENCODERS: - if hasattr(_typ, "_type_marker"): - _MARKERS[_typ._type_marker] = _ENCODERS[_typ] - - -_BUILT_IN_TYPES = tuple(t for t in _ENCODERS) - - -def _name_value_to_bson( - name: bytes, - value: Any, - check_keys: bool, - opts: CodecOptions[Any], - in_custom_call: bool = False, - in_fallback_call: bool = False, -) -> bytes: - """Encode a single name, value pair.""" - - was_integer_overflow = False - - # First see if the type is already cached. KeyError will only ever - # happen once per subtype. - try: - return _ENCODERS[type(value)](name, value, check_keys, opts) # type: ignore - except KeyError: - pass - except OverflowError: - if not isinstance(value, int): - raise - - # Give the fallback_encoder a chance - was_integer_overflow = True - - # Second, fall back to trying _type_marker. This has to be done - # before the loop below since users could subclass one of our - # custom types that subclasses a python built-in (e.g. Binary) - marker = getattr(value, "_type_marker", None) - if isinstance(marker, int) and marker in _MARKERS: - func = _MARKERS[marker] - # Cache this type for faster subsequent lookup. - _ENCODERS[type(value)] = func - return func(name, value, check_keys, opts) # type: ignore - - # Third, check if a type encoder is registered for this type. - # Note that subtypes of registered custom types are not auto-encoded. - if not in_custom_call and opts.type_registry._encoder_map: - custom_encoder = opts.type_registry._encoder_map.get(type(value)) - if custom_encoder is not None: - return _name_value_to_bson( - name, custom_encoder(value), check_keys, opts, in_custom_call=True - ) - - # Fourth, test each base type. This will only happen once for - # a subtype of a supported base type. Unlike in the C-extensions, this - # is done after trying the custom type encoder because checking for each - # subtype is expensive. - for base in _BUILT_IN_TYPES: - if not was_integer_overflow and isinstance(value, base): - func = _ENCODERS[base] - # Cache this type for faster subsequent lookup. - _ENCODERS[type(value)] = func - return func(name, value, check_keys, opts) # type: ignore - - # As a last resort, try using the fallback encoder, if the user has - # provided one. - fallback_encoder = opts.type_registry._fallback_encoder - if not in_fallback_call and fallback_encoder is not None: - return _name_value_to_bson( - name, fallback_encoder(value), check_keys, opts, in_fallback_call=True - ) - - if was_integer_overflow: - raise OverflowError("BSON can only handle up to 8-byte ints") - raise InvalidDocument(f"cannot encode object: {value!r}, of type: {type(value)!r}") - - -def _element_to_bson(key: Any, value: Any, check_keys: bool, opts: CodecOptions[Any]) -> bytes: - """Encode a single key, value pair.""" - if not isinstance(key, str): - raise InvalidDocument(f"documents must have only string keys, key was {key!r}") - if check_keys: - if key.startswith("$"): - raise InvalidDocument(f"key {key!r} must not start with '$'") - if "." in key: - raise InvalidDocument(f"key {key!r} must not contain '.'") - - name = _make_name(key) - return _name_value_to_bson(name, value, check_keys, opts) - - -def _dict_to_bson( - doc: Any, check_keys: bool, opts: CodecOptions[Any], top_level: bool = True -) -> bytes: - """Encode a document to BSON.""" - if _raw_document_class(doc): - return cast(bytes, doc.raw) - try: - elements = [] - if top_level and "_id" in doc: - elements.append(_name_value_to_bson(b"_id\x00", doc["_id"], check_keys, opts)) - for key, value in doc.items(): - if not top_level or key != "_id": - try: - elements.append(_element_to_bson(key, value, check_keys, opts)) - except InvalidDocument as err: - raise InvalidDocument(f"Invalid document {doc} | {err}") from err - except AttributeError: - raise TypeError(f"encoder expected a mapping type but got: {doc!r}") from None - - encoded = b"".join(elements) - return _PACK_INT(len(encoded) + 5) + encoded + b"\x00" - - -if _USE_C: - _dict_to_bson = _cbson._dict_to_bson - - -_CODEC_OPTIONS_TYPE_ERROR = TypeError("codec_options must be an instance of CodecOptions") - - -def encode( - document: Mapping[str, Any], - check_keys: bool = False, - codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS, -) -> bytes: - """Encode a document to BSON. - - A document can be any mapping type (like :class:`dict`). - - Raises :class:`TypeError` if `document` is not a mapping type, - or contains keys that are not instances of :class:`str`. Raises - :class:`~bson.errors.InvalidDocument` if `document` cannot be - converted to :class:`BSON`. - - :param document: mapping type representing a document - :param check_keys: check if keys start with '$' or - contain '.', raising :class:`~bson.errors.InvalidDocument` in - either case - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionadded:: 3.9 - """ - if not isinstance(codec_options, CodecOptions): - raise _CODEC_OPTIONS_TYPE_ERROR - - return _dict_to_bson(document, check_keys, codec_options) - - -@overload -def decode(data: _ReadableBuffer, codec_options: None = None) -> dict[str, Any]: - ... - - -@overload -def decode(data: _ReadableBuffer, codec_options: CodecOptions[_DocumentType]) -> _DocumentType: - ... - - -def decode( - data: _ReadableBuffer, codec_options: Optional[CodecOptions[_DocumentType]] = None -) -> Union[dict[str, Any], _DocumentType]: - """Decode BSON to a document. - - By default, returns a BSON document represented as a Python - :class:`dict`. To use a different :class:`MutableMapping` class, - configure a :class:`~bson.codec_options.CodecOptions`:: - - >>> import collections # From Python standard library. - >>> import bson - >>> from bson.codec_options import CodecOptions - >>> data = bson.encode({'a': 1}) - >>> decoded_doc = bson.decode(data) - - >>> options = CodecOptions(document_class=collections.OrderedDict) - >>> decoded_doc = bson.decode(data, codec_options=options) - >>> type(decoded_doc) - - - :param data: the BSON to decode. Any bytes-like object that implements - the buffer protocol. - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionadded:: 3.9 - """ - opts: CodecOptions[Any] = codec_options or DEFAULT_CODEC_OPTIONS - if not isinstance(opts, CodecOptions): - raise _CODEC_OPTIONS_TYPE_ERROR - - return cast("Union[dict[str, Any], _DocumentType]", _bson_to_dict(data, opts)) - - -def _decode_all(data: _ReadableBuffer, opts: CodecOptions[_DocumentType]) -> list[_DocumentType]: - """Decode a BSON data to multiple documents.""" - data, view = get_data_and_view(data) - data_len = len(data) - docs: list[_DocumentType] = [] - position = 0 - end = data_len - 1 - use_raw = _raw_document_class(opts.document_class) - try: - while position < end: - obj_size = _UNPACK_INT_FROM(data, position)[0] - if data_len - position < obj_size: - raise InvalidBSON("invalid object size") - obj_end = position + obj_size - 1 - if data[obj_end] != 0: - raise InvalidBSON("bad eoo") - if use_raw: - docs.append(opts.document_class(data[position : obj_end + 1], opts)) # type: ignore - else: - docs.append(_elements_to_dict(data, view, position + 4, obj_end, opts)) - position += obj_size - return docs - except InvalidBSON: - raise - except Exception: - # Change exception type to InvalidBSON but preserve traceback. - _, exc_value, exc_tb = sys.exc_info() - raise InvalidBSON(str(exc_value)).with_traceback(exc_tb) from None - - -if _USE_C: - _decode_all = _cbson._decode_all - - -@overload -def decode_all(data: _ReadableBuffer, codec_options: None = None) -> list[dict[str, Any]]: - ... - - -@overload -def decode_all( - data: _ReadableBuffer, codec_options: CodecOptions[_DocumentType] -) -> list[_DocumentType]: - ... - - -def decode_all( - data: _ReadableBuffer, codec_options: Optional[CodecOptions[_DocumentType]] = None -) -> Union[list[dict[str, Any]], list[_DocumentType]]: - """Decode BSON data to multiple documents. - - `data` must be a bytes-like object implementing the buffer protocol that - provides concatenated, valid, BSON-encoded documents. - - :param data: BSON data - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionchanged:: 3.9 - Supports bytes-like objects that implement the buffer protocol. - - .. versionchanged:: 3.0 - Removed `compile_re` option: PyMongo now always represents BSON regular - expressions as :class:`~bson.regex.Regex` objects. Use - :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a - BSON regular expression to a Python regular expression object. - - Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with - `codec_options`. - """ - if codec_options is None: - return _decode_all(data, DEFAULT_CODEC_OPTIONS) - - if not isinstance(codec_options, CodecOptions): - raise _CODEC_OPTIONS_TYPE_ERROR - - return _decode_all(data, codec_options) - - -def _decode_selective( - rawdoc: Any, fields: Any, codec_options: CodecOptions[_DocumentType] -) -> _DocumentType: - if _raw_document_class(codec_options.document_class): - # If document_class is RawBSONDocument, use vanilla dictionary for - # decoding command response. - doc: _DocumentType = {} # type:ignore[assignment] - else: - # Else, use the specified document_class. - doc = codec_options.document_class() - for key, value in rawdoc.items(): - if key in fields: - if fields[key] == 1: - doc[key] = _bson_to_dict(rawdoc.raw, codec_options)[key] # type:ignore[index] - else: - doc[key] = _decode_selective( # type:ignore[index] - value, fields[key], codec_options - ) - else: - doc[key] = value # type:ignore[index] - return doc - - -def _array_of_documents_to_buffer(data: Union[memoryview, bytes]) -> bytes: - # Extract the raw bytes of each document. - position = 0 - view = memoryview(data) - _, end = _get_object_size(view, position, len(view)) - position += 4 - buffers: list[memoryview] = [] - append = buffers.append - while position < end - 1: - # Just skip the keys. - while view[position] != 0: - position += 1 - position += 1 - obj_size, _ = _get_object_size(view, position, end) - append(view[position : position + obj_size]) - position += obj_size - if position != end: - raise InvalidBSON("bad object or element length") - return b"".join(buffers) - - -if _USE_C: - _array_of_documents_to_buffer = _cbson._array_of_documents_to_buffer - - -def _convert_raw_document_lists_to_streams(document: Any) -> None: - """Convert raw array of documents to a stream of BSON documents.""" - cursor = document.get("cursor") - if not cursor: - return - for key in ("firstBatch", "nextBatch"): - batch = cursor.get(key) - if not batch: - continue - data = _array_of_documents_to_buffer(batch) - if data: - cursor[key] = [data] - else: - cursor[key] = [] - - -def _decode_all_selective( - data: Any, codec_options: CodecOptions[_DocumentType], fields: Any -) -> list[_DocumentType]: - """Decode BSON data to a single document while using user-provided - custom decoding logic. - - `data` must be a string representing a valid, BSON-encoded document. - - :param data: BSON data - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions` with user-specified type - decoders. If no decoders are found, this method is the same as - ``decode_all``. - :param fields: Map of document namespaces where data that needs - to be custom decoded lives or None. For example, to custom decode a - list of objects in 'field1.subfield1', the specified value should be - ``{'field1': {'subfield1': 1}}``. If ``fields`` is an empty map or - None, this method is the same as ``decode_all``. - - :return: Single-member list containing the decoded document. - - .. versionadded:: 3.8 - """ - if not codec_options.type_registry._decoder_map: - return decode_all(data, codec_options) - - if not fields: - return decode_all(data, codec_options.with_options(type_registry=None)) - - # Decode documents for internal use. - from bson.raw_bson import RawBSONDocument - - internal_codec_options: CodecOptions[RawBSONDocument] = codec_options.with_options( - document_class=RawBSONDocument, type_registry=None - ) - _doc = _bson_to_dict(data, internal_codec_options) - return [ - _decode_selective( - _doc, - fields, - codec_options, - ) - ] - - -@overload -def decode_iter(data: bytes, codec_options: None = None) -> Iterator[dict[str, Any]]: - ... - - -@overload -def decode_iter(data: bytes, codec_options: CodecOptions[_DocumentType]) -> Iterator[_DocumentType]: - ... - - -def decode_iter( - data: bytes, codec_options: Optional[CodecOptions[_DocumentType]] = None -) -> Union[Iterator[dict[str, Any]], Iterator[_DocumentType]]: - """Decode BSON data to multiple documents as a generator. - - Works similarly to the decode_all function, but yields one document at a - time. - - `data` must be a string of concatenated, valid, BSON-encoded - documents. - - :param data: BSON data - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionchanged:: 3.0 - Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with - `codec_options`. - - .. versionadded:: 2.8 - """ - opts = codec_options or DEFAULT_CODEC_OPTIONS - if not isinstance(opts, CodecOptions): - raise _CODEC_OPTIONS_TYPE_ERROR - - position = 0 - end = len(data) - 1 - while position < end: - obj_size = _UNPACK_INT_FROM(data, position)[0] - elements = data[position : position + obj_size] - position += obj_size - - yield _bson_to_dict(elements, opts) # type:ignore[misc] - - -@overload -def decode_file_iter( - file_obj: Union[BinaryIO, IO[bytes]], codec_options: None = None -) -> Iterator[dict[str, Any]]: - ... - - -@overload -def decode_file_iter( - file_obj: Union[BinaryIO, IO[bytes]], codec_options: CodecOptions[_DocumentType] -) -> Iterator[_DocumentType]: - ... - - -def decode_file_iter( - file_obj: Union[BinaryIO, IO[bytes]], - codec_options: Optional[CodecOptions[_DocumentType]] = None, -) -> Union[Iterator[dict[str, Any]], Iterator[_DocumentType]]: - """Decode bson data from a file to multiple documents as a generator. - - Works similarly to the decode_all function, but reads from the file object - in chunks and parses bson in chunks, yielding one document at a time. - - :param file_obj: A file object containing BSON data. - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionchanged:: 3.0 - Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with - `codec_options`. - - .. versionadded:: 2.8 - """ - opts = codec_options or DEFAULT_CODEC_OPTIONS - while True: - # Read size of next object. - size_data: Any = file_obj.read(4) - if not size_data: - break # Finished with file normally. - elif len(size_data) != 4: - raise InvalidBSON("cut off in middle of objsize") - obj_size = _UNPACK_INT_FROM(size_data, 0)[0] - 4 - elements = size_data + file_obj.read(max(0, obj_size)) - yield _bson_to_dict(elements, opts) # type:ignore[arg-type, misc] - - -def is_valid(bson: bytes) -> bool: - """Check that the given string represents valid :class:`BSON` data. - - Raises :class:`TypeError` if `bson` is not an instance of - :class:`bytes`. Returns ``True`` - if `bson` is valid :class:`BSON`, ``False`` otherwise. - - :param bson: the data to be validated - """ - if not isinstance(bson, bytes): - raise TypeError(f"BSON data must be an instance of a subclass of bytes, not {type(bson)}") - - try: - _bson_to_dict(bson, DEFAULT_CODEC_OPTIONS) - return True - except Exception: - return False - - -class BSON(bytes): - """BSON (Binary JSON) data. - - .. warning:: Using this class to encode and decode BSON adds a performance - cost. For better performance use the module level functions - :func:`encode` and :func:`decode` instead. - """ - - @classmethod - def encode( - cls: Type[BSON], - document: Mapping[str, Any], - check_keys: bool = False, - codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS, - ) -> BSON: - """Encode a document to a new :class:`BSON` instance. - - A document can be any mapping type (like :class:`dict`). - - Raises :class:`TypeError` if `document` is not a mapping type, - or contains keys that are not instances of - :class:`str'. Raises :class:`~bson.errors.InvalidDocument` - if `document` cannot be converted to :class:`BSON`. - - :param document: mapping type representing a document - :param check_keys: check if keys start with '$' or - contain '.', raising :class:`~bson.errors.InvalidDocument` in - either case - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionchanged:: 3.0 - Replaced `uuid_subtype` option with `codec_options`. - """ - return cls(encode(document, check_keys, codec_options)) - - def decode( # type:ignore[override] - self, codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS - ) -> dict[str, Any]: - """Decode this BSON data. - - By default, returns a BSON document represented as a Python - :class:`dict`. To use a different :class:`MutableMapping` class, - configure a :class:`~bson.codec_options.CodecOptions`:: - - >>> import collections # From Python standard library. - >>> import bson - >>> from bson.codec_options import CodecOptions - >>> data = bson.BSON.encode({'a': 1}) - >>> decoded_doc = bson.BSON(data).decode() - - >>> options = CodecOptions(document_class=collections.OrderedDict) - >>> decoded_doc = bson.BSON(data).decode(codec_options=options) - >>> type(decoded_doc) - - - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions`. - - .. versionchanged:: 3.0 - Removed `compile_re` option: PyMongo now always represents BSON - regular expressions as :class:`~bson.regex.Regex` objects. Use - :meth:`~bson.regex.Regex.try_compile` to attempt to convert from a - BSON regular expression to a Python regular expression object. - - Replaced `as_class`, `tz_aware`, and `uuid_subtype` options with - `codec_options`. - """ - return decode(self, codec_options) - - -def has_c() -> bool: - """Is the C extension installed?""" - return _USE_C - - -def _after_fork() -> None: - """Releases the ObjectID lock child.""" - if ObjectId._inc_lock.locked(): - ObjectId._inc_lock.release() - - -if hasattr(os, "register_at_fork"): - # This will run in the same thread as the fork was called. - # If we fork in a critical region on the same thread, it should break. - # This is fine since we would never call fork directly from a critical region. - os.register_at_fork(after_in_child=_after_fork) diff --git a/venv/Lib/site-packages/bson/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index cbc0f6a6f901db0e41172c19b437af4b3d9dc049..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42401 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 diff --git a/venv/Lib/site-packages/bson/__pycache__/_helpers.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/_helpers.cpython-310.pyc deleted file mode 100644 index 05167db0a60007f9dfe4ad62ef2f17e5d9efc549..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1171 zcmZ8gO>f*b5G5&USF74tS@4F}OV?zGH&G##U&0|8S zeF{L5IgwPdnl^0CDB`G&8b0SuJda_2OHO3^7oU&hk8&!v0FC8sxg&1?O61KWGTZ&r z94TjA;Z#<%GFx767OS>&m2Pde&?eKzr>b-|dt14aObA6?LuOR_!t^b<-8D zI>3jCQ)zb@~|@&8YvOXj=`bG0lwm=t+Cw$1jVngVUZ{ zRWA(k^>L`rkBo9F(|UfWTU9a)a}o;ls+FAko=x%^zU=lP53IJXe@*RCkfilwsovDNKEaiZ!DZvNI?_$>hm1F4~v zyAa!A(rr4W{Hxgl=y_W-%1722KkAHHRDb-3GxEpo1kU#X^yC9fz(;B}CF|)fS<@a^ z?*dmD{flS(&@&-C6&@u>p$g+H>N;a)8^V|yXprq-rhxp0Xo_}OD}goL0guHoO=&`t zh<{C}K?YxTuC)6dgnW>Jd0kTQUoUJeDitc;2hfvKa!S{?><9iyOd5I5Otv|QC{AH}j8VEA+++Gc5##?#~*$c`A< diff --git a/venv/Lib/site-packages/bson/__pycache__/binary.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/binary.cpython-310.pyc deleted file mode 100644 index 99cdb47574cfc9a48b77de9b8534a13bfed8be80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12903 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 Ezv&KW`2YX_ diff --git a/venv/Lib/site-packages/bson/__pycache__/datetime_ms.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/datetime_ms.cpython-310.pyc deleted file mode 100644 index 085df7d86ccb7b61c139107e4370981a5f9fb26c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6261 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 WDGDe$3EImzjF@NHirHbS)_(!?RGwA< diff --git a/venv/Lib/site-packages/bson/__pycache__/decimal128.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/decimal128.cpython-310.pyc deleted file mode 100644 index 672b2187ede9d4aba2ef39c0ddf0dfa19eeb7674..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9784 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 K3fT^go%wIG1)$jg diff --git a/venv/Lib/site-packages/bson/__pycache__/errors.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/errors.cpython-310.pyc deleted file mode 100644 index b8c27ba820c9f9fa0bc088d21502ec304b96c5d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1197 zcmb7@OK%!65XZgj0?RX0t=dCX)l#HN973*DpHTv>kRl?L=7LsQnYDp!7Mt3J7Ow4= z$p`3{;nG7-J?GX_XBJ9wAVKwNz4M>-<2PfEs#J;u+QXkuMn614exbP8z(f3*z7y^V_nX`EKxcUlbWV7nv!L_b2koai2fDzEpo^)_gD&wh z=yIxkUg?s0b@8nAH4+mWD`}`^u@Rj1=hTh_J?@@$=!8WVY$zJPk+beBOH4{-Svo#K z-_7QLI0F8w8W@7~9Ec&qou11xu$Q|m;F2w^m0s*0Gb3n}Fk|RIY08phwV~MHG&+~w z(hoz)#v%-t#V{NzK26XrhvDZbOV)q#VaQb!hL=QRe$(#H$;pf0+z4%g$xw|&&=lsv zs!4F#Y|U5_%!Hf;r*S_pu@wjFC{55eN*)R%G>yqzx!ySE1GS`8RY*kJK?JD!k{;)rL`p)^v`vRER#RPx~bdYz+w{)Ogf&>l_bGZ|E z+zov01vTE`b>6u2fkv0N_&RtE-UdP&W$nGp_jcI}hmcPq)4~W@p;0xZ`CL?Vf!y9M z&6kW_+HE~czV@@?B{QsmT*bAxK=c?=y{ za?X|p2>!3l-tNsrgN$jG(gjNjF|d;Zb)n;^3L&(<709Apk?T#+yR2)G7g}oELIg72 z8T$Af;cD>1iOGmuIYV6oA9m>*kxcEy9={Kd2IDVAXfw`cDiz~nVa{@ujZco>0;};t z$i?_1o{UYLi{}}O&e%+t@x&V%41;!vUu&2$eI~SC z$F>`Ip!O>Va@M$;NAMV=+61-yHQ#NyUC(BQy@q}O2_!HrVAViCqe5jJAYwVQ1C$=@ cz}ByHw_sM5=Ie_48s;d;%~>-}oY?XS$zp%M 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 BeYF4p diff --git a/venv/Lib/site-packages/bson/__pycache__/objectid.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/objectid.cpython-310.pyc deleted file mode 100644 index d7bfb809e4894903298c5833e8240d89f2c5e7d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9072 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 diff --git a/venv/Lib/site-packages/bson/__pycache__/raw_bson.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/raw_bson.cpython-310.pyc deleted file mode 100644 index 5eeb4e71317291eb0f3e83d1f222ae5f8093cc12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7241 zcmb_h&2!tv6$e0&q9BTvEq{MyqqLEj$aG>mos_jbQ6xE|i7jPhyP4ARfFO5eLk0n6 z0a+0v_fYxLLwe|;hh{R9OlLadOAnptt$#=dmmYe`IX7M0-&+tAKcu)#3k`wA;_chF z@4bER_g2C9xTWDb`OgcFmo8}9zv!j+%Hib$P1D1_qj6v3T2%{Ft@Tyvy4(#%)$>YM3}Hm$1F9IKA0_pDcFj#tN<#cEN#=kR`{I-zT$Bm5jc z&nNiN=h^Dfk2HRaPd?Z9q!x(-)VjteP^y~{Onz=bipyQnszS;ypXL2l1b5$A{2h)`j41&w%CVvSC$zM z8k zv?YYkxVyeCB!pnxiJZCI`-IQHrKfCGp z+cTgkLv3_D_+rX-`Ba6yJIkgVdOn+FY2Ov})d%{nqOUQ~cMW}t$FqkW*6AYl#od>2 zzpo=JIUtnATv)p!?YispnNp=k(3W)lXl8v1hUq#WUFUNZRw&?S}qy^7rd8V z88_)CL($k$|KP6X_T}u;VBiZHNh`#Bxc5s`pGNOAx(}Fq8mgXFs-AY}`RvDxhEb;L zKYBFGH{JNrqhaW2wSs4sbqiM83OG3lCBCU zb=P;~wpI6nddQ*xL_)H#C17KUO3u^33CMkH;L}4p1 z&2ct)jFWpe>_ABp?p^5R^kB6=EfR)RnShBSy2o~X-usbuTI1o0fIaHE_&?3vpTNU z%b-sw6)XvXC5#-uAuzWhRI{n*T&ew9MTEXF$Z@pg5xUXG7n(eS$KK+6W$ivP zZ@AWa6g0)!f(V~LrE9kr7N0ua+Ed{_UAyhp*FrZEms(EaiStN=YqX}zWNx*%)^mjUFGl&>yvUC{H+S`_#b^0Ze(bqf9Yg;m1y`uQAjWx_pX8?$RgqsNxC5#q z{2hLgzlPQXf0w_`r_egeukfGpH_N$xW7JMo$i_)> z^TLN+UrF4k8%3N(Lm);W?vT4eY06rMd7T?|ymiI*w&5B;C{E(p4DOilLNr38X(G$bT{!`Z z#jn`|ddshj`4U&xQ21`;t{+I(Cqc zblLq^zA}iiJATq-*5fbTzQe*1L0V5JT(6w6R_o-nT8%k%qyeXaaE7ej<)q>oQxKZ= z2nAE_NRFgmm&n{K1f)h_c6^G0zy$OKaKM3v9eydmPU*5j7)7$F)e@{uHcBo+?P>yw zSSjdM$$DQ5q9i)(1M+JN_fVD;0LN{C@X4m>rT=nICL1WI-48lR_In2jri% z8aYvdA$rm@V=dHUa83kcVEd%rg_9D_^n}74-5l{s`QGc1Z;231D&(v21oA{zkXefK zJ*);n#;dK+9lYGWKCm5VM*`I-q z7|F9}#d*qxZe-h^;w_{xxi@lpK9kc6x`97aH(#1BbLMfQeR@DS<#cF+7M@AHDrHc{?*G0Y2nxn#=ML92kQQhVY>2Z&j<_QBKdNm??nWgLUMw9gJoyieL7 zHK!M~Gx&AYPW2Fgig8zyW%R@5gs5K_hdQnL{zuRx$}-y*hNkYt>aj_>i!;c}k|rLK zX2=P4^fPb*B@G<$ZHz&sp&apDvS40v z!=W9Niu67CB`IhFNG=u0P%Dy3u!EdQZECQ$?LT3(yoTF>n^%#<8Jr3oI=}oGaUiom z0~8$&pLE2wQHI&}pNUG%d1_bziXzSiNHS6$1Lcr0x~@Sx9Vl5Zdi=4@MhX4^0DDRF5;KT~g?99{sC z4QY#ZfpX`IXh2d}>nnxaH;k_g;B#y_JTqUb0)Kf=pJ`9bq6+UhdAPBsmr7EmkgV7ey^wf^MqQNg=i8UG~dAYuJpr|PCE<&z)dV@Tn{(vVI^ zOg*m~nZirsN^ zL;dz2+SlFMmb@wn`ShQkFEfxgvwTmULbtq3w|D5)zd@Da|Av0$;6=0j24&fy^_A1g zUY*e_%LR-m<&@*dMdEskZXeN&Y?7FBf2Mt_-Nx6y;ujK<%EM}gF`-N9MLzfm9&!q| z_8YyJ@WFv1J&aGOgUh+q)wy3K$Cn)hzg*I9mGTE_k&drabWHZbahmsxlAHX0eG_Mn z6c}i;$2mAR@RQ1HlAJ`6rX__WIf7f&Bq*Oi!clrZrcSi_qL11qa*T!)aEnJeP&84H z+QNi0l>({-I*mzBOqCww5`DZww*!OhBjbeY5cL^!UUh N(=znpOEZ(){|!Cfm=XX0 diff --git a/venv/Lib/site-packages/bson/__pycache__/regex.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/regex.cpython-310.pyc deleted file mode 100644 index 6fe15772ed9b46ecb90d3d29f192c8597a0f1acb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4580 zcmeHL-ESMm5x>1Veu$(f*-l)$jhu}WTVkqEZQT|rk+_j1!4RNOh9n2*S?=+~U5Y2& z2fe%0SDBZ{|3y)teH75Y=w9;Br~C_g>dYRGq-441LmzvFmV2|ab2B?LznOJBJzX;3 zx%=Z>_swm?_!quRJ~?>##xRKd0Vd3F3`Uq4kkE8Yf^#dd91DK!zz%axF3damu;3KJ zqEif~oT;$nlrD2ElN5>7kQ`aK_1!x?7==CiEKDsOFPmQS&1ev98ex12lA4OV3{ zZw)rX^Zd?z185&GYul*ZI(xDc$AP4sSWv-xf=eDLKia3?#?gMf`V5Hs{lF8HpWveO z<4D$jLX&DFDSJ^AD^DS@S<5HZa&(#$p7V$cznv6bcuH{*CHBr~k0%8jzw<!b&s`bBN&-P%A;2dJTWjvlpI)pbQ&I`H6L|YFv0$3y1y_9#ZuyaF6I5vU znDC2#D|pNbCX9R!hdeNj3{f5sWgL)A11OfJe4r_&rr4S?rzw`EV(4z}17s8mAygaio*6CxARPsmBFkeGrerS<2{&8@YSvHJTo~d3yj?z9 zY3#m~T*%$tejM`MRW1)z+}qt)T|4rE-6I|y?QZycyV6(ui=Nj$^!B;j-IH;&1pehG z_1a0rCE$q0nE z>DWBy*ktk4Ds#u^(z@ayRULJjq zqZUC32t|P%Ur5zxj4h+|>C>ll=s@~47*rn`urOc$e7-jNX3D7j2WS&=G0cIWX zg`tQWH`H~4(LZbPLu;=IW_$46AmD8Tz&f}9+~&p+U---XQ1W~OPn(~7UmI)R=y}2m zQ+k6g11w)-}lB1ct&zKbLMwCTmaBh zc^WD2gnAJh6DLKX3*wG;7dqdIvbwNHkGp=mivlHWy;#{=Yq|BYHIp*Nl>=;5!ska> zpkXw@p+UIQ&^x72OR`9Wn4J`nTC_-^NFihBDfsjiJ5oI%PT@4OaOg!ih%wbodxvlk!AFe+dMc zhoN+DmQ>BNTU#34CpdIfN(Fy{!ch9RDNKdBdvgKho%>SzA%8gJfuNg013dAVq?wr zwxEK(2Od%!A1Bogf{F$!jX#oi`T-q54u*FYdN<^oj%)y2F-9vtLPr8h0EE$FUv-B` zH7{@252@oJ3QWY$Fv*87&;aPez#PTRa9Kl41F{cK9XuuIp07er9_mQ$fx``Y26*{X&EyZZ}*$6quQJbol1?btM6#K5PWBP%j8C$b9 zC4LE!Af{nRa(kzWOR08z^1A z&%zw)@_}^-by(Tk#sz8Ca;bG!Gcl<`U0n}*0S^H`IlC~$Z$PT}Ee_a=O=M=?b@?0D zJpgK&l;j?<&9h2o04_G)(bfcZtu5Xp2GBbkniXT)5WgP@$1K0$TM>6%0ZS4kl*sry zdI6nurBBB86t5%tTX$i?AU_X`zna)99}xJp{+5HT#BQGDwZ;o)<|4f$HSsAhUy#)9 zYbJyL@D|~^ec;iG+$Cd=rAzNtzo&^T2q#a7yJ!EZ(R;xv! zFZmD6(nMDNzhI6F|No?5(niQtx6xAK)E)OIx<(7nmt#By#A@)9cB2Iq6p}R-*ZP?M zrr6eOfnk~yhF_XMk*|P$JtN8!N}XiUI6Ixy#EI2fKCQ0vC`Fgp8qToE7oWpWBf4q= zo5r+J-4shBwqGHeouYs>qW%u4W-18tFPo$I+U*3ACGtYZ+N9*VVa)mg&MU6_rtbyA zm4fTCxDDhfH@zf7f=$78WEuT`*ly^?1o!KkVG-_zwh8}WG|dXBd{p|-&X>%RRkbuH zoC#i6b%{vNLDzu~1)z?BW_S8&`SNA2fd+KYD5=^4FX|GU|S;!I22)Urt$V# zce^}*Zb|Ah(Wl@P^#UyF&Pv};)6f4J_iE=o#MuqTCB?5&H#|jfl<*%ohFz_YqDi6f MR7lCH+`ec18yo4dNB{r; diff --git a/venv/Lib/site-packages/bson/__pycache__/son.cpython-310.pyc b/venv/Lib/site-packages/bson/__pycache__/son.cpython-310.pyc deleted file mode 100644 index fd1a3ed441f7f546e05cfbb2e9d140db8f8d217f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7269 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\n') - - # Use a "details" disclosure element if parent has "class" arg "details". - def visit_definition_list_item(self, node): - if 'details' in node.parent['classes']: - atts = {} - if "open" in node.parent['classes']: - atts['open'] = 'open' - self.body.append(self.starttag(node, 'details', **atts)) - - def depart_definition_list_item(self, node): - if 'details' in node.parent['classes']: - self.body.append('\n') - - def visit_description(self, node): - self.body.append(self.starttag(node, 'dd', '')) - - def depart_description(self, node): - self.body.append('\n') - - def visit_docinfo(self, node): - self.context.append(len(self.body)) - classes = ['docinfo'] - if self.is_compactable(node): - classes.append('simple') - self.body.append(self.starttag(node, 'dl', classes=classes)) - - def depart_docinfo(self, node): - self.body.append('\n') - start = self.context.pop() - self.docinfo = self.body[start:] - self.body = [] - - def visit_docinfo_item(self, node, name, meta=True): - if meta: - self.meta.append(f'\n') - self.body.append(f'
{self.language.labels[name]}' - ':
\n') - self.body.append(self.starttag(node, 'dd', '', CLASS=name)) - - def depart_docinfo_item(self): - self.body.append('\n') - - def visit_doctest_block(self, node): - self.body.append(self.starttag(node, 'pre', suffix='', - classes=['code', 'python', 'doctest'])) - - def depart_doctest_block(self, node): - self.body.append('\n\n') - - def visit_document(self, node): - title = (node.get('title') or os.path.basename(node['source']) - or 'untitled Docutils document') - self.head.append(f'{self.encode(title)}\n') - - def depart_document(self, node): - self.head_prefix.extend([self.doctype, - self.head_prefix_template % - {'lang': self.settings.language_code}]) - self.html_prolog.append(self.doctype) - self.head = self.meta[:] + self.head - if 'name="dcterms.' in ''.join(self.meta): - self.head.append('') - if self.math_header: - if self.math_output == 'mathjax': - self.head.extend(self.math_header) - else: - self.stylesheet.extend(self.math_header) - # skip content-type meta tag with interpolated charset value: - self.html_head.extend(self.head[1:]) - self.body_prefix.append(self.starttag(node, **self.documenttag_args)) - self.body_suffix.insert(0, f'\n') - self.fragment.extend(self.body) # self.fragment is the "naked" body - self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo - + self.docinfo + self.body - + self.body_suffix[:-1]) - assert not self.context, f'len(context) = {len(self.context)}' - - def visit_emphasis(self, node): - self.body.append(self.starttag(node, 'em', '')) - - def depart_emphasis(self, node): - self.body.append('') - - def visit_entry(self, node): - atts = {'classes': []} - if isinstance(node.parent.parent, nodes.thead): - atts['classes'].append('head') - if node.parent.parent.parent.stubs[node.parent.column]: - # "stubs" list is an attribute of the tgroup element - atts['classes'].append('stub') - if atts['classes']: - tagname = 'th' - else: - tagname = 'td' - node.parent.column += 1 - if 'morerows' in node: - atts['rowspan'] = node['morerows'] + 1 - if 'morecols' in node: - atts['colspan'] = node['morecols'] + 1 - node.parent.column += node['morecols'] - self.body.append(self.starttag(node, tagname, '', **atts)) - self.context.append('\n' % tagname.lower()) - - def depart_entry(self, node): - self.body.append(self.context.pop()) - - def visit_enumerated_list(self, node): - atts = {'classes': []} - if 'start' in node: - atts['start'] = node['start'] - if 'enumtype' in node: - atts['classes'].append(node['enumtype']) - if self.is_compactable(node): - atts['classes'].append('simple') - self.body.append(self.starttag(node, 'ol', **atts)) - - def depart_enumerated_list(self, node): - self.body.append('\n') - - def visit_field_list(self, node): - atts = {} - classes = node.setdefault('classes', []) - for i, cls in enumerate(classes): - if cls.startswith('field-indent-'): - try: - indent_length = length_or_percentage_or_unitless( - cls[13:], 'px') - except ValueError: - break - atts['style'] = '--field-indent: %s;' % indent_length - classes.pop(i) - break - classes.append('field-list') - if self.is_compactable(node): - classes.append('simple') - self.body.append(self.starttag(node, 'dl', **atts)) - - def depart_field_list(self, node): - self.body.append('\n') - - def visit_field(self, node): - # Insert children ( and ) directly. - # Transfer "id" attribute to the child node. - for child in node: - if isinstance(child, nodes.field_name): - child['ids'].extend(node['ids']) - - def depart_field(self, node): - pass - - # as field is ignored, pass class arguments to field-name and field-body: - def visit_field_name(self, node): - self.body.append(self.starttag(node, 'dt', '', - classes=node.parent['classes'])) - - def depart_field_name(self, node): - self.body.append(':\n') - - def visit_field_body(self, node): - self.body.append(self.starttag(node, 'dd', '', - classes=node.parent['classes'])) - # prevent misalignment of following content if the field is empty: - if not node.children: - self.body.append('

') - - def depart_field_body(self, node): - self.body.append('\n') - - def visit_figure(self, node): - atts = {'class': 'figure'} - if node.get('width'): - atts['style'] = 'width: %s' % node['width'] - if node.get('align'): - atts['class'] += " align-" + node['align'] - self.body.append(self.starttag(node, 'div', **atts)) - - def depart_figure(self, node): - self.body.append('\n') - - def visit_footer(self, node): - self.context.append(len(self.body)) - - def depart_footer(self, node): - start = self.context.pop() - footer = [self.starttag(node, 'div', CLASS='footer'), - '\n'] - footer.extend(self.body[start:]) - footer.append('\n\n') - self.footer.extend(footer) - self.body_suffix[:0] = footer - del self.body[start:] - - def visit_footnote(self, node): - # No native HTML element: use \n') - - def visit_footnote_reference(self, node): - href = '#' + node['refid'] - classes = [self.settings.footnote_references] - self.body.append(self.starttag(node, 'a', suffix='', classes=classes, - role='doc-noteref', href=href)) - self.body.append('[') - - def depart_footnote_reference(self, node): - self.body.append(']') - self.body.append('') - - # Docutils-generated text: put section numbers in a span for CSS styling: - def visit_generated(self, node): - if 'sectnum' in node['classes']: - # get section number (strip trailing no-break-spaces) - sectnum = node.astext().rstrip(' ') - self.body.append('%s ' - % self.encode(sectnum)) - # Content already processed: - raise nodes.SkipNode - - def depart_generated(self, node): - pass - - def visit_header(self, node): - self.context.append(len(self.body)) - - def depart_header(self, node): - start = self.context.pop() - header = [self.starttag(node, 'div', CLASS='header')] - header.extend(self.body[start:]) - header.append('\n
\n\n') - self.body_prefix.extend(header) - self.header.extend(header) - del self.body[start:] - - def visit_image(self, node): - # reference/embed images (still images and videos) - uri = node['uri'] - alt = node.get('alt', uri) - mimetype = mimetypes.guess_type(uri)[0] - element = '' # the HTML element (including potential children) - atts = {} # attributes for the HTML tag - # alignment is handled by CSS rules - if 'align' in node: - atts['class'] = 'align-%s' % node['align'] - # set size with "style" attribute (more universal, accepts dimensions) - size_declaration = self.image_size(node) - if size_declaration: - atts['style'] = size_declaration - - # ``:loading:`` option (embed, link, lazy), default from setting, - # exception: only embed videos if told via directive option - loading = 'link' if mimetype in self.videotypes else self.image_loading - loading = node.get('loading', loading) - if loading == 'lazy': - atts['loading'] = 'lazy' - elif loading == 'embed': - try: - imagepath = self.uri2imagepath(uri) - with open(imagepath, 'rb') as imagefile: - imagedata = imagefile.read() - except (ValueError, OSError) as err: - self.messages.append(self.document.reporter.error( - f'Cannot embed image "{uri}":\n {err}', base_node=node)) - # TODO: get external files with urllib.request (cf. odtwriter)? - else: - self.settings.record_dependencies.add(imagepath) - if mimetype == 'image/svg+xml': - element = self.prepare_svg(node, imagedata, - size_declaration) - else: - data64 = base64.b64encode(imagedata).decode() - uri = f'data:{mimetype};base64,{data64}' - - # No newlines around inline images (but all images may be nested - # in a `reference` node which is a `TextElement` instance): - if (not isinstance(node.parent, nodes.TextElement) - or isinstance(node.parent, nodes.reference) - and not isinstance(node.parent.parent, nodes.TextElement)): - suffix = '\n' - else: - suffix = '' - - if mimetype in self.videotypes: - atts['title'] = alt - if 'controls' in node['classes']: - node['classes'].remove('controls') - atts['controls'] = 'controls' - element = (self.starttag(node, "video", suffix, src=uri, **atts) - + f'{alt}{suffix}' - + f'{suffix}') - elif mimetype == 'application/x-shockwave-flash': - atts['type'] = mimetype - element = (self.starttag(node, 'object', '', data=uri, **atts) - + f'{alt}{suffix}') - elif element: # embedded SVG, see above - element += suffix - else: - atts['alt'] = alt - element = self.emptytag(node, 'img', suffix, src=uri, **atts) - self.body.append(element) - if suffix: # block-element - self.report_messages(node) - - def depart_image(self, node): - pass - - def visit_inline(self, node): - self.body.append(self.starttag(node, 'span', '')) - - def depart_inline(self, node): - self.body.append('') - - # footnote and citation labels: - def visit_label(self, node): - self.body.append('') - self.body.append('[') - # footnote/citation backrefs: - if self.settings.footnote_backlinks: - backrefs = node.parent.get('backrefs', []) - if len(backrefs) == 1: - self.body.append('' % backrefs[0]) - - def depart_label(self, node): - backrefs = [] - if self.settings.footnote_backlinks: - backrefs = node.parent.get('backrefs', backrefs) - if len(backrefs) == 1: - self.body.append('') - self.body.append(']\n') - if len(backrefs) > 1: - backlinks = ['%s' % (ref, i) - for (i, ref) in enumerate(backrefs, 1)] - self.body.append('(%s)\n' - % ','.join(backlinks)) - - def visit_legend(self, node): - self.body.append(self.starttag(node, 'div', CLASS='legend')) - - def depart_legend(self, node): - self.body.append('\n') - - def visit_line(self, node): - self.body.append(self.starttag(node, 'div', suffix='', CLASS='line')) - if not len(node): - self.body.append('
') - - def depart_line(self, node): - self.body.append('\n') - - def visit_line_block(self, node): - self.body.append(self.starttag(node, 'div', CLASS='line-block')) - - def depart_line_block(self, node): - self.body.append('\n') - - def visit_list_item(self, node): - self.body.append(self.starttag(node, 'li', '')) - - def depart_list_item(self, node): - self.body.append('\n') - - # inline literal - def visit_literal(self, node): - # special case: "code" role - classes = node['classes'] - if 'code' in classes: - # filter 'code' from class arguments - classes.pop(classes.index('code')) - self.body.append(self.starttag(node, 'code', '')) - return - self.body.append( - self.starttag(node, 'span', '', CLASS='docutils literal')) - text = node.astext() - if not isinstance(node.parent, nodes.literal_block): - text = text.replace('\n', ' ') - # Protect text like ``--an-option`` and the regular expression - # ``[+]?(\d+(\.\d*)?|\.\d+)`` from bad line wrapping - for token in self.words_and_spaces.findall(text): - if token.strip() and self.in_word_wrap_point.search(token): - self.body.append('%s' - % self.encode(token)) - else: - self.body.append(self.encode(token)) - self.body.append('') - raise nodes.SkipNode # content already processed - - def depart_literal(self, node): - # skipped unless literal element is from "code" role: - self.body.append('') - - def visit_literal_block(self, node): - self.body.append(self.starttag(node, 'pre', '', CLASS='literal-block')) - if 'code' in node['classes']: - self.body.append('') - - def depart_literal_block(self, node): - if 'code' in node['classes']: - self.body.append('') - self.body.append('\n') - - # Mathematics: - # As there is no native HTML math support, we provide alternatives - # for the math-output: LaTeX and MathJax simply wrap the content, - # HTML and MathML also convert the math_code. - # HTML element: - math_tags = { # format: (inline, block, [class arguments]) - 'html': ('span', 'div', ['formula']), - 'latex': ('tt', 'pre', ['math']), - 'mathjax': ('span', 'div', ['math']), - 'mathml': ('', 'div', []), - 'problematic': ('span', 'pre', ['math', 'problematic']), - } - - def visit_math(self, node): - # Also called from `visit_math_block()`: - is_block = isinstance(node, nodes.math_block) - format = self.math_output - math_code = node.astext().translate(unichar2tex.uni2tex_table) - - # preamble code and conversion - if format == 'html': - if self.math_options and not self.math_header: - self.math_header = [ - self.stylesheet_call(utils.find_file_in_dirs( - s, self.settings.stylesheet_dirs), adjust_path=True) - for s in self.math_options.split(',')] - math2html.DocumentParameters.displaymode = is_block - # TODO: fix display mode in matrices and fractions - math_code = wrap_math_code(math_code, is_block) - math_code = math2html.math2html(math_code) - elif format == 'latex': - math_code = self.encode(math_code) - elif format == 'mathjax': - if not self.math_header: - if self.math_options: - self.mathjax_url = self.math_options - else: - self.document.reporter.warning( - 'No MathJax URL specified, using local fallback ' - '(see config.html).', base_node=node) - # append MathJax configuration - # (input LaTeX with AMS, output common HTML): - if '?' not in self.mathjax_url: - self.mathjax_url += '?config=TeX-AMS_CHTML' - self.math_header = [self.mathjax_script % self.mathjax_url] - if is_block: - math_code = wrap_math_code(math_code, is_block) - else: - math_code = rf'\({math_code}\)' - math_code = self.encode(math_code) - elif format == 'mathml': - if 'XHTML 1' in self.doctype: - self.doctype = self.doctype_mathml - self.content_type = self.content_type_mathml - if self.math_options: - converter = getattr(tex2mathml_extern, self.math_options) - else: - converter = latex2mathml.tex2mathml - try: - math_code = converter(math_code, as_block=is_block) - except (MathError, OSError) as err: - details = getattr(err, 'details', []) - self.messages.append(self.document.reporter.warning( - err, *details, base_node=node)) - math_code = self.encode(node.astext()) - if self.settings.report_level <= 2: - format = 'problematic' - else: - format = 'latex' - if isinstance(err, OSError): - # report missing converter only once - self.math_output = format - - # append to document body - tag = self.math_tags[format][is_block] - suffix = '\n' if is_block else '' - if tag: - self.body.append(self.starttag(node, tag, suffix=suffix, - classes=self.math_tags[format][2])) - self.body.extend([math_code, suffix]) - if tag: - self.body.append(f'{suffix}') - # Content already processed: - raise nodes.SkipChildren - - def depart_math(self, node): - pass - - def visit_math_block(self, node): - self.visit_math(node) - - def depart_math_block(self, node): - self.report_messages(node) - - # Meta tags: 'lang' attribute replaced by 'xml:lang' in XHTML 1.1 - # HTML5/polyglot recommends using both - def visit_meta(self, node): - self.meta.append(self.emptytag(node, 'meta', - **node.non_default_attributes())) - - def depart_meta(self, node): - pass - - def visit_option(self, node): - self.body.append(self.starttag(node, 'span', '', CLASS='option')) - - def depart_option(self, node): - self.body.append('') - if isinstance(node.next_node(descend=False, siblings=True), - nodes.option): - self.body.append(', ') - - def visit_option_argument(self, node): - self.body.append(node.get('delimiter', ' ')) - self.body.append(self.starttag(node, 'var', '')) - - def depart_option_argument(self, node): - self.body.append('') - - def visit_option_group(self, node): - self.body.append(self.starttag(node, 'dt', '')) - self.body.append('') - - def depart_option_group(self, node): - self.body.append('\n') - - def visit_option_list(self, node): - self.body.append( - self.starttag(node, 'dl', CLASS='option-list')) - - def depart_option_list(self, node): - self.body.append('\n') - - def visit_option_list_item(self, node): - pass - - def depart_option_list_item(self, node): - pass - - def visit_option_string(self, node): - pass - - def depart_option_string(self, node): - pass - - def visit_organization(self, node): - self.visit_docinfo_item(node, 'organization') - - def depart_organization(self, node): - self.depart_docinfo_item() - - # Do not omit

tags - # -------------------- - # - # The HTML4CSS1 writer does this to "produce - # visually compact lists (less vertical whitespace)". This writer - # relies on CSS rules for visual compactness. - # - # * In XHTML 1.1, e.g., a

element may not contain - # character data, so you cannot drop the

tags. - # * Keeping simple paragraphs in the field_body enables a CSS - # rule to start the field-body on a new line if the label is too long - # * it makes the code simpler. - # - # TODO: omit paragraph tags in simple table cells? - - def visit_paragraph(self, node): - self.body.append(self.starttag(node, 'p', '')) - - def depart_paragraph(self, node): - self.body.append('

') - if not (isinstance(node.parent, (nodes.list_item, nodes.entry)) - and (len(node.parent) == 1)): - self.body.append('\n') - self.report_messages(node) - - def visit_problematic(self, node): - if node.hasattr('refid'): - self.body.append('' % node['refid']) - self.context.append('') - else: - self.context.append('') - self.body.append(self.starttag(node, 'span', '', CLASS='problematic')) - - def depart_problematic(self, node): - self.body.append('') - self.body.append(self.context.pop()) - - def visit_raw(self, node): - if 'html' in node.get('format', '').split(): - if isinstance(node.parent, nodes.TextElement): - tagname = 'span' - else: - tagname = 'div' - if node['classes']: - self.body.append(self.starttag(node, tagname, suffix='')) - self.body.append(node.astext()) - if node['classes']: - self.body.append('' % tagname) - # Keep non-HTML raw text out of output: - raise nodes.SkipNode - - def visit_reference(self, node): - atts = {'classes': ['reference']} - suffix = '' - if 'refuri' in node: - atts['href'] = node['refuri'] - if (self.settings.cloak_email_addresses - and atts['href'].startswith('mailto:')): - atts['href'] = self.cloak_mailto(atts['href']) - self.in_mailto = True - atts['classes'].append('external') - else: - assert 'refid' in node, \ - 'References must have "refuri" or "refid" attribute.' - atts['href'] = '#' + node['refid'] - atts['classes'].append('internal') - if len(node) == 1 and isinstance(node[0], nodes.image): - atts['classes'].append('image-reference') - if not isinstance(node.parent, nodes.TextElement): - suffix = '\n' - self.body.append(self.starttag(node, 'a', suffix, **atts)) - - def depart_reference(self, node): - self.body.append('') - if not isinstance(node.parent, nodes.TextElement): - self.body.append('\n') - self.in_mailto = False - - def visit_revision(self, node): - self.visit_docinfo_item(node, 'revision', meta=False) - - def depart_revision(self, node): - self.depart_docinfo_item() - - def visit_row(self, node): - self.body.append(self.starttag(node, 'tr', '')) - node.column = 0 - - def depart_row(self, node): - self.body.append('\n') - - def visit_rubric(self, node): - self.body.append(self.starttag(node, 'p', '', CLASS='rubric')) - - def depart_rubric(self, node): - self.body.append('

\n') - - def visit_section(self, node): - self.section_level += 1 - self.body.append( - self.starttag(node, 'div', CLASS='section')) - - def depart_section(self, node): - self.section_level -= 1 - self.body.append('\n') - - # TODO: use the new HTML5 element \n') - - def visit_table(self, node): - atts = {'classes': self.settings.table_style.replace(',', ' ').split()} - if 'align' in node: - atts['classes'].append('align-%s' % node['align']) - if 'width' in node: - atts['style'] = 'width: %s;' % node['width'] - tag = self.starttag(node, 'table', **atts) - self.body.append(tag) - - def depart_table(self, node): - self.body.append('\n') - self.report_messages(node) - - def visit_target(self, node): - if ('refuri' not in node - and 'refid' not in node - and 'refname' not in node): - self.body.append(self.starttag(node, 'span', '', CLASS='target')) - self.context.append('') - else: - self.context.append('') - - def depart_target(self, node): - self.body.append(self.context.pop()) - - # no hard-coded vertical alignment in table body - def visit_tbody(self, node): - self.body.append(self.starttag(node, 'tbody')) - - def depart_tbody(self, node): - self.body.append('\n') - - def visit_term(self, node): - if 'details' in node.parent.parent['classes']: - self.body.append(self.starttag(node, 'summary', suffix='')) - else: - # The parent node (definition_list_item) is omitted in HTML. - self.body.append(self.starttag(node, 'dt', suffix='', - classes=node.parent['classes'], - ids=node.parent['ids'])) - - def depart_term(self, node): - # Nest (optional) classifier(s) in the
element - if node.next_node(nodes.classifier, descend=False, siblings=True): - return # skip (depart_classifier() calls this function again) - if 'details' in node.parent.parent['classes']: - self.body.append('\n') - else: - self.body.append('
\n') - - def visit_tgroup(self, node): - self.colspecs = [] - node.stubs = [] - - def depart_tgroup(self, node): - pass - - def visit_thead(self, node): - self.body.append(self.starttag(node, 'thead')) - - def depart_thead(self, node): - self.body.append('\n') - - def section_title_tags(self, node): - atts = {} - h_level = self.section_level + self.initial_header_level - 1 - # Only 6 heading levels have dedicated HTML tags. - tagname = 'h%i' % min(h_level, 6) - if h_level > 6: - atts['aria-level'] = h_level - start_tag = self.starttag(node, tagname, '', **atts) - if node.hasattr('refid'): - atts = {} - atts['class'] = 'toc-backref' - atts['role'] = 'doc-backlink' # HTML5 only - atts['href'] = '#' + node['refid'] - start_tag += self.starttag(nodes.reference(), 'a', '', **atts) - close_tag = '\n' % tagname - else: - close_tag = '\n' % tagname - return start_tag, close_tag - - def visit_title(self, node): - close_tag = '

\n' - if isinstance(node.parent, nodes.topic): - # TODO: use role="heading" or

? (HTML5 only) - self.body.append( - self.starttag(node, 'p', '', CLASS='topic-title')) - if (self.settings.toc_backlinks - and 'contents' in node.parent['classes']): - self.body.append('') - close_tag = '

\n' - elif isinstance(node.parent, nodes.sidebar): - # TODO: use role="heading" or

? (HTML5 only) - self.body.append( - self.starttag(node, 'p', '', CLASS='sidebar-title')) - elif isinstance(node.parent, nodes.Admonition): - self.body.append( - self.starttag(node, 'p', '', CLASS='admonition-title')) - elif isinstance(node.parent, nodes.table): - self.body.append(self.starttag(node, 'caption', '')) - close_tag = '\n' - elif isinstance(node.parent, nodes.document): - self.body.append(self.starttag(node, 'h1', '', CLASS='title')) - close_tag = '

\n' - self.in_document_title = len(self.body) - else: - assert isinstance(node.parent, nodes.section) - # Get correct heading and evt. backlink tags - start_tag, close_tag = self.section_title_tags(node) - self.body.append(start_tag) - self.context.append(close_tag) - - def depart_title(self, node): - self.body.append(self.context.pop()) - if self.in_document_title: - self.title = self.body[self.in_document_title:-1] - self.in_document_title = 0 - self.body_pre_docinfo.extend(self.body) - self.html_title.extend(self.body) - del self.body[:] - - def visit_title_reference(self, node): - self.body.append(self.starttag(node, 'cite', '')) - - def depart_title_reference(self, node): - self.body.append('') - - def visit_topic(self, node): - self.body.append(self.starttag(node, 'div', CLASS='topic')) - - def depart_topic(self, node): - self.body.append('\n') - - def visit_transition(self, node): - self.body.append(self.emptytag(node, 'hr', CLASS='docutils')) - - def depart_transition(self, node): - pass - - def visit_version(self, node): - self.visit_docinfo_item(node, 'version', meta=False) - - def depart_version(self, node): - self.depart_docinfo_item() - - def unimplemented_visit(self, node): - raise NotImplementedError('visiting unimplemented node type: %s' - % node.__class__.__name__) - - -class SimpleListChecker(nodes.GenericNodeVisitor): - - """ - Raise `nodes.NodeFound` if non-simple list item is encountered. - - Here "simple" means a list item containing nothing other than a single - paragraph, a simple list, or a paragraph followed by a simple list. - - This version also checks for simple field lists and docinfo. - """ - - def default_visit(self, node): - raise nodes.NodeFound - - def visit_list_item(self, node): - children = [child for child in node.children - if not isinstance(child, nodes.Invisible)] - if (children and isinstance(children[0], nodes.paragraph) - and (isinstance(children[-1], nodes.bullet_list) - or isinstance(children[-1], nodes.enumerated_list) - or isinstance(children[-1], nodes.field_list))): - children.pop() - if len(children) <= 1: - return - else: - raise nodes.NodeFound - - def pass_node(self, node): - pass - - def ignore_node(self, node): - # ignore nodes that are never complex (can contain only inline nodes) - raise nodes.SkipNode - - # Paragraphs and text - visit_Text = ignore_node - visit_paragraph = ignore_node - - # Lists - visit_bullet_list = pass_node - visit_enumerated_list = pass_node - visit_docinfo = pass_node - - # Docinfo nodes: - visit_author = ignore_node - visit_authors = visit_list_item - visit_address = visit_list_item - visit_contact = pass_node - visit_copyright = ignore_node - visit_date = ignore_node - visit_organization = ignore_node - visit_status = ignore_node - visit_version = visit_list_item - - # Definition list: - visit_definition_list = pass_node - visit_definition_list_item = pass_node - visit_term = ignore_node - visit_classifier = pass_node - visit_definition = visit_list_item - - # Field list: - visit_field_list = pass_node - visit_field = pass_node - # the field body corresponds to a list item - visit_field_body = visit_list_item - visit_field_name = ignore_node - - # Invisible nodes should be ignored. - visit_comment = ignore_node - visit_substitution_definition = ignore_node - visit_target = ignore_node - visit_pending = ignore_node diff --git a/venv/Lib/site-packages/docutils/writers/docutils_xml.py b/venv/Lib/site-packages/docutils/writers/docutils_xml.py deleted file mode 100644 index f416929..0000000 --- a/venv/Lib/site-packages/docutils/writers/docutils_xml.py +++ /dev/null @@ -1,187 +0,0 @@ -# $Id: docutils_xml.py 9502 2023-12-14 22:39:08Z milde $ -# Author: David Goodger, Paul Tremblay, Guenter Milde -# Maintainer: docutils-develop@lists.sourceforge.net -# Copyright: This module has been placed in the public domain. - -""" -Simple document tree Writer, writes Docutils XML according to -https://docutils.sourceforge.io/docs/ref/docutils.dtd. -""" - -__docformat__ = 'reStructuredText' - -from io import StringIO -import xml.sax.saxutils - -import docutils -from docutils import frontend, nodes, writers, utils - - -class RawXmlError(docutils.ApplicationError): - pass - - -class Writer(writers.Writer): - - supported = ('xml',) - """Formats this writer supports.""" - - settings_spec = ( - '"Docutils XML" Writer Options', - None, - (('Generate XML with newlines before and after tags.', - ['--newlines'], - {'action': 'store_true', 'validator': frontend.validate_boolean}), - ('Generate XML with indents and newlines.', - ['--indents'], # TODO use integer value for number of spaces? - {'action': 'store_true', 'validator': frontend.validate_boolean}), - ('Omit the XML declaration. Use with caution.', - ['--no-xml-declaration'], - {'dest': 'xml_declaration', 'default': 1, 'action': 'store_false', - 'validator': frontend.validate_boolean}), - ('Omit the DOCTYPE declaration.', - ['--no-doctype'], - {'dest': 'doctype_declaration', 'default': 1, - 'action': 'store_false', 'validator': frontend.validate_boolean}),)) - - settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'} - - config_section = 'docutils_xml writer' - config_section_dependencies = ('writers',) - - output = None - """Final translated form of `document`.""" - - def __init__(self): - writers.Writer.__init__(self) - self.translator_class = XMLTranslator - - def translate(self): - self.visitor = visitor = self.translator_class(self.document) - self.document.walkabout(visitor) - self.output = ''.join(visitor.output) - - -class XMLTranslator(nodes.GenericNodeVisitor): - - # TODO: add stylesheet options similar to HTML and LaTeX writers? - # xml_stylesheet = '\n' - doctype = ( - '\n') - generator = '\n' - - xmlparser = xml.sax.make_parser() - """SAX parser instance to check/extract raw XML.""" - xmlparser.setFeature( - "http://xml.org/sax/features/external-general-entities", True) - - def __init__(self, document): - nodes.NodeVisitor.__init__(self, document) - - # Reporter - self.warn = self.document.reporter.warning - self.error = self.document.reporter.error - - # Settings - self.settings = settings = document.settings - self.indent = self.newline = '' - if settings.newlines: - self.newline = '\n' - if settings.indents: - self.newline = '\n' - self.indent = ' ' # TODO make this configurable? - self.level = 0 # indentation level - self.in_simple = 0 # level of nesting inside mixed-content elements - self.fixed_text = 0 # level of nesting inside FixedText elements - - # Output - self.output = [] - if settings.xml_declaration: - self.output.append(utils.xml_declaration(settings.output_encoding)) - if settings.doctype_declaration: - self.output.append(self.doctype) - self.output.append(self.generator % docutils.__version__) - - # initialize XML parser - self.the_handle = TestXml() - self.xmlparser.setContentHandler(self.the_handle) - - # generic visit and depart methods - # -------------------------------- - - simple_nodes = (nodes.TextElement, nodes.meta, - nodes.image, nodes.colspec, nodes.transition) - - def default_visit(self, node): - """Default node visit method.""" - if not self.in_simple: - self.output.append(self.indent*self.level) - self.output.append(node.starttag(xml.sax.saxutils.quoteattr)) - self.level += 1 - # `nodes.literal` is not an instance of FixedTextElement by design, - # see docs/ref/rst/restructuredtext.html#inline-literals - if isinstance(node, (nodes.FixedTextElement, nodes.literal)): - self.fixed_text += 1 - if isinstance(node, self.simple_nodes): - self.in_simple += 1 - if not self.in_simple: - self.output.append(self.newline) - - def default_departure(self, node): - """Default node depart method.""" - self.level -= 1 - if not self.in_simple: - self.output.append(self.indent*self.level) - self.output.append(node.endtag()) - if isinstance(node, (nodes.FixedTextElement, nodes.literal)): - self.fixed_text -= 1 - if isinstance(node, self.simple_nodes): - self.in_simple -= 1 - if not self.in_simple: - self.output.append(self.newline) - - # specific visit and depart methods - # --------------------------------- - - def visit_Text(self, node): - text = xml.sax.saxutils.escape(node.astext()) - # indent text if we are not in a FixedText element: - if not self.fixed_text: - text = text.replace('\n', '\n'+self.indent*self.level) - self.output.append(text) - - def depart_Text(self, node): - pass - - def visit_raw(self, node): - if 'xml' not in node.get('format', '').split(): - # skip other raw content? - # raise nodes.SkipNode - self.default_visit(node) - return - # wrap in element - self.default_visit(node) # or not? - xml_string = node.astext() - self.output.append(xml_string) - self.default_departure(node) # or not? - # Check validity of raw XML: - try: - self.xmlparser.parse(StringIO(xml_string)) - except xml.sax._exceptions.SAXParseException: - col_num = self.the_handle.locator.getColumnNumber() - line_num = self.the_handle.locator.getLineNumber() - srcline = node.line - if not isinstance(node.parent, nodes.TextElement): - srcline += 2 # directive content start line - msg = 'Invalid raw XML in column %d, line offset %d:\n%s' % ( - col_num, line_num, node.astext()) - self.warn(msg, source=node.source, line=srcline+line_num-1) - raise nodes.SkipNode # content already processed - - -class TestXml(xml.sax.handler.ContentHandler): - - def setDocumentLocator(self, locator): - self.locator = locator diff --git a/venv/Lib/site-packages/docutils/writers/html4css1/__init__.py b/venv/Lib/site-packages/docutils/writers/html4css1/__init__.py deleted file mode 100644 index 799d30e..0000000 --- a/venv/Lib/site-packages/docutils/writers/html4css1/__init__.py +++ /dev/null @@ -1,955 +0,0 @@ -# $Id: __init__.py 9558 2024-03-11 17:48:52Z milde $ -# Author: David Goodger -# Maintainer: docutils-develop@lists.sourceforge.net -# Copyright: This module has been placed in the public domain. - -""" -Simple HyperText Markup Language document tree Writer. - -The output conforms to the XHTML version 1.0 Transitional DTD -(*almost* strict). The output contains a minimum of formatting -information. The cascading style sheet "html4css1.css" is required -for proper viewing with a modern graphical browser. -""" - -__docformat__ = 'reStructuredText' - -import os.path -import re - -from docutils import frontend, nodes, writers -from docutils.writers import _html_base -from docutils.writers._html_base import PIL - - -class Writer(writers._html_base.Writer): - - supported = ('html', 'html4', 'html4css1', 'xhtml', 'xhtml10') - """Formats this writer supports.""" - - default_stylesheets = ['html4css1.css'] - default_stylesheet_dirs = ['.', - os.path.abspath(os.path.dirname(__file__)), - os.path.abspath(os.path.join( - os.path.dirname(os.path.dirname(__file__)), - 'html5_polyglot')) # for math.css - ] - default_template = os.path.join( - os.path.dirname(os.path.abspath(__file__)), 'template.txt') - - # use a copy of the parent spec with some modifications - settings_spec = frontend.filter_settings_spec( - writers._html_base.Writer.settings_spec, - template=( - 'Template file. (UTF-8 encoded, default: "%s")' % default_template, - ['--template'], - {'default': default_template, 'metavar': ''}), - stylesheet_path=( - 'Comma separated list of stylesheet paths. ' - 'Relative paths are expanded if a matching file is found in ' - 'the --stylesheet-dirs. With --link-stylesheet, ' - 'the path is rewritten relative to the output HTML file. ' - '(default: "%s")' % ','.join(default_stylesheets), - ['--stylesheet-path'], - {'metavar': '', 'overrides': 'stylesheet', - 'validator': frontend.validate_comma_separated_list, - 'default': default_stylesheets}), - stylesheet_dirs=( - 'Comma-separated list of directories where stylesheets are found. ' - 'Used by --stylesheet-path when expanding relative path ' - 'arguments. (default: "%s")' % ','.join(default_stylesheet_dirs), - ['--stylesheet-dirs'], - {'metavar': '', - 'validator': frontend.validate_comma_separated_list, - 'default': default_stylesheet_dirs}), - initial_header_level=( - 'Specify the initial header level. Does not affect document ' - 'title & subtitle (see --no-doc-title). (default: 1 for "

")', - ['--initial-header-level'], - {'choices': '1 2 3 4 5 6'.split(), 'default': '1', - 'metavar': ''}), - xml_declaration=( - 'Prepend an XML declaration (default). ', - ['--xml-declaration'], - {'default': True, 'action': 'store_true', - 'validator': frontend.validate_boolean}), - ) - settings_spec = settings_spec + ( - 'HTML4 Writer Options', - '', - (('Specify the maximum width (in characters) for one-column field ' - 'names. Longer field names will span an entire row of the table ' - 'used to render the field list. Default is 14 characters. ' - 'Use 0 for "no limit".', - ['--field-name-limit'], - {'default': 14, 'metavar': '', - 'validator': frontend.validate_nonnegative_int}), - ('Specify the maximum width (in characters) for options in option ' - 'lists. Longer options will span an entire row of the table used ' - 'to render the option list. Default is 14 characters. ' - 'Use 0 for "no limit".', - ['--option-limit'], - {'default': 14, 'metavar': '', - 'validator': frontend.validate_nonnegative_int}), - ) - ) - - config_section = 'html4css1 writer' - - def __init__(self): - self.parts = {} - self.translator_class = HTMLTranslator - - -class HTMLTranslator(writers._html_base.HTMLTranslator): - """ - The html4css1 writer has been optimized to produce visually compact - lists (less vertical whitespace). HTML's mixed content models - allow list items to contain "
  • body elements

  • " or - "
  • just text
  • " or even "
  • text

    and body - elements

    combined
  • ", each with different effects. It would - be best to stick with strict body elements in list items, but they - affect vertical spacing in older browsers (although they really - shouldn't). - The html5_polyglot writer solves this using CSS2. - - Here is an outline of the optimization: - - - Check for and omit

    tags in "simple" lists: list items - contain either a single paragraph, a nested simple list, or a - paragraph followed by a nested simple list. This means that - this list can be compact: - - - Item 1. - - Item 2. - - But this list cannot be compact: - - - Item 1. - - This second paragraph forces space between list items. - - - Item 2. - - - In non-list contexts, omit

    tags on a paragraph if that - paragraph is the only child of its parent (footnotes & citations - are allowed a label first). - - - Regardless of the above, in definitions, table cells, field bodies, - option descriptions, and list items, mark the first child with - 'class="first"' and the last child with 'class="last"'. The stylesheet - sets the margins (top & bottom respectively) to 0 for these elements. - - The ``no_compact_lists`` setting (``--no-compact-lists`` command-line - option) disables list whitespace optimization. - """ - - # The following definitions are required for display in browsers limited - # to CSS1 or backwards compatible behaviour of the writer: - - doctype = ( - '\n') - - content_type = ('\n') - content_type_mathml = ('\n') - - # encode also non-breaking space - special_characters = _html_base.HTMLTranslator.special_characters.copy() - special_characters[0xa0] = ' ' - - # use character reference for dash (not valid in HTML5) - attribution_formats = {'dash': ('—', ''), - 'parentheses': ('(', ')'), - 'parens': ('(', ')'), - 'none': ('', '')} - - # ersatz for first/last pseudo-classes missing in CSS1 - def set_first_last(self, node): - self.set_class_on_child(node, 'first', 0) - self.set_class_on_child(node, 'last', -1) - - # add newline after opening tag - def visit_address(self, node): - self.visit_docinfo_item(node, 'address', meta=False) - self.body.append(self.starttag(node, 'pre', CLASS='address')) - - def depart_address(self, node): - self.body.append('\n\n') - self.depart_docinfo_item() - - # ersatz for first/last pseudo-classes - def visit_admonition(self, node): - node['classes'].insert(0, 'admonition') - self.body.append(self.starttag(node, 'div')) - self.set_first_last(node) - - def depart_admonition(self, node=None): - self.body.append('\n') - - # author, authors: use
    instead of paragraphs - def visit_author(self, node): - if isinstance(node.parent, nodes.authors): - if self.author_in_authors: - self.body.append('\n
    ') - else: - self.visit_docinfo_item(node, 'author') - - def depart_author(self, node): - if isinstance(node.parent, nodes.authors): - self.author_in_authors = True - else: - self.depart_docinfo_item() - - def visit_authors(self, node): - self.visit_docinfo_item(node, 'authors') - self.author_in_authors = False # initialize - - def depart_authors(self, node): - self.depart_docinfo_item() - - # use "width" argument instead of "style: 'width'": - def visit_colspec(self, node): - self.colspecs.append(node) - # "stubs" list is an attribute of the tgroup element: - node.parent.stubs.append(node.attributes.get('stub')) - - def depart_colspec(self, node): - # write out when all colspecs are processed - if isinstance(node.next_node(descend=False, siblings=True), - nodes.colspec): - return - if ('colwidths-auto' in node.parent.parent['classes'] - or ('colwidths-auto' in self.settings.table_style - and 'colwidths-given' not in node.parent.parent['classes'])): - return - total_width = sum(node['colwidth'] for node in self.colspecs) - self.body.append(self.starttag(node, 'colgroup')) - for node in self.colspecs: - colwidth = int(node['colwidth'] * 100.0 / total_width + 0.5) - self.body.append(self.emptytag(node, 'col', - width='%i%%' % colwidth)) - self.body.append('\n') - - # Compact lists: - # exclude definition lists and field lists (non-compact by default) - - def is_compactable(self, node): - return ('compact' in node['classes'] - or (self.settings.compact_lists - and 'open' not in node['classes'] - and (self.compact_simple - or 'contents' in node.parent['classes'] - # TODO: self.in_contents - or self.check_simple_list(node)))) - - # citations: Use table for bibliographic references. - def visit_citation(self, node): - self.body.append(self.starttag(node, 'table', - CLASS='docutils citation', - frame="void", rules="none")) - self.body.append('\n' - '\n' - '') - self.footnote_backrefs(node) - - def depart_citation(self, node): - self.body.append('\n' - '\n\n') - - def visit_citation_reference(self, node): - href = '#' - if 'refid' in node: - href += node['refid'] - elif 'refname' in node: - href += self.document.nameids[node['refname']] - self.body.append(self.starttag(node, 'a', suffix='[', href=href, - classes=['citation-reference'])) - - def depart_citation_reference(self, node): - self.body.append(']') - - # insert classifier-delimiter (not required with CSS2) - def visit_classifier(self, node): - self.body.append(' : ') - self.body.append(self.starttag(node, 'span', '', CLASS='classifier')) - - def depart_classifier(self, node): - self.body.append('') - self.depart_term(node) # close the

    after last classifier - - # ersatz for first/last pseudo-classes - def visit_compound(self, node): - self.body.append(self.starttag(node, 'div', CLASS='compound')) - if len(node) > 1: - node[0]['classes'].append('compound-first') - node[-1]['classes'].append('compound-last') - for child in node[1:-1]: - child['classes'].append('compound-middle') - - def depart_compound(self, node): - self.body.append('\n') - - # ersatz for first/last pseudo-classes, no special handling of "details" - def visit_definition(self, node): - self.body.append(self.starttag(node, 'dd', '')) - self.set_first_last(node) - - def depart_definition(self, node): - self.body.append('\n') - - # don't add "simple" class value, no special handling of "details" - def visit_definition_list(self, node): - self.body.append(self.starttag(node, 'dl', CLASS='docutils')) - - def depart_definition_list(self, node): - self.body.append('\n') - - # no special handling of "details" - def visit_definition_list_item(self, node): - pass - - def depart_definition_list_item(self, node): - pass - - # use a table for description lists - def visit_description(self, node): - self.body.append(self.starttag(node, 'td', '')) - self.set_first_last(node) - - def depart_description(self, node): - self.body.append('') - - # use table for docinfo - def visit_docinfo(self, node): - self.context.append(len(self.body)) - self.body.append(self.starttag(node, 'table', - CLASS='docinfo', - frame="void", rules="none")) - self.body.append('\n' - '\n' - '\n') - self.in_docinfo = True - - def depart_docinfo(self, node): - self.body.append('\n\n') - self.in_docinfo = False - start = self.context.pop() - self.docinfo = self.body[start:] - self.body = [] - - def visit_docinfo_item(self, node, name, meta=True): - if meta: - meta_tag = '\n' \ - % (name, self.attval(node.astext())) - self.meta.append(meta_tag) - self.body.append(self.starttag(node, 'tr', '')) - self.body.append('%s:\n' - % self.language.labels[name]) - if len(node): - if isinstance(node[0], nodes.Element): - node[0]['classes'].append('first') - if isinstance(node[-1], nodes.Element): - node[-1]['classes'].append('last') - - def depart_docinfo_item(self): - self.body.append('\n') - - # add newline after opening tag - def visit_doctest_block(self, node): - self.body.append(self.starttag(node, 'pre', CLASS='doctest-block')) - - def depart_doctest_block(self, node): - self.body.append('\n\n') - - # insert an NBSP into empty cells, ersatz for first/last - def visit_entry(self, node): - writers._html_base.HTMLTranslator.visit_entry(self, node) - if len(node) == 0: # empty cell - self.body.append(' ') - self.set_first_last(node) - - def depart_entry(self, node): - self.body.append(self.context.pop()) - - # ersatz for first/last pseudo-classes - def visit_enumerated_list(self, node): - """ - The 'start' attribute does not conform to HTML 4.01's strict.dtd, but - cannot be emulated in CSS1 (HTML 5 reincludes it). - """ - atts = {} - if 'start' in node: - atts['start'] = node['start'] - if 'enumtype' in node: - atts['class'] = node['enumtype'] - # @@@ To do: prefix, suffix. How? Change prefix/suffix to a - # single "format" attribute? Use CSS2? - old_compact_simple = self.compact_simple - self.context.append((self.compact_simple, self.compact_p)) - self.compact_p = None - self.compact_simple = self.is_compactable(node) - if self.compact_simple and not old_compact_simple: - atts['class'] = (atts.get('class', '') + ' simple').strip() - self.body.append(self.starttag(node, 'ol', **atts)) - - def depart_enumerated_list(self, node): - self.compact_simple, self.compact_p = self.context.pop() - self.body.append('\n') - - # use table for field-list: - def visit_field(self, node): - self.body.append(self.starttag(node, 'tr', '', CLASS='field')) - - def depart_field(self, node): - self.body.append('\n') - - def visit_field_body(self, node): - self.body.append(self.starttag(node, 'td', '', CLASS='field-body')) - self.set_class_on_child(node, 'first', 0) - field = node.parent - if (self.compact_field_list - or isinstance(field.parent, nodes.docinfo) - or field.parent.index(field) == len(field.parent) - 1): - # If we are in a compact list, the docinfo, or if this is - # the last field of the field list, do not add vertical - # space after last element. - self.set_class_on_child(node, 'last', -1) - - def depart_field_body(self, node): - self.body.append('\n') - - def visit_field_list(self, node): - self.context.append((self.compact_field_list, self.compact_p)) - self.compact_p = None - if 'compact' in node['classes']: - self.compact_field_list = True - elif (self.settings.compact_field_lists - and 'open' not in node['classes']): - self.compact_field_list = True - if self.compact_field_list: - for field in node: - field_body = field[-1] - assert isinstance(field_body, nodes.field_body) - children = [n for n in field_body - if not isinstance(n, nodes.Invisible)] - if not (len(children) == 0 - or len(children) == 1 - and isinstance(children[0], - (nodes.paragraph, nodes.line_block))): - self.compact_field_list = False - break - self.body.append(self.starttag(node, 'table', frame='void', - rules='none', - CLASS='docutils field-list')) - self.body.append('\n' - '\n' - '\n') - - def depart_field_list(self, node): - self.body.append('\n\n') - self.compact_field_list, self.compact_p = self.context.pop() - - def visit_field_name(self, node): - atts = {} - if self.in_docinfo: - atts['class'] = 'docinfo-name' - else: - atts['class'] = 'field-name' - if (self.settings.field_name_limit - and len(node.astext()) > self.settings.field_name_limit): - atts['colspan'] = 2 - self.context.append('\n' - + self.starttag(node.parent, 'tr', '', - CLASS='field') - + ' ') - else: - self.context.append('') - self.body.append(self.starttag(node, 'th', '', **atts)) - - def depart_field_name(self, node): - self.body.append(':') - self.body.append(self.context.pop()) - - # use table for footnote text - def visit_footnote(self, node): - self.body.append(self.starttag(node, 'table', - CLASS='docutils footnote', - frame="void", rules="none")) - self.body.append('\n' - '\n' - '') - self.footnote_backrefs(node) - - def footnote_backrefs(self, node): - backlinks = [] - backrefs = node['backrefs'] - if self.settings.footnote_backlinks and backrefs: - if len(backrefs) == 1: - self.context.append('') - self.context.append('') - self.context.append('' - % backrefs[0]) - else: - for (i, backref) in enumerate(backrefs, 1): - backlinks.append('%s' - % (backref, i)) - self.context.append('(%s) ' % ', '.join(backlinks)) - self.context += ['', ''] - else: - self.context.append('') - self.context += ['', ''] - # If the node does not only consist of a label. - if len(node) > 1: - # If there are preceding backlinks, we do not set class - # 'first', because we need to retain the top-margin. - if not backlinks: - node[1]['classes'].append('first') - node[-1]['classes'].append('last') - - def depart_footnote(self, node): - self.body.append('\n' - '\n\n') - - # insert markers in text (pseudo-classes are not supported in CSS1): - def visit_footnote_reference(self, node): - href = '#' + node['refid'] - format = self.settings.footnote_references - if format == 'brackets': - suffix = '[' - self.context.append(']') - else: - assert format == 'superscript' - suffix = '' - self.context.append('') - self.body.append(self.starttag(node, 'a', suffix, - CLASS='footnote-reference', href=href)) - - def depart_footnote_reference(self, node): - self.body.append(self.context.pop() + '') - - # just pass on generated text - def visit_generated(self, node): - pass - - # Backwards-compatibility implementation: - # * Do not use

    \n') - self.in_document_title = len(self.body) - elif isinstance(node.parent, nodes.section): - tag = 'h%s' % (self.section_level + self.initial_header_level - 1) - self.body.append( - self.starttag(node, tag, '', CLASS='section-subtitle') - + self.starttag({}, 'span', '', CLASS='section-subtitle')) - self.context.append('\n' % tag) - - def depart_subtitle(self, node): - self.body.append(self.context.pop()) - if self.in_document_title: - self.subtitle = self.body[self.in_document_title:-1] - self.in_document_title = 0 - self.body_pre_docinfo.extend(self.body) - self.html_subtitle.extend(self.body) - del self.body[:] - - # not allowed in
     in HTML 4
    -    def visit_superscript(self, node):
    -        if isinstance(node.parent, nodes.literal_block):
    -            self.body.append(self.starttag(node, 'span', '',
    -                                           CLASS='superscript'))
    -        else:
    -            self.body.append(self.starttag(node, 'sup', ''))
    -
    -    def depart_superscript(self, node):
    -        if isinstance(node.parent, nodes.literal_block):
    -            self.body.append('')
    -        else:
    -            self.body.append('')
    -
    -    #  element deprecated in HTML 5
    -    def visit_system_message(self, node):
    -        self.body.append(self.starttag(node, 'div', CLASS='system-message'))
    -        self.body.append('

    ') - backref_text = '' - if len(node['backrefs']): - backrefs = node['backrefs'] - if len(backrefs) == 1: - backref_text = ('; backlink' - % backrefs[0]) - else: - i = 1 - backlinks = [] - for backref in backrefs: - backlinks.append('%s' % (backref, i)) - i += 1 - backref_text = ('; backlinks: %s' - % ', '.join(backlinks)) - if node.hasattr('line'): - line = ', line %s' % node['line'] - else: - line = '' - self.body.append('System Message: %s/%s ' - '(%s%s)%s

    \n' - % (node['type'], node['level'], - self.encode(node['source']), line, backref_text)) - - def depart_system_message(self, node): - self.body.append('\n') - - # "hard coded" border setting - def visit_table(self, node): - self.context.append(self.compact_p) - self.compact_p = True - atts = {'border': 1} - classes = ['docutils', self.settings.table_style] - if 'align' in node: - classes.append('align-%s' % node['align']) - if 'width' in node: - atts['style'] = 'width: %s' % node['width'] - self.body.append( - self.starttag(node, 'table', CLASS=' '.join(classes), **atts)) - - def depart_table(self, node): - self.compact_p = self.context.pop() - self.body.append('\n') - - # hard-coded vertical alignment - def visit_tbody(self, node): - self.body.append(self.starttag(node, 'tbody', valign='top')) - - def depart_tbody(self, node): - self.body.append('\n') - - # no special handling of "details" in definition list - def visit_term(self, node): - self.body.append(self.starttag(node, 'dt', '', - classes=node.parent['classes'], - ids=node.parent['ids'])) - - def depart_term(self, node): - # Nest (optional) classifier(s) in the
    element - if node.next_node(nodes.classifier, descend=False, siblings=True): - return # skip (depart_classifier() calls this function again) - self.body.append('
    \n') - - # hard-coded vertical alignment - def visit_thead(self, node): - self.body.append(self.starttag(node, 'thead', valign='bottom')) - - def depart_thead(self, node): - self.body.append('\n') - - # auxiliary method, called by visit_title() - # "with-subtitle" class, no ARIA roles - def section_title_tags(self, node): - classes = [] - h_level = self.section_level + self.initial_header_level - 1 - if (len(node.parent) >= 2 - and isinstance(node.parent[1], nodes.subtitle)): - classes.append('with-subtitle') - if h_level > 6: - classes.append('h%i' % h_level) - tagname = 'h%i' % min(h_level, 6) - start_tag = self.starttag(node, tagname, '', classes=classes) - if node.hasattr('refid'): - atts = {} - atts['class'] = 'toc-backref' - atts['href'] = '#' + node['refid'] - start_tag += self.starttag({}, 'a', '', **atts) - close_tag = '\n' % tagname - else: - close_tag = '\n' % tagname - return start_tag, close_tag - - -class SimpleListChecker(writers._html_base.SimpleListChecker): - - """ - Raise `nodes.NodeFound` if non-simple list item is encountered. - - Here "simple" means a list item containing nothing other than a single - paragraph, a simple list, or a paragraph followed by a simple list. - """ - - def visit_list_item(self, node): - children = [] - for child in node.children: - if not isinstance(child, nodes.Invisible): - children.append(child) - if (children and isinstance(children[0], nodes.paragraph) - and (isinstance(children[-1], nodes.bullet_list) - or isinstance(children[-1], nodes.enumerated_list))): - children.pop() - if len(children) <= 1: - return - else: - raise nodes.NodeFound - - # def visit_bullet_list(self, node): - # pass - - # def visit_enumerated_list(self, node): - # pass - - def visit_paragraph(self, node): - raise nodes.SkipNode - - def visit_definition_list(self, node): - raise nodes.NodeFound - - def visit_docinfo(self, node): - raise nodes.NodeFound diff --git a/venv/Lib/site-packages/docutils/writers/html4css1/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/docutils/writers/html4css1/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index fd0dc13483cc96e1ca113f067e30bff6cc5a54a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32158 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 -# Based on the html4css1 writer by David Goodger. -# :Maintainer: docutils-develop@lists.sourceforge.net -# :Copyright: © 2005, 2009, 2015 Günter Milde, -# portions from html4css1 © David Goodger. -# :License: Released under the terms of the `2-Clause BSD license`_, in short: -# -# Copying and distribution of this file, with or without modification, -# are permitted in any medium without royalty provided the copyright -# notice and this notice are preserved. -# This file is offered as-is, without any warranty. -# -# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause - -# Use "best practice" as recommended by the W3C: -# http://www.w3.org/2009/cheatsheet/ - -""" -Plain HyperText Markup Language document tree Writer. - -The output conforms to the `HTML 5` specification. - -The cascading style sheet "minimal.css" is required for proper viewing, -the style sheet "plain.css" improves reading experience. -""" -__docformat__ = 'reStructuredText' - -from pathlib import Path - -from docutils import frontend, nodes -from docutils.writers import _html_base - - -class Writer(_html_base.Writer): - - supported = ('html5', 'xhtml', 'html') - """Formats this writer supports.""" - - default_stylesheets = ['minimal.css', 'plain.css'] - default_stylesheet_dirs = ['.', str(Path(__file__).parent)] - default_template = Path(__file__).parent / 'template.txt' - - # use a copy of the parent spec with some modifications - settings_spec = frontend.filter_settings_spec( - _html_base.Writer.settings_spec, - template=( - f'Template file. (UTF-8 encoded, default: "{default_template}")', - ['--template'], - {'default': default_template, 'metavar': ''}), - stylesheet_path=( - 'Comma separated list of stylesheet paths. ' - 'Relative paths are expanded if a matching file is found in ' - 'the --stylesheet-dirs. With --link-stylesheet, ' - 'the path is rewritten relative to the output HTML file. ' - '(default: "%s")' % ','.join(default_stylesheets), - ['--stylesheet-path'], - {'metavar': '', 'overrides': 'stylesheet', - 'validator': frontend.validate_comma_separated_list, - 'default': default_stylesheets}), - stylesheet_dirs=( - 'Comma-separated list of directories where stylesheets are found. ' - 'Used by --stylesheet-path when expanding relative path ' - 'arguments. (default: "%s")' % ','.join(default_stylesheet_dirs), - ['--stylesheet-dirs'], - {'metavar': '', - 'validator': frontend.validate_comma_separated_list, - 'default': default_stylesheet_dirs}), - initial_header_level=( - 'Specify the initial header level. Does not affect document ' - 'title & subtitle (see --no-doc-title). (default: 2 for "

    ")', - ['--initial-header-level'], - {'choices': '1 2 3 4 5 6'.split(), 'default': '2', - 'metavar': ''}), - no_xml_declaration=( - 'Omit the XML declaration (default).', - ['--no-xml-declaration'], - {'dest': 'xml_declaration', 'action': 'store_false'}), - ) - settings_spec = settings_spec + ( - 'HTML5 Writer Options', - '', - ((frontend.SUPPRESS_HELP, # Obsoleted by "--image-loading" - ['--embed-images'], - {'action': 'store_true', - 'validator': frontend.validate_boolean}), - (frontend.SUPPRESS_HELP, # Obsoleted by "--image-loading" - ['--link-images'], - {'dest': 'embed_images', 'action': 'store_false'}), - ('Suggest at which point images should be loaded: ' - '"embed", "link" (default), or "lazy".', - ['--image-loading'], - {'choices': ('embed', 'link', 'lazy'), - # 'default': 'link' # default set in _html_base.py - }), - ('Append a self-link to section headings.', - ['--section-self-link'], - {'default': False, 'action': 'store_true'}), - ('Do not append a self-link to section headings. (default)', - ['--no-section-self-link'], - {'dest': 'section_self_link', 'action': 'store_false'}), - ) - ) - - config_section = 'html5 writer' - - def __init__(self): - self.parts = {} - self.translator_class = HTMLTranslator - - -class HTMLTranslator(_html_base.HTMLTranslator): - """ - This writer generates `polyglot markup`: HTML5 that is also valid XML. - - Safe subclassing: when overriding, treat ``visit_*`` and ``depart_*`` - methods as a unit to prevent breaks due to internal changes. See the - docstring of docutils.writers._html_base.HTMLTranslator for details - and examples. - """ - - # self.starttag() arguments for the main document - documenttag_args = {'tagname': 'main'} - - # add meta tag to fix rendering in mobile browsers - def __init__(self, document): - super().__init__(document) - self.meta.append('\n') - - # tag obsolete in HTML5. Use the tag instead. - def visit_acronym(self, node): - # @@@ implementation incomplete ("title" attribute) - self.body.append(self.starttag(node, 'abbr', '')) - - def depart_acronym(self, node): - self.body.append('') - - # no standard meta tag name in HTML5, use separate "author" meta tags - # https://www.w3.org/TR/html5/document-metadata.html#standard-metadata-names - def visit_authors(self, node): - self.visit_docinfo_item(node, 'authors', meta=False) - for subnode in node: - self.meta.append('\n') - - def depart_authors(self, node): - self.depart_docinfo_item() - - # use the
    semantic tag. - def visit_caption(self, node): - if isinstance(node.parent, nodes.figure): - self.body.append('
    \n') - self.body.append(self.starttag(node, 'p', '')) - - def depart_caption(self, node): - self.body.append('

    \n') - #
    is closed in depart_figure(), as legend may follow. - - # use HTML block-level tags if matching class value found - supported_block_tags = {'ins', 'del'} - - def visit_container(self, node): - # If there is exactly one of the "supported block tags" in - # the list of class values, use it as tag name: - classes = node['classes'] - tags = [cls for cls in classes - if cls in self.supported_block_tags] - if len(tags) == 1: - node.html5tagname = tags[0] - classes.remove(tags[0]) - else: - node.html5tagname = 'div' - self.body.append(self.starttag(node, node.html5tagname, - CLASS='docutils container')) - - def depart_container(self, node): - self.body.append(f'\n') - del node.html5tagname - - # no standard meta tag name in HTML5, use dcterms.rights - # see https://wiki.whatwg.org/wiki/MetaExtensions - def visit_copyright(self, node): - self.visit_docinfo_item(node, 'copyright', meta=False) - self.meta.append('\n') - - def depart_copyright(self, node): - self.depart_docinfo_item() - - # no standard meta tag name in HTML5, use dcterms.date - def visit_date(self, node): - self.visit_docinfo_item(node, 'date', meta=False) - self.meta.append('\n') - - def depart_date(self, node): - self.depart_docinfo_item() - - # use new HTML5
    and
    elements - def visit_figure(self, node): - atts = {} - if node.get('width'): - atts['style'] = f"width: {node['width']}" - if node.get('align'): - atts['class'] = f"align-{node['align']}" - self.body.append(self.starttag(node, 'figure', **atts)) - - def depart_figure(self, node): - if len(node) > 1: - self.body.append('
    \n') - self.body.append('
    \n') - - # use HTML5
    element - def visit_footer(self, node): - self.context.append(len(self.body)) - - def depart_footer(self, node): - start = self.context.pop() - footer = [self.starttag(node, 'footer')] - footer.extend(self.body[start:]) - footer.append('
    \n') - self.footer.extend(footer) - self.body_suffix[:0] = footer - del self.body[start:] - - # use HTML5
    element - def visit_header(self, node): - self.context.append(len(self.body)) - - def depart_header(self, node): - start = self.context.pop() - header = [self.starttag(node, 'header')] - header.extend(self.body[start:]) - header.append('
    \n') - self.body_prefix.extend(header) - self.header.extend(header) - del self.body[start:] - - # use HTML text-level tags if matching class value found - supported_inline_tags = {'code', 'kbd', 'dfn', 'samp', 'var', - 'bdi', 'del', 'ins', 'mark', 'small', - 'b', 'i', 'q', 's', 'u'} - - # Use `supported_inline_tags` if found in class values - def visit_inline(self, node): - classes = node['classes'] - node.html5tagname = 'span' - # Special handling for "code" directive content - if (isinstance(node.parent, nodes.literal_block) - and 'code' in node.parent.get('classes') - or isinstance(node.parent, nodes.literal) - and getattr(node.parent, 'html5tagname', None) == 'code'): - if classes == ['ln']: - # line numbers are not part of the "fragment of computer code" - if self.body[-1] == '': - del self.body[-1] - else: - self.body.append('') - node.html5tagname = 'small' - else: - tags = [cls for cls in self.supported_inline_tags - if cls in classes] - if len(tags): - node.html5tagname = tags[0] - classes.remove(node.html5tagname) - self.body.append(self.starttag(node, node.html5tagname, '')) - - def depart_inline(self, node): - self.body.append(f'') - if (node.html5tagname == 'small' and node.get('classes') == ['ln'] - and isinstance(node.parent, nodes.literal_block)): - self.body.append(f'') - del node.html5tagname - - # place inside HTML5
    element (together with caption) - def visit_legend(self, node): - if not isinstance(node.parent[1], nodes.caption): - self.body.append('
    \n') - self.body.append(self.starttag(node, 'div', CLASS='legend')) - - def depart_legend(self, node): - self.body.append('\n') - #
    closed in visit_figure() - - # use HTML5 text-level tags if matching class value found - def visit_literal(self, node): - classes = node['classes'] - html5tagname = 'span' - tags = [cls for cls in self.supported_inline_tags - if cls in classes] - if len(tags): - html5tagname = tags[0] - classes.remove(html5tagname) - if html5tagname == 'code': - node.html5tagname = html5tagname - self.body.append(self.starttag(node, html5tagname, '')) - return - self.body.append( - self.starttag(node, html5tagname, '', CLASS='docutils literal')) - text = node.astext() - # remove hard line breaks (except if in a parsed-literal block) - if not isinstance(node.parent, nodes.literal_block): - text = text.replace('\n', ' ') - # Protect text like ``--an-option`` and the regular expression - # ``[+]?(\d+(\.\d*)?|\.\d+)`` from bad line wrapping - for token in self.words_and_spaces.findall(text): - if token.strip() and self.in_word_wrap_point.search(token): - self.body.append( - f'{self.encode(token)}') - else: - self.body.append(self.encode(token)) - self.body.append(f'') - # Content already processed: - raise nodes.SkipNode - - def depart_literal(self, node): - # skipped unless literal element is from "code" role: - self.depart_inline(node) - - # Meta tags: 'lang' attribute replaced by 'xml:lang' in XHTML 1.1 - # HTML5/polyglot recommends using both - def visit_meta(self, node): - if node.hasattr('lang'): - node['xml:lang'] = node['lang'] - self.meta.append(self.emptytag(node, 'meta', - **node.non_default_attributes())) - - def depart_meta(self, node): - pass - - # no standard meta tag name in HTML5 - def visit_organization(self, node): - self.visit_docinfo_item(node, 'organization', meta=False) - - def depart_organization(self, node): - self.depart_docinfo_item() - - # use the new HTML5 element
    - def visit_section(self, node): - self.section_level += 1 - self.body.append( - self.starttag(node, 'section')) - - def depart_section(self, node): - self.section_level -= 1 - self.body.append('
    \n') - - # use the new HTML5 element \n') - self.in_sidebar = False - - # Use new HTML5 element

    (=R9U|RBv0x_XbD( zwuRb|+dp7+&siF}<#D?{v=-PK)AOwSWS^9I=*Z9)3tDK_Q9OU>$mHxdv&H3B7F?y+eyrXR5<`_p;h`EFh=%{6lAoz9=MthuzAmB+G!}TElz(gcaw2@f(V+ zdj@_ZpkgKHg>oCW6C;6IUnYGa)y`O+_P~%IQ?o!#i<;Zi{Fa(K)clT`KT@-Qt7uB! z({w%2{hd;ls~HaN75vb;mUXFNT28}s9k=S*_*L@Xl&vo{Z(4qWIkfxE0FKA*C1rYf zh8peLD)xZr(wD2G`1PAq>$HMR5n(5(wuRok-_Q&-3|Jwk{!i2%{2s1GEpkt`>^2~o#0BYP&%@DD8b z3-~2(Sg_(3SmB$h6<|xp=U&}=eC%7MX=Iso@Z<5PudZeN#NhAcnc$UW+3K4i+#(jY zxs%(%A&!l_lXrwmT;UN<_{0|h2}DRj(Is8m0#`mUHEte>h(x=3FONk`;vM(%M5H7& zbzKOc2j0>-w0M9>`VjIE{QGS8i$nHIF8VL`!1O+ZM?B`q(lvbpo?cp`-si)swt^wc z*Gz#LHVXJ~-VW!gEPmnhMz)SwQIs{S*JYtbzD}<`zMsQS+FTtTn_Hf>q}1U$E`T<@szC+2f9RK5_ zSuR0-x8y$7BmAC>pJ&$!q{^yQDIlAGx~a=5JDp57EYCJjY_ik!JX7l$o>pve!&aa& oH1q8CDe97lSJhyw{QdakkFuuy zgOk}|!sMl<5s?8n)Trialu$h)vF_>wu@M=u;To~&nsLc3sWmgQ;<8(gZP$(~ZiQ&f zq~wygRa#;-YHevhYqU)5w;Hus>C$lPtPY+km%2L#D>Yi((r9g8Yt~0k55ky@(u6sj zMZRRz8OksUWyplnPr38s{$8i`FGk!XdCgCfRQfVZ6VWtso5BVO`|}D)$|C9KmK=pi zKSlLkhL(Pmmkx$m#PZT%0&|Wj=cfDW^ zpbu${)&Z618l9u_fGqlmF422{%Jea9&}Be2tgX;hKoxo)GF{JWKZU=RjoQOeu*KEm?Z@VPR|!Wn6i;4%=z^~ zo}`KMMo2%QKBrC;_PEb49GV8h54)73trID;=j}FVL@QJKS}7m2uXnVk%(hNs96c#0 z-AsF@ERf>G8?U9D?67{Agvr41yaCi938l{m!t)%K_`L{H$im<(LW8ywq}c_aVqdOs9gDT>2ZYDmI)ew^B7H4wElich8LjhK3IuPS`8!PqE{dSXd3CY1cCW@8=J45~pj^bT}W`I_mbnO8#*CP-VriuP!DGu86EBHVoG<|@Vr zeP#+4^?41>=W`&gG`<2qlb!A7-9y2+=w^d7X5Aeo&SaW(cXwW$`%(9tCFkAUu-6r# zWSf~EocRMLx;>F5Z8`Gr7C>Qg+w+iEAQgNH8$^}Zq^?)Vs4){_Yic%GR=s}o;X-UU zK;m&gVCQro*5Rvos{f>F;z36+1QH*Z9kVs+pY$c{b8FoC#?{(JG!7 zM81HALzb`@p7$|uz6K6&hYfa|W!&?=1Eq?0{SJ?XL9SCdS(?5eN7MUotlA^MOs4}e zGKyKe$8<1@eT_c^*d!{TE4?7`D_FW6Qe`NEqP;dj`yRbnWVAfX;RlP)p39%2=j#)( zZ2W5!w~7W&BeL{8s<2?ArP)&oL2u-B&--oY zM@6UPWzU1x4;tb=x_gA;OBCOrz}JK~QGDc3A?$vRf2p`jV6?Vol4=<~27cxZrOgd^ zv~vS0*J;l44KTw<`a^ihuuHMZ+(3aD@Dl1Rd6B^j$+3kv{8eilZ#zet@w(0Y^??J7 ifVWV5BEH<-Dsp~-eW`-9=If-PH^`#CXe@nUlK%k@aPX`E diff --git a/venv/Lib/site-packages/bson/_cbson.cp310-win_amd64.pyd b/venv/Lib/site-packages/bson/_cbson.cp310-win_amd64.pyd deleted file mode 100644 index 7b6715544861da7cff43f2bd16bff25048af5232..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46592 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 diff --git a/venv/Lib/site-packages/bson/_cbsonmodule.c b/venv/Lib/site-packages/bson/_cbsonmodule.c deleted file mode 100644 index 672f5ee..0000000 --- a/venv/Lib/site-packages/bson/_cbsonmodule.c +++ /dev/null @@ -1,3267 +0,0 @@ -/* - * Copyright 2009-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * This file contains C implementations of some of the functions - * needed by the bson module. If possible, these implementations - * should be used to speed up BSON encoding and decoding. - */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#include "datetime.h" - -#include "buffer.h" -#include "time64.h" - -#define _CBSON_MODULE -#include "_cbsonmodule.h" - -/* New module state and initialization code. - * See the module-initialization-and-state - * section in the following doc: - * http://docs.python.org/release/3.1.3/howto/cporting.html - * which references the following pep: - * http://www.python.org/dev/peps/pep-3121/ - * */ -struct module_state { - PyObject* Binary; - PyObject* Code; - PyObject* ObjectId; - PyObject* DBRef; - PyObject* Regex; - PyObject* UUID; - PyObject* Timestamp; - PyObject* MinKey; - PyObject* MaxKey; - PyObject* UTC; - PyTypeObject* REType; - PyObject* BSONInt64; - PyObject* Decimal128; - PyObject* Mapping; - PyObject* DatetimeMS; - PyObject* min_datetime; - PyObject* max_datetime; - PyObject* replace_args; - PyObject* replace_kwargs; - PyObject* _type_marker_str; - PyObject* _flags_str; - PyObject* _pattern_str; - PyObject* _encoder_map_str; - PyObject* _decoder_map_str; - PyObject* _fallback_encoder_str; - PyObject* _raw_str; - PyObject* _subtype_str; - PyObject* _binary_str; - PyObject* _scope_str; - PyObject* _inc_str; - PyObject* _time_str; - PyObject* _bid_str; - PyObject* _replace_str; - PyObject* _astimezone_str; - PyObject* _id_str; - PyObject* _dollar_ref_str; - PyObject* _dollar_id_str; - PyObject* _dollar_db_str; - PyObject* _tzinfo_str; - PyObject* _as_doc_str; - PyObject* _utcoffset_str; - PyObject* _from_uuid_str; - PyObject* _as_uuid_str; - PyObject* _from_bid_str; - int64_t min_millis; - int64_t max_millis; -}; - -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) - -/* Maximum number of regex flags */ -#define FLAGS_SIZE 7 - -/* Default UUID representation type code. */ -#define PYTHON_LEGACY 3 - -/* Other UUID representations. */ -#define STANDARD 4 -#define JAVA_LEGACY 5 -#define CSHARP_LEGACY 6 -#define UNSPECIFIED 0 - -#define BSON_MAX_SIZE 2147483647 -/* The smallest possible BSON document, i.e. "{}" */ -#define BSON_MIN_SIZE 5 - -/* Datetime codec options */ -#define DATETIME 1 -#define DATETIME_CLAMP 2 -#define DATETIME_MS 3 -#define DATETIME_AUTO 4 - -/* Converts integer to its string representation in decimal notation. */ -extern int cbson_long_long_to_str(long long num, char* str, size_t size) { - // Buffer should fit 64-bit signed integer - if (size < 21) { - PyErr_Format( - PyExc_RuntimeError, - "Buffer too small to hold long long: %d < 21", size); - return -1; - } - int index = 0; - int sign = 1; - // Convert to unsigned to handle -LLONG_MIN overflow - unsigned long long absNum; - // Handle the case of 0 - if (num == 0) { - str[index++] = '0'; - str[index] = '\0'; - return 0; - } - // Handle negative numbers - if (num < 0) { - sign = -1; - absNum = 0ULL - (unsigned long long)num; - } else { - absNum = (unsigned long long)num; - } - // Convert the number to string - unsigned long long digit; - while (absNum > 0) { - digit = absNum % 10ULL; - str[index++] = (char)digit + '0'; // Convert digit to character - absNum /= 10; - } - // Add minus sign if negative - if (sign == -1) { - str[index++] = '-'; - } - str[index] = '\0'; // Null terminator - // Reverse the string - int start = 0; - int end = index - 1; - while (start < end) { - char temp = str[start]; - str[start++] = str[end]; - str[end--] = temp; - } - return 0; -} - -static PyObject* _test_long_long_to_str(PyObject* self, PyObject* args) { - // Test extreme values - Py_ssize_t maxNum = PY_SSIZE_T_MAX; - Py_ssize_t minNum = PY_SSIZE_T_MIN; - Py_ssize_t num; - char str_1[BUF_SIZE]; - char str_2[BUF_SIZE]; - int res = LL2STR(str_1, (long long)minNum); - if (res == -1) { - return NULL; - } - INT2STRING(str_2, (long long)minNum); - if (strcmp(str_1, str_2) != 0) { - PyErr_Format( - PyExc_RuntimeError, - "LL2STR != INT2STRING: %s != %s", str_1, str_2); - return NULL; - } - LL2STR(str_1, (long long)maxNum); - INT2STRING(str_2, (long long)maxNum); - if (strcmp(str_1, str_2) != 0) { - PyErr_Format( - PyExc_RuntimeError, - "LL2STR != INT2STRING: %s != %s", str_1, str_2); - return NULL; - } - - // Test common values - for (num = 0; num < 10000; num++) { - char str_1[BUF_SIZE]; - char str_2[BUF_SIZE]; - LL2STR(str_1, (long long)num); - INT2STRING(str_2, (long long)num); - if (strcmp(str_1, str_2) != 0) { - PyErr_Format( - PyExc_RuntimeError, - "LL2STR != INT2STRING: %s != %s", str_1, str_2); - return NULL; - } - } - - return args; -} - -/* Get an error class from the bson.errors module. - * - * Returns a new ref */ -static PyObject* _error(char* name) { - PyObject* error = NULL; - PyObject* errors = PyImport_ImportModule("bson.errors"); - if (!errors) { - return NULL; - } - error = PyObject_GetAttrString(errors, name); - Py_DECREF(errors); - return error; -} - -/* Safely downcast from Py_ssize_t to int, setting an - * exception and returning -1 on error. */ -static int -_downcast_and_check(Py_ssize_t size, uint8_t extra) { - if (size > BSON_MAX_SIZE || ((BSON_MAX_SIZE - extra) < size)) { - PyObject* InvalidStringData = _error("InvalidStringData"); - if (InvalidStringData) { - PyErr_SetString(InvalidStringData, - "String length must be <= 2147483647"); - Py_DECREF(InvalidStringData); - } - return -1; - } - return (int)size + extra; -} - -static PyObject* elements_to_dict(PyObject* self, const char* string, - unsigned max, - const codec_options_t* options); - -static int _write_element_to_buffer(PyObject* self, buffer_t buffer, - int type_byte, PyObject* value, - unsigned char check_keys, - const codec_options_t* options, - unsigned char in_custom_call, - unsigned char in_fallback_call); - -/* Write a RawBSONDocument to the buffer. - * Returns the number of bytes written or 0 on failure. - */ -static int write_raw_doc(buffer_t buffer, PyObject* raw, PyObject* _raw); - -/* Date stuff */ -static PyObject* datetime_from_millis(long long millis) { - /* To encode a datetime instance like datetime(9999, 12, 31, 23, 59, 59, 999999) - * we follow these steps: - * 1. Calculate a timestamp in seconds: 253402300799 - * 2. Multiply that by 1000: 253402300799000 - * 3. Add in microseconds divided by 1000 253402300799999 - * - * (Note: BSON doesn't support microsecond accuracy, hence the truncation.) - * - * To decode we could do: - * 1. Get seconds: timestamp / 1000: 253402300799 - * 2. Get micros: (timestamp % 1000) * 1000: 999000 - * Resulting in datetime(9999, 12, 31, 23, 59, 59, 999000) -- the expected result - * - * Now what if the we encode (1, 1, 1, 1, 1, 1, 111111)? - * 1. and 2. gives: -62135593139000 - * 3. Gives us: -62135593138889 - * - * Now decode: - * 1. Gives us: -62135593138 - * 2. Gives us: -889000 - * Resulting in datetime(1, 1, 1, 1, 1, 2, 15888216) -- an invalid result - * - * If instead to decode we do: - * diff = ((millis % 1000) + 1000) % 1000: 111 - * seconds = (millis - diff) / 1000: -62135593139 - * micros = diff * 1000 111000 - * Resulting in datetime(1, 1, 1, 1, 1, 1, 111000) -- the expected result - */ - PyObject* datetime = NULL; - int diff = (int)(((millis % 1000) + 1000) % 1000); - int microseconds = diff * 1000; - Time64_T seconds = (millis - diff) / 1000; - struct TM timeinfo; - cbson_gmtime64_r(&seconds, &timeinfo); - - datetime = PyDateTime_FromDateAndTime(timeinfo.tm_year + 1900, - timeinfo.tm_mon + 1, - timeinfo.tm_mday, - timeinfo.tm_hour, - timeinfo.tm_min, - timeinfo.tm_sec, - microseconds); - if(!datetime) { - PyObject *etype = NULL, *evalue = NULL, *etrace = NULL; - - /* - * Calling _error clears the error state, so fetch it first. - */ - PyErr_Fetch(&etype, &evalue, &etrace); - - /* Only add addition error message on ValueError exceptions. */ - if (PyErr_GivenExceptionMatches(etype, PyExc_ValueError)) { - if (evalue) { - PyObject* err_msg = PyObject_Str(evalue); - if (err_msg) { - PyObject* appendage = PyUnicode_FromString(" (Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO) or MongoClient(datetime_conversion='DATETIME_AUTO')). See: https://www.mongodb.com/docs/languages/python/pymongo-driver/current/data-formats/dates-and-times/#handling-out-of-range-datetimes"); - if (appendage) { - PyObject* msg = PyUnicode_Concat(err_msg, appendage); - if (msg) { - Py_DECREF(evalue); - evalue = msg; - } - } - Py_XDECREF(appendage); - } - Py_XDECREF(err_msg); - } - PyErr_NormalizeException(&etype, &evalue, &etrace); - } - /* Steals references to args. */ - PyErr_Restore(etype, evalue, etrace); - } - return datetime; -} - -static long long millis_from_datetime(PyObject* datetime) { - struct TM timeinfo; - long long millis; - - timeinfo.tm_year = PyDateTime_GET_YEAR(datetime) - 1900; - timeinfo.tm_mon = PyDateTime_GET_MONTH(datetime) - 1; - timeinfo.tm_mday = PyDateTime_GET_DAY(datetime); - timeinfo.tm_hour = PyDateTime_DATE_GET_HOUR(datetime); - timeinfo.tm_min = PyDateTime_DATE_GET_MINUTE(datetime); - timeinfo.tm_sec = PyDateTime_DATE_GET_SECOND(datetime); - - millis = cbson_timegm64(&timeinfo) * 1000; - millis += PyDateTime_DATE_GET_MICROSECOND(datetime) / 1000; - return millis; -} - -/* Extended-range datetime, returns a DatetimeMS object with millis */ -static PyObject* datetime_ms_from_millis(PyObject* self, long long millis){ - // Allocate a new DatetimeMS object. - struct module_state *state = GETSTATE(self); - if (!state) { - return NULL; - } - - PyObject* dt = NULL; - PyObject* ll_millis = NULL; - - if (!(ll_millis = PyLong_FromLongLong(millis))){ - return NULL; - } - dt = PyObject_CallFunctionObjArgs(state->DatetimeMS, ll_millis, NULL); - Py_DECREF(ll_millis); - return dt; -} - -/* Extended-range datetime, takes a DatetimeMS object and extracts the long long value. */ -static int millis_from_datetime_ms(PyObject* dt, long long* out){ - PyObject* ll_millis; - long long millis; - - if (!(ll_millis = PyNumber_Long(dt))){ - return 0; - } - millis = PyLong_AsLongLong(ll_millis); - Py_DECREF(ll_millis); - if (millis == -1 && PyErr_Occurred()) { /* Overflow */ - PyErr_SetString(PyExc_OverflowError, - "MongoDB datetimes can only handle up to 8-byte ints"); - return 0; - } - *out = millis; - return 1; -} - -static PyObject* decode_datetime(PyObject* self, long long millis, const codec_options_t* options){ - PyObject* naive = NULL; - PyObject* replace = NULL; - PyObject* value = NULL; - struct module_state *state = GETSTATE(self); - if (!state) { - goto invalid; - } - if (options->datetime_conversion == DATETIME_MS){ - return datetime_ms_from_millis(self, millis); - } - - int dt_clamp = options->datetime_conversion == DATETIME_CLAMP; - int dt_auto = options->datetime_conversion == DATETIME_AUTO; - - if (dt_clamp || dt_auto){ - int64_t min_millis = state->min_millis; - int64_t max_millis = state->max_millis; - int64_t min_millis_offset = 0; - int64_t max_millis_offset = 0; - if (options->tz_aware && options->tzinfo && options->tzinfo != Py_None) { - PyObject* utcoffset = PyObject_CallMethodObjArgs(options->tzinfo, state->_utcoffset_str, state->min_datetime, NULL); - if (utcoffset == NULL) { - return 0; - } - if (utcoffset != Py_None) { - if (!PyDelta_Check(utcoffset)) { - PyObject* BSONError = _error("BSONError"); - if (BSONError) { - PyErr_SetString(BSONError, "tzinfo.utcoffset() did not return a datetime.timedelta"); - Py_DECREF(BSONError); - } - Py_DECREF(utcoffset); - return 0; - } - min_millis_offset = (PyDateTime_DELTA_GET_DAYS(utcoffset) * (int64_t)86400 + - PyDateTime_DELTA_GET_SECONDS(utcoffset)) * (int64_t)1000 + - (PyDateTime_DELTA_GET_MICROSECONDS(utcoffset) / 1000); - } - Py_DECREF(utcoffset); - utcoffset = PyObject_CallMethodObjArgs(options->tzinfo, state->_utcoffset_str, state->max_datetime, NULL); - if (utcoffset == NULL) { - return 0; - } - if (utcoffset != Py_None) { - if (!PyDelta_Check(utcoffset)) { - PyObject* BSONError = _error("BSONError"); - if (BSONError) { - PyErr_SetString(BSONError, "tzinfo.utcoffset() did not return a datetime.timedelta"); - Py_DECREF(BSONError); - } - Py_DECREF(utcoffset); - return 0; - } - max_millis_offset = (PyDateTime_DELTA_GET_DAYS(utcoffset) * (int64_t)86400 + - PyDateTime_DELTA_GET_SECONDS(utcoffset)) * (int64_t)1000 + - (PyDateTime_DELTA_GET_MICROSECONDS(utcoffset) / 1000); - } - Py_DECREF(utcoffset); - } - if (min_millis_offset < 0) { - min_millis -= min_millis_offset; - } - - if (max_millis_offset > 0) { - max_millis -= max_millis_offset; - } - - if (dt_clamp) { - if (millis < min_millis) { - millis = min_millis; - } else if (millis > max_millis) { - millis = max_millis; - } - // Continues from here to return a datetime. - } else { // dt_auto - if (millis < min_millis || millis > max_millis){ - return datetime_ms_from_millis(self, millis); - } - } - } - - naive = datetime_from_millis(millis); - if (!naive) { - goto invalid; - } - - if (!options->tz_aware) { /* In the naive case, we're done here. */ - return naive; - } - replace = PyObject_GetAttr(naive, state->_replace_str); - if (!replace) { - goto invalid; - } - value = PyObject_Call(replace, state->replace_args, state->replace_kwargs); - if (!value) { - goto invalid; - } - - /* convert to local time */ - if (options->tzinfo != Py_None) { - PyObject* temp = PyObject_CallMethodObjArgs(value, state->_astimezone_str, options->tzinfo, NULL); - Py_DECREF(value); - value = temp; - } -invalid: - Py_XDECREF(naive); - Py_XDECREF(replace); - return value; -} - -/* Just make this compatible w/ the old API. */ -int buffer_write_bytes(buffer_t buffer, const char* data, int size) { - if (pymongo_buffer_write(buffer, data, size)) { - return 0; - } - return 1; -} - -int buffer_write_double(buffer_t buffer, double data) { - double data_le = BSON_DOUBLE_TO_LE(data); - return buffer_write_bytes(buffer, (const char*)&data_le, 8); -} - -int buffer_write_int32(buffer_t buffer, int32_t data) { - uint32_t data_le = BSON_UINT32_TO_LE(data); - return buffer_write_bytes(buffer, (const char*)&data_le, 4); -} - -int buffer_write_int64(buffer_t buffer, int64_t data) { - uint64_t data_le = BSON_UINT64_TO_LE(data); - return buffer_write_bytes(buffer, (const char*)&data_le, 8); -} - -void buffer_write_int32_at_position(buffer_t buffer, - int position, - int32_t data) { - uint32_t data_le = BSON_UINT32_TO_LE(data); - memcpy(pymongo_buffer_get_buffer(buffer) + position, &data_le, 4); -} - -static int write_unicode(buffer_t buffer, PyObject* py_string) { - int size; - const char* data; - PyObject* encoded = PyUnicode_AsUTF8String(py_string); - if (!encoded) { - return 0; - } - data = PyBytes_AS_STRING(encoded); - if (!data) - goto unicodefail; - - if ((size = _downcast_and_check(PyBytes_GET_SIZE(encoded), 1)) == -1) - goto unicodefail; - - if (!buffer_write_int32(buffer, (int32_t)size)) - goto unicodefail; - - if (!buffer_write_bytes(buffer, data, size)) - goto unicodefail; - - Py_DECREF(encoded); - return 1; - -unicodefail: - Py_DECREF(encoded); - return 0; -} - -/* returns 0 on failure */ -static int write_string(buffer_t buffer, PyObject* py_string) { - int size; - const char* data; - if (PyUnicode_Check(py_string)){ - return write_unicode(buffer, py_string); - } - data = PyBytes_AsString(py_string); - if (!data) { - return 0; - } - - if ((size = _downcast_and_check(PyBytes_Size(py_string), 1)) == -1) - return 0; - - if (!buffer_write_int32(buffer, (int32_t)size)) { - return 0; - } - if (!buffer_write_bytes(buffer, data, size)) { - return 0; - } - return 1; -} - -/* Load a Python object to cache. - * - * Returns non-zero on failure. */ -static int _load_object(PyObject** object, char* module_name, char* object_name) { - PyObject* module; - - module = PyImport_ImportModule(module_name); - if (!module) { - return 1; - } - - *object = PyObject_GetAttrString(module, object_name); - Py_DECREF(module); - - return (*object) ? 0 : 2; -} - -/* Load all Python objects to cache. - * - * Returns non-zero on failure. */ -static int _load_python_objects(PyObject* module) { - PyObject* empty_string = NULL; - PyObject* re_compile = NULL; - PyObject* compiled = NULL; - PyObject* min_datetime_ms = NULL; - PyObject* max_datetime_ms = NULL; - struct module_state *state = GETSTATE(module); - if (!state) { - return 1; - } - - /* Cache commonly used attribute names to improve performance. */ - if (!((state->_type_marker_str = PyUnicode_FromString("_type_marker")) && - (state->_flags_str = PyUnicode_FromString("flags")) && - (state->_pattern_str = PyUnicode_FromString("pattern")) && - (state->_encoder_map_str = PyUnicode_FromString("_encoder_map")) && - (state->_decoder_map_str = PyUnicode_FromString("_decoder_map")) && - (state->_fallback_encoder_str = PyUnicode_FromString("_fallback_encoder")) && - (state->_raw_str = PyUnicode_FromString("raw")) && - (state->_subtype_str = PyUnicode_FromString("subtype")) && - (state->_binary_str = PyUnicode_FromString("binary")) && - (state->_scope_str = PyUnicode_FromString("scope")) && - (state->_inc_str = PyUnicode_FromString("inc")) && - (state->_time_str = PyUnicode_FromString("time")) && - (state->_bid_str = PyUnicode_FromString("bid")) && - (state->_replace_str = PyUnicode_FromString("replace")) && - (state->_astimezone_str = PyUnicode_FromString("astimezone")) && - (state->_id_str = PyUnicode_FromString("_id")) && - (state->_dollar_ref_str = PyUnicode_FromString("$ref")) && - (state->_dollar_id_str = PyUnicode_FromString("$id")) && - (state->_dollar_db_str = PyUnicode_FromString("$db")) && - (state->_tzinfo_str = PyUnicode_FromString("tzinfo")) && - (state->_as_doc_str = PyUnicode_FromString("as_doc")) && - (state->_utcoffset_str = PyUnicode_FromString("utcoffset")) && - (state->_from_uuid_str = PyUnicode_FromString("from_uuid")) && - (state->_as_uuid_str = PyUnicode_FromString("as_uuid")) && - (state->_from_bid_str = PyUnicode_FromString("from_bid")))) { - return 1; - } - - if (_load_object(&state->Binary, "bson.binary", "Binary") || - _load_object(&state->Code, "bson.code", "Code") || - _load_object(&state->ObjectId, "bson.objectid", "ObjectId") || - _load_object(&state->DBRef, "bson.dbref", "DBRef") || - _load_object(&state->Timestamp, "bson.timestamp", "Timestamp") || - _load_object(&state->MinKey, "bson.min_key", "MinKey") || - _load_object(&state->MaxKey, "bson.max_key", "MaxKey") || - _load_object(&state->UTC, "bson.tz_util", "utc") || - _load_object(&state->Regex, "bson.regex", "Regex") || - _load_object(&state->BSONInt64, "bson.int64", "Int64") || - _load_object(&state->Decimal128, "bson.decimal128", "Decimal128") || - _load_object(&state->UUID, "uuid", "UUID") || - _load_object(&state->Mapping, "collections.abc", "Mapping") || - _load_object(&state->DatetimeMS, "bson.datetime_ms", "DatetimeMS") || - _load_object(&min_datetime_ms, "bson.datetime_ms", "_MIN_UTC_MS") || - _load_object(&max_datetime_ms, "bson.datetime_ms", "_MAX_UTC_MS") || - _load_object(&state->min_datetime, "bson.datetime_ms", "_MIN_UTC") || - _load_object(&state->max_datetime, "bson.datetime_ms", "_MAX_UTC")) { - return 1; - } - - state->min_millis = PyLong_AsLongLong(min_datetime_ms); - state->max_millis = PyLong_AsLongLong(max_datetime_ms); - Py_DECREF(min_datetime_ms); - Py_DECREF(max_datetime_ms); - if ((state->min_millis == -1 || state->max_millis == -1) && PyErr_Occurred()) { - return 1; - } - - /* Speed up datetime.replace(tzinfo=utc) call */ - state->replace_args = PyTuple_New(0); - if (!state->replace_args) { - return 1; - } - state->replace_kwargs = PyDict_New(); - if (!state->replace_kwargs) { - return 1; - } - if (PyDict_SetItem(state->replace_kwargs, state->_tzinfo_str, state->UTC) == -1) { - return 1; - } - - /* Reload our REType hack too. */ - empty_string = PyBytes_FromString(""); - if (empty_string == NULL) { - state->REType = NULL; - return 1; - } - - if (_load_object(&re_compile, "re", "compile")) { - state->REType = NULL; - Py_DECREF(empty_string); - return 1; - } - - compiled = PyObject_CallFunction(re_compile, "O", empty_string); - Py_DECREF(re_compile); - if (compiled == NULL) { - state->REType = NULL; - Py_DECREF(empty_string); - return 1; - } - Py_INCREF(Py_TYPE(compiled)); - state->REType = Py_TYPE(compiled); - Py_DECREF(empty_string); - Py_DECREF(compiled); - return 0; -} - -/* - * Get the _type_marker from an Object. - * - * Return the type marker, 0 if there is no marker, or -1 on failure. - */ -static long _type_marker(PyObject* object, PyObject* _type_marker_str) { - PyObject* type_marker = NULL; - long type = 0; - - if (PyObject_HasAttr(object, _type_marker_str)) { - type_marker = PyObject_GetAttr(object, _type_marker_str); - if (type_marker == NULL) { - return -1; - } - } - - /* - * Python objects with broken __getattr__ implementations could return - * arbitrary types for a call to PyObject_GetAttrString. For example - * pymongo.database.Database returns a new Collection instance for - * __getattr__ calls with names that don't match an existing attribute - * or method. In some cases "value" could be a subtype of something - * we know how to serialize. Make a best effort to encode these types. - */ - if (type_marker && PyLong_CheckExact(type_marker)) { - type = PyLong_AsLong(type_marker); - Py_DECREF(type_marker); - } else { - Py_XDECREF(type_marker); - } - - return type; -} - -/* Fill out a type_registry_t* from a TypeRegistry object. - * - * Return 1 on success. options->document_class is a new reference. - * Return 0 on failure. - */ -int cbson_convert_type_registry(PyObject* registry_obj, type_registry_t* registry, PyObject* _encoder_map_str, PyObject* _decoder_map_str, PyObject* _fallback_encoder_str) { - registry->encoder_map = NULL; - registry->decoder_map = NULL; - registry->fallback_encoder = NULL; - registry->registry_obj = NULL; - - registry->encoder_map = PyObject_GetAttr(registry_obj, _encoder_map_str); - if (registry->encoder_map == NULL) { - goto fail; - } - registry->is_encoder_empty = (PyDict_Size(registry->encoder_map) == 0); - - registry->decoder_map = PyObject_GetAttr(registry_obj, _decoder_map_str); - if (registry->decoder_map == NULL) { - goto fail; - } - registry->is_decoder_empty = (PyDict_Size(registry->decoder_map) == 0); - - registry->fallback_encoder = PyObject_GetAttr(registry_obj, _fallback_encoder_str); - if (registry->fallback_encoder == NULL) { - goto fail; - } - registry->has_fallback_encoder = (registry->fallback_encoder != Py_None); - - registry->registry_obj = registry_obj; - Py_INCREF(registry->registry_obj); - return 1; - -fail: - Py_XDECREF(registry->encoder_map); - Py_XDECREF(registry->decoder_map); - Py_XDECREF(registry->fallback_encoder); - return 0; -} - -/* Fill out a codec_options_t* from a CodecOptions object. - * - * Return 1 on success. options->document_class is a new reference. - * Return 0 on failure. - */ -int convert_codec_options(PyObject* self, PyObject* options_obj, codec_options_t* options) { - PyObject* type_registry_obj = NULL; - struct module_state *state = GETSTATE(self); - long type_marker; - if (!state) { - return 0; - } - - options->unicode_decode_error_handler = NULL; - - if (!PyArg_ParseTuple(options_obj, "ObbzOOb", - &options->document_class, - &options->tz_aware, - &options->uuid_rep, - &options->unicode_decode_error_handler, - &options->tzinfo, - &type_registry_obj, - &options->datetime_conversion)) { - return 0; - } - - type_marker = _type_marker(options->document_class, - state->_type_marker_str); - if (type_marker < 0) { - return 0; - } - - if (!cbson_convert_type_registry(type_registry_obj, - &options->type_registry, state->_encoder_map_str, state->_decoder_map_str, state->_fallback_encoder_str)) { - return 0; - } - - options->is_raw_bson = (101 == type_marker); - options->options_obj = options_obj; - - Py_INCREF(options->options_obj); - Py_INCREF(options->document_class); - Py_INCREF(options->tzinfo); - - return 1; -} - -void destroy_codec_options(codec_options_t* options) { - Py_CLEAR(options->document_class); - Py_CLEAR(options->tzinfo); - Py_CLEAR(options->options_obj); - Py_CLEAR(options->type_registry.registry_obj); - Py_CLEAR(options->type_registry.encoder_map); - Py_CLEAR(options->type_registry.decoder_map); - Py_CLEAR(options->type_registry.fallback_encoder); -} - -static int write_element_to_buffer(PyObject* self, buffer_t buffer, - int type_byte, PyObject* value, - unsigned char check_keys, - const codec_options_t* options, - unsigned char in_custom_call, - unsigned char in_fallback_call) { - int result = 0; - if(Py_EnterRecursiveCall(" while encoding an object to BSON ")) { - return 0; - } - result = _write_element_to_buffer(self, buffer, type_byte, - value, check_keys, options, - in_custom_call, in_fallback_call); - Py_LeaveRecursiveCall(); - return result; -} - -static void -_set_cannot_encode(PyObject* value) { - if (PyLong_Check(value)) { - if ((PyLong_AsLongLong(value) == -1) && PyErr_Occurred()) { - return PyErr_SetString(PyExc_OverflowError, - "MongoDB can only handle up to 8-byte ints"); - } - } - - PyObject* type = NULL; - PyObject* InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument == NULL) { - goto error; - } - - type = PyObject_Type(value); - if (type == NULL) { - goto error; - } - PyErr_Format(InvalidDocument, "cannot encode object: %R, of type: %R", - value, type); -error: - Py_XDECREF(type); - Py_XDECREF(InvalidDocument); -} - -/* - * Encode a builtin Python regular expression or our custom Regex class. - * - * Sets exception and returns 0 on failure. - */ -static int _write_regex_to_buffer( - buffer_t buffer, int type_byte, PyObject* value, PyObject* _flags_str, PyObject* _pattern_str) { - - PyObject* py_flags; - PyObject* py_pattern; - PyObject* encoded_pattern; - PyObject* decoded_pattern; - long int_flags; - char flags[FLAGS_SIZE]; - char check_utf8 = 0; - const char* pattern_data; - int pattern_length, flags_length; - - /* - * Both the builtin re type and our Regex class have attributes - * "flags" and "pattern". - */ - py_flags = PyObject_GetAttr(value, _flags_str); - if (!py_flags) { - return 0; - } - int_flags = PyLong_AsLong(py_flags); - Py_DECREF(py_flags); - if (int_flags == -1 && PyErr_Occurred()) { - return 0; - } - py_pattern = PyObject_GetAttr(value, _pattern_str); - if (!py_pattern) { - return 0; - } - - if (PyUnicode_Check(py_pattern)) { - encoded_pattern = PyUnicode_AsUTF8String(py_pattern); - Py_DECREF(py_pattern); - if (!encoded_pattern) { - return 0; - } - } else { - encoded_pattern = py_pattern; - check_utf8 = 1; - } - - if (!(pattern_data = PyBytes_AsString(encoded_pattern))) { - Py_DECREF(encoded_pattern); - return 0; - } - if ((pattern_length = _downcast_and_check(PyBytes_Size(encoded_pattern), 0)) == -1) { - Py_DECREF(encoded_pattern); - return 0; - } - - if (strlen(pattern_data) != (size_t) pattern_length){ - PyObject* InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument) { - PyErr_SetString(InvalidDocument, - "regex patterns must not contain the NULL byte"); - Py_DECREF(InvalidDocument); - } - Py_DECREF(encoded_pattern); - return 0; - } - - if (check_utf8) { - decoded_pattern = PyUnicode_DecodeUTF8(pattern_data, (Py_ssize_t) pattern_length, NULL); - if (decoded_pattern == NULL) { - PyErr_Clear(); - PyObject* InvalidStringData = _error("InvalidStringData"); - if (InvalidStringData) { - PyErr_SetString(InvalidStringData, - "regex patterns must be valid UTF-8"); - Py_DECREF(InvalidStringData); - } - Py_DECREF(encoded_pattern); - return 0; - } - Py_DECREF(decoded_pattern); - } - - if (!buffer_write_bytes(buffer, pattern_data, pattern_length + 1)) { - Py_DECREF(encoded_pattern); - return 0; - } - Py_DECREF(encoded_pattern); - - flags[0] = 0; - - if (int_flags & 2) { - STRCAT(flags, FLAGS_SIZE, "i"); - } - if (int_flags & 4) { - STRCAT(flags, FLAGS_SIZE, "l"); - } - if (int_flags & 8) { - STRCAT(flags, FLAGS_SIZE, "m"); - } - if (int_flags & 16) { - STRCAT(flags, FLAGS_SIZE, "s"); - } - if (int_flags & 32) { - STRCAT(flags, FLAGS_SIZE, "u"); - } - if (int_flags & 64) { - STRCAT(flags, FLAGS_SIZE, "x"); - } - flags_length = (int)strlen(flags) + 1; - if (!buffer_write_bytes(buffer, flags, flags_length)) { - return 0; - } - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0B; - return 1; -} - -/* Write a single value to the buffer (also write its type_byte, for which - * space has already been reserved. - * - * returns 0 on failure */ -static int _write_element_to_buffer(PyObject* self, buffer_t buffer, - int type_byte, PyObject* value, - unsigned char check_keys, - const codec_options_t* options, - unsigned char in_custom_call, - unsigned char in_fallback_call) { - PyObject* new_value = NULL; - int retval; - int is_list; - long type; - struct module_state *state = GETSTATE(self); - if (!state) { - return 0; - } - /* - * Use _type_marker attribute instead of PyObject_IsInstance for better perf. - */ - type = _type_marker(value, state->_type_marker_str); - if (type < 0) { - return 0; - } - - switch (type) { - case 5: - { - /* Binary */ - PyObject* subtype_object; - char subtype; - const char* data; - int size; - - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x05; - subtype_object = PyObject_GetAttr(value, state->_subtype_str); - if (!subtype_object) { - return 0; - } - subtype = (char)PyLong_AsLong(subtype_object); - if (subtype == -1) { - Py_DECREF(subtype_object); - return 0; - } - size = _downcast_and_check(PyBytes_Size(value), 0); - if (size == -1) { - Py_DECREF(subtype_object); - return 0; - } - - Py_DECREF(subtype_object); - if (subtype == 2) { - int other_size = _downcast_and_check(PyBytes_Size(value), 4); - if (other_size == -1) - return 0; - if (!buffer_write_int32(buffer, other_size)) { - return 0; - } - if (!buffer_write_bytes(buffer, &subtype, 1)) { - return 0; - } - } - if (!buffer_write_int32(buffer, size)) { - return 0; - } - if (subtype != 2) { - if (!buffer_write_bytes(buffer, &subtype, 1)) { - return 0; - } - } - data = PyBytes_AsString(value); - if (!data) { - return 0; - } - if (!buffer_write_bytes(buffer, data, size)) { - return 0; - } - return 1; - } - case 7: - { - /* ObjectId */ - const char* data; - PyObject* pystring = PyObject_GetAttr(value, state->_binary_str); - if (!pystring) { - return 0; - } - data = PyBytes_AsString(pystring); - if (!data) { - Py_DECREF(pystring); - return 0; - } - if (!buffer_write_bytes(buffer, data, 12)) { - Py_DECREF(pystring); - return 0; - } - Py_DECREF(pystring); - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x07; - return 1; - } - case 9: - { - /* DatetimeMS */ - long long millis; - if (!millis_from_datetime_ms(value, &millis)) { - return 0; - } - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x09; - return buffer_write_int64(buffer, (int64_t)millis); - } - case 11: - { - /* Regex */ - return _write_regex_to_buffer(buffer, type_byte, value, state->_flags_str, state->_pattern_str); - } - case 13: - { - /* Code */ - int start_position, - length_location, - length; - - PyObject* scope = PyObject_GetAttr(value, state->_scope_str); - if (!scope) { - return 0; - } - - if (scope == Py_None) { - Py_DECREF(scope); - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0D; - return write_string(buffer, value); - } - - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0F; - - start_position = pymongo_buffer_get_position(buffer); - /* save space for length */ - length_location = pymongo_buffer_save_space(buffer, 4); - if (length_location == -1) { - Py_DECREF(scope); - return 0; - } - - if (!write_string(buffer, value)) { - Py_DECREF(scope); - return 0; - } - - if (!write_dict(self, buffer, scope, 0, options, 0)) { - Py_DECREF(scope); - return 0; - } - Py_DECREF(scope); - - length = pymongo_buffer_get_position(buffer) - start_position; - buffer_write_int32_at_position( - buffer, length_location, (int32_t)length); - return 1; - } - case 17: - { - /* Timestamp */ - PyObject* obj; - unsigned long i; - - obj = PyObject_GetAttr(value, state->_inc_str); - if (!obj) { - return 0; - } - i = PyLong_AsUnsignedLong(obj); - Py_DECREF(obj); - if (i == (unsigned long)-1 && PyErr_Occurred()) { - return 0; - } - if (!buffer_write_int32(buffer, (int32_t)i)) { - return 0; - } - - obj = PyObject_GetAttr(value, state->_time_str); - if (!obj) { - return 0; - } - i = PyLong_AsUnsignedLong(obj); - Py_DECREF(obj); - if (i == (unsigned long)-1 && PyErr_Occurred()) { - return 0; - } - if (!buffer_write_int32(buffer, (int32_t)i)) { - return 0; - } - - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x11; - return 1; - } - case 18: - { - /* Int64 */ - const long long ll = PyLong_AsLongLong(value); - if (PyErr_Occurred()) { /* Overflow */ - PyErr_SetString(PyExc_OverflowError, - "MongoDB can only handle up to 8-byte ints"); - return 0; - } - if (!buffer_write_int64(buffer, (int64_t)ll)) { - return 0; - } - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x12; - return 1; - } - case 19: - { - /* Decimal128 */ - const char* data; - PyObject* pystring = PyObject_GetAttr(value, state->_bid_str); - if (!pystring) { - return 0; - } - data = PyBytes_AsString(pystring); - if (!data) { - Py_DECREF(pystring); - return 0; - } - if (!buffer_write_bytes(buffer, data, 16)) { - Py_DECREF(pystring); - return 0; - } - Py_DECREF(pystring); - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x13; - return 1; - } - case 100: - { - /* DBRef */ - PyObject* as_doc = PyObject_CallMethodObjArgs(value, state->_as_doc_str, NULL); - if (!as_doc) { - return 0; - } - if (!write_dict(self, buffer, as_doc, 0, options, 0)) { - Py_DECREF(as_doc); - return 0; - } - Py_DECREF(as_doc); - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; - return 1; - } - case 101: - { - /* RawBSONDocument */ - if (!write_raw_doc(buffer, value, state->_raw_str)) { - return 0; - } - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; - return 1; - } - case 255: - { - /* MinKey */ - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0xFF; - return 1; - } - case 127: - { - /* MaxKey */ - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x7F; - return 1; - } - } - - /* No _type_marker attribute or not one of our types. */ - - if (PyBool_Check(value)) { - const char c = (value == Py_True) ? 0x01 : 0x00; - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x08; - return buffer_write_bytes(buffer, &c, 1); - } - else if (PyLong_Check(value)) { - const long long long_long_value = PyLong_AsLongLong(value); - if (long_long_value == -1 && PyErr_Occurred()) { - /* Ignore error and give the fallback_encoder a chance. */ - PyErr_Clear(); - } else if (-2147483648LL <= long_long_value && long_long_value <= 2147483647LL) { - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x10; - return buffer_write_int32(buffer, (int32_t)long_long_value); - } else { - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x12; - return buffer_write_int64(buffer, (int64_t)long_long_value); - } - } else if (PyFloat_Check(value)) { - const double d = PyFloat_AsDouble(value); - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x01; - return buffer_write_double(buffer, d); - } else if (value == Py_None) { - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x0A; - return 1; - } else if (PyDict_Check(value)) { - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; - return write_dict(self, buffer, value, check_keys, options, 0); - } else if ((is_list = PyList_Check(value)) || PyTuple_Check(value)) { - Py_ssize_t items, i; - int start_position, - length_location, - length; - char zero = 0; - - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x04; - start_position = pymongo_buffer_get_position(buffer); - - /* save space for length */ - length_location = pymongo_buffer_save_space(buffer, 4); - if (length_location == -1) { - return 0; - } - if (is_list) { - items = PyList_Size(value); - } else { - items = PyTuple_Size(value); - } - if (items > BSON_MAX_SIZE) { - PyObject* BSONError = _error("BSONError"); - if (BSONError) { - PyErr_SetString(BSONError, - "Too many items to serialize."); - Py_DECREF(BSONError); - } - return 0; - } - for(i = 0; i < items; i++) { - int list_type_byte = pymongo_buffer_save_space(buffer, 1); - char name[BUF_SIZE]; - PyObject* item_value; - - if (list_type_byte == -1) { - return 0; - } - int res = LL2STR(name, (long long)i); - if (res == -1) { - return 0; - } - if (!buffer_write_bytes(buffer, name, (int)strlen(name) + 1)) { - return 0; - } - if (is_list) { - item_value = PyList_GET_ITEM(value, i); - } else { - item_value = PyTuple_GET_ITEM(value, i); - } - if (!item_value) { - return 0; - } - if (!write_element_to_buffer(self, buffer, list_type_byte, - item_value, check_keys, options, - 0, 0)) { - return 0; - } - } - - /* write null byte and fill in length */ - if (!buffer_write_bytes(buffer, &zero, 1)) { - return 0; - } - length = pymongo_buffer_get_position(buffer) - start_position; - buffer_write_int32_at_position( - buffer, length_location, (int32_t)length); - return 1; - /* Python3 special case. Store bytes as BSON binary subtype 0. */ - } else if (PyBytes_Check(value)) { - char subtype = 0; - int size; - const char* data = PyBytes_AS_STRING(value); - if (!data) - return 0; - if ((size = _downcast_and_check(PyBytes_GET_SIZE(value), 0)) == -1) - return 0; - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x05; - if (!buffer_write_int32(buffer, (int32_t)size)) { - return 0; - } - if (!buffer_write_bytes(buffer, &subtype, 1)) { - return 0; - } - if (!buffer_write_bytes(buffer, data, size)) { - return 0; - } - return 1; - } else if (PyUnicode_Check(value)) { - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x02; - return write_unicode(buffer, value); - } else if (PyDateTime_Check(value)) { - long long millis; - PyObject* utcoffset = PyObject_CallMethodObjArgs(value, state->_utcoffset_str , NULL); - if (utcoffset == NULL) - return 0; - if (utcoffset != Py_None) { - PyObject* result = PyNumber_Subtract(value, utcoffset); - if (!result) { - Py_DECREF(utcoffset); - return 0; - } - millis = millis_from_datetime(result); - Py_DECREF(result); - } else { - millis = millis_from_datetime(value); - } - Py_DECREF(utcoffset); - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x09; - return buffer_write_int64(buffer, (int64_t)millis); - } else if (PyObject_TypeCheck(value, state->REType)) { - return _write_regex_to_buffer(buffer, type_byte, value, state->_flags_str, state->_pattern_str); - } else if (PyObject_IsInstance(value, state->Mapping)) { - /* PyObject_IsInstance returns -1 on error */ - if (PyErr_Occurred()) { - return 0; - } - *(pymongo_buffer_get_buffer(buffer) + type_byte) = 0x03; - return write_dict(self, buffer, value, check_keys, options, 0); - } else if (PyObject_IsInstance(value, state->UUID)) { - PyObject* binary_value = NULL; - PyObject *uuid_rep_obj = NULL; - int result; - - /* PyObject_IsInstance returns -1 on error */ - if (PyErr_Occurred()) { - return 0; - } - - if (!(uuid_rep_obj = PyLong_FromLong(options->uuid_rep))) { - return 0; - } - binary_value = PyObject_CallMethodObjArgs(state->Binary, state->_from_uuid_str, value, uuid_rep_obj, NULL); - Py_DECREF(uuid_rep_obj); - - if (binary_value == NULL) { - return 0; - } - - result = _write_element_to_buffer(self, buffer, - type_byte, binary_value, - check_keys, options, - in_custom_call, - in_fallback_call); - Py_DECREF(binary_value); - return result; - } - - /* Try a custom encoder if one is provided and we have not already - * attempted to use a type encoder. */ - if (!in_custom_call && !options->type_registry.is_encoder_empty) { - PyObject* value_type = NULL; - PyObject* converter = NULL; - value_type = PyObject_Type(value); - if (value_type == NULL) { - return 0; - } - converter = PyDict_GetItem(options->type_registry.encoder_map, value_type); - Py_XDECREF(value_type); - if (converter != NULL) { - /* Transform types that have a registered converter. - * A new reference is created upon transformation. */ - new_value = PyObject_CallFunctionObjArgs(converter, value, NULL); - if (new_value == NULL) { - return 0; - } - retval = write_element_to_buffer(self, buffer, type_byte, new_value, - check_keys, options, 1, 0); - Py_XDECREF(new_value); - return retval; - } - } - - /* Try the fallback encoder if one is provided and we have not already - * attempted to use the fallback encoder. */ - if (!in_fallback_call && options->type_registry.has_fallback_encoder) { - new_value = PyObject_CallFunctionObjArgs( - options->type_registry.fallback_encoder, value, NULL); - if (new_value == NULL) { - // propagate any exception raised by the callback - return 0; - } - retval = write_element_to_buffer(self, buffer, type_byte, new_value, - check_keys, options, 0, 1); - Py_XDECREF(new_value); - return retval; - } - - /* We can't determine value's type. Fail. */ - _set_cannot_encode(value); - return 0; -} - -static int check_key_name(const char* name, int name_length) { - - if (name_length > 0 && name[0] == '$') { - PyObject* InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument) { - PyObject* errmsg = PyUnicode_FromFormat( - "key '%s' must not start with '$'", name); - if (errmsg) { - PyErr_SetObject(InvalidDocument, errmsg); - Py_DECREF(errmsg); - } - Py_DECREF(InvalidDocument); - } - return 0; - } - if (strchr(name, '.')) { - PyObject* InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument) { - PyObject* errmsg = PyUnicode_FromFormat( - "key '%s' must not contain '.'", name); - if (errmsg) { - PyErr_SetObject(InvalidDocument, errmsg); - Py_DECREF(errmsg); - } - Py_DECREF(InvalidDocument); - } - return 0; - } - return 1; -} - -/* Write a (key, value) pair to the buffer. - * - * Returns 0 on failure */ -int write_pair(PyObject* self, buffer_t buffer, const char* name, int name_length, - PyObject* value, unsigned char check_keys, - const codec_options_t* options, unsigned char allow_id) { - int type_byte; - - /* Don't write any _id elements unless we're explicitly told to - - * _id has to be written first so we do so, but don't bother - * deleting it from the dictionary being written. */ - if (!allow_id && strcmp(name, "_id") == 0) { - return 1; - } - - type_byte = pymongo_buffer_save_space(buffer, 1); - if (type_byte == -1) { - return 0; - } - if (check_keys && !check_key_name(name, name_length)) { - return 0; - } - if (!buffer_write_bytes(buffer, name, name_length + 1)) { - return 0; - } - if (!write_element_to_buffer(self, buffer, type_byte, - value, check_keys, options, 0, 0)) { - return 0; - } - return 1; -} - -int decode_and_write_pair(PyObject* self, buffer_t buffer, - PyObject* key, PyObject* value, - unsigned char check_keys, - const codec_options_t* options, - unsigned char top_level) { - PyObject* encoded; - const char* data; - int size; - if (PyUnicode_Check(key)) { - encoded = PyUnicode_AsUTF8String(key); - if (!encoded) { - return 0; - } - if (!(data = PyBytes_AS_STRING(encoded))) { - Py_DECREF(encoded); - return 0; - } - if ((size = _downcast_and_check(PyBytes_GET_SIZE(encoded), 1)) == -1) { - Py_DECREF(encoded); - return 0; - } - if (strlen(data) != (size_t)(size - 1)) { - PyObject* InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument) { - PyErr_SetString(InvalidDocument, - "Key names must not contain the NULL byte"); - Py_DECREF(InvalidDocument); - } - Py_DECREF(encoded); - return 0; - } - } else { - PyObject* InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument) { - PyObject* repr = PyObject_Repr(key); - if (repr) { - PyObject* errmsg = PyUnicode_FromString( - "documents must have only string keys, key was "); - if (errmsg) { - PyObject* error = PyUnicode_Concat(errmsg, repr); - if (error) { - PyErr_SetObject(InvalidDocument, error); - Py_DECREF(error); - } - Py_DECREF(errmsg); - Py_DECREF(repr); - } else { - Py_DECREF(repr); - } - } - Py_DECREF(InvalidDocument); - } - return 0; - } - - /* If top_level is True, don't allow writing _id here - it was already written. */ - if (!write_pair(self, buffer, data, - size - 1, value, check_keys, options, !top_level)) { - Py_DECREF(encoded); - return 0; - } - - Py_DECREF(encoded); - return 1; -} - - -/* Write a RawBSONDocument to the buffer. - * Returns the number of bytes written or 0 on failure. - */ -static int write_raw_doc(buffer_t buffer, PyObject* raw, PyObject* _raw_str) { - char* bytes; - Py_ssize_t len; - int len_int; - int bytes_written = 0; - PyObject* bytes_obj = NULL; - - bytes_obj = PyObject_GetAttr(raw, _raw_str); - if (!bytes_obj) { - goto fail; - } - - if (-1 == PyBytes_AsStringAndSize(bytes_obj, &bytes, &len)) { - goto fail; - } - len_int = _downcast_and_check(len, 0); - if (-1 == len_int) { - goto fail; - } - if (!buffer_write_bytes(buffer, bytes, len_int)) { - goto fail; - } - bytes_written = len_int; -fail: - Py_XDECREF(bytes_obj); - return bytes_written; -} - - -/* Update Invalid Document error message to include doc. - */ -void handle_invalid_doc_error(PyObject* dict) { - PyObject *etype = NULL, *evalue = NULL, *etrace = NULL; - PyObject *msg = NULL, *dict_str = NULL, *new_msg = NULL; - PyErr_Fetch(&etype, &evalue, &etrace); - PyObject *InvalidDocument = _error("InvalidDocument"); - if (InvalidDocument == NULL) { - goto cleanup; - } - - if (evalue && PyErr_GivenExceptionMatches(etype, InvalidDocument)) { - PyObject *msg = PyObject_Str(evalue); - if (msg) { - // Prepend doc to the existing message - PyObject *dict_str = PyObject_Str(dict); - if (dict_str == NULL) { - goto cleanup; - } - const char * dict_str_utf8 = PyUnicode_AsUTF8(dict_str); - if (dict_str_utf8 == NULL) { - goto cleanup; - } - const char * msg_utf8 = PyUnicode_AsUTF8(msg); - if (msg_utf8 == NULL) { - goto cleanup; - } - PyObject *new_msg = PyUnicode_FromFormat("Invalid document %s | %s", dict_str_utf8, msg_utf8); - Py_DECREF(evalue); - Py_DECREF(etype); - etype = InvalidDocument; - InvalidDocument = NULL; - if (new_msg) { - evalue = new_msg; - } else { - evalue = msg; - } - } - PyErr_NormalizeException(&etype, &evalue, &etrace); - } -cleanup: - PyErr_Restore(etype, evalue, etrace); - Py_XDECREF(msg); - Py_XDECREF(InvalidDocument); - Py_XDECREF(dict_str); - Py_XDECREF(new_msg); -} - - -/* returns the number of bytes written or 0 on failure */ -int write_dict(PyObject* self, buffer_t buffer, - PyObject* dict, unsigned char check_keys, - const codec_options_t* options, unsigned char top_level) { - PyObject* key; - PyObject* iter; - char zero = 0; - int length; - int length_location; - struct module_state *state = GETSTATE(self); - long type_marker; - int is_dict = PyDict_Check(dict); - if (!state) { - return 0; - } - - if (!is_dict) { - /* check for RawBSONDocument */ - type_marker = _type_marker(dict, state->_type_marker_str); - if (type_marker < 0) { - return 0; - } - - if (101 == type_marker) { - return write_raw_doc(buffer, dict, state->_raw_str); - } - - if (!PyObject_IsInstance(dict, state->Mapping)) { - PyObject* repr; - if ((repr = PyObject_Repr(dict))) { - PyObject* errmsg = PyUnicode_FromString( - "encoder expected a mapping type but got: "); - if (errmsg) { - PyObject* error = PyUnicode_Concat(errmsg, repr); - if (error) { - PyErr_SetObject(PyExc_TypeError, error); - Py_DECREF(error); - } - Py_DECREF(errmsg); - Py_DECREF(repr); - } - else { - Py_DECREF(repr); - } - } else { - PyErr_SetString(PyExc_TypeError, - "encoder expected a mapping type"); - } - - return 0; - } - /* PyObject_IsInstance returns -1 on error */ - if (PyErr_Occurred()) { - return 0; - } - } - - length_location = pymongo_buffer_save_space(buffer, 4); - if (length_location == -1) { - return 0; - } - - /* Write _id first if this is a top level doc. */ - if (top_level) { - /* - * If "dict" is a defaultdict we don't want to call - * PyObject_GetItem on it. That would **create** - * an _id where one didn't previously exist (PYTHON-871). - */ - if (is_dict) { - /* PyDict_GetItem returns a borrowed reference. */ - PyObject* _id = PyDict_GetItem(dict, state->_id_str); - if (_id) { - if (!write_pair(self, buffer, "_id", 3, - _id, check_keys, options, 1)) { - return 0; - } - } - } else if (PyMapping_HasKey(dict, state->_id_str)) { - PyObject* _id = PyObject_GetItem(dict, state->_id_str); - if (!_id) { - return 0; - } - if (!write_pair(self, buffer, "_id", 3, - _id, check_keys, options, 1)) { - Py_DECREF(_id); - return 0; - } - /* PyObject_GetItem returns a new reference. */ - Py_DECREF(_id); - } - } - - if (is_dict) { - PyObject* value; - Py_ssize_t pos = 0; - while (PyDict_Next(dict, &pos, &key, &value)) { - if (!decode_and_write_pair(self, buffer, key, value, - check_keys, options, top_level)) { - if (PyErr_Occurred() && top_level) { - handle_invalid_doc_error(dict); - } - return 0; - } - } - } else { - iter = PyObject_GetIter(dict); - if (iter == NULL) { - return 0; - } - while ((key = PyIter_Next(iter)) != NULL) { - PyObject* value = PyObject_GetItem(dict, key); - if (!value) { - PyErr_SetObject(PyExc_KeyError, key); - Py_DECREF(key); - Py_DECREF(iter); - return 0; - } - if (!decode_and_write_pair(self, buffer, key, value, - check_keys, options, top_level)) { - if (PyErr_Occurred() && top_level) { - handle_invalid_doc_error(dict); - } - Py_DECREF(key); - Py_DECREF(value); - Py_DECREF(iter); - return 0; - } - Py_DECREF(key); - Py_DECREF(value); - } - Py_DECREF(iter); - if (PyErr_Occurred()) { - return 0; - } - } - - /* write null byte and fill in length */ - if (!buffer_write_bytes(buffer, &zero, 1)) { - return 0; - } - length = pymongo_buffer_get_position(buffer) - length_location; - buffer_write_int32_at_position( - buffer, length_location, (int32_t)length); - return length; -} - -static PyObject* _cbson_dict_to_bson(PyObject* self, PyObject* args) { - PyObject* dict; - PyObject* result; - unsigned char check_keys; - unsigned char top_level = 1; - PyObject* options_obj = NULL; - codec_options_t options; - buffer_t buffer; - PyObject* raw_bson_document_bytes_obj; - long type_marker; - struct module_state *state = GETSTATE(self); - if (!state) { - return NULL; - } - - if (!(PyArg_ParseTuple(args, "ObO|b", &dict, &check_keys, - &options_obj, &top_level) && - convert_codec_options(self, options_obj, &options))) { - return NULL; - } - - /* check for RawBSONDocument */ - type_marker = _type_marker(dict, state->_type_marker_str); - if (type_marker < 0) { - destroy_codec_options(&options); - return NULL; - } else if (101 == type_marker) { - destroy_codec_options(&options); - raw_bson_document_bytes_obj = PyObject_GetAttr(dict, state->_raw_str); - if (NULL == raw_bson_document_bytes_obj) { - return NULL; - } - return raw_bson_document_bytes_obj; - } - - buffer = pymongo_buffer_new(); - if (!buffer) { - destroy_codec_options(&options); - return NULL; - } - - if (!write_dict(self, buffer, dict, check_keys, &options, top_level)) { - destroy_codec_options(&options); - pymongo_buffer_free(buffer); - return NULL; - } - - /* objectify buffer */ - result = Py_BuildValue("y#", pymongo_buffer_get_buffer(buffer), - (Py_ssize_t)pymongo_buffer_get_position(buffer)); - destroy_codec_options(&options); - pymongo_buffer_free(buffer); - return result; -} - -/* - * Hook for optional decoding BSON documents to DBRef. - */ -static PyObject *_dbref_hook(PyObject* self, PyObject* value) { - struct module_state *state = GETSTATE(self); - PyObject* ref = NULL; - PyObject* id = NULL; - PyObject* database = NULL; - PyObject* ret = NULL; - int db_present = 0; - if (!state) { - return NULL; - } - - /* Decoding for DBRefs */ - if (PyMapping_HasKey(value, state->_dollar_ref_str) && PyMapping_HasKey(value, state->_dollar_id_str)) { /* DBRef */ - ref = PyObject_GetItem(value, state->_dollar_ref_str); - /* PyObject_GetItem returns NULL to indicate error. */ - if (!ref) { - goto invalid; - } - id = PyObject_GetItem(value, state->_dollar_id_str); - /* PyObject_GetItem returns NULL to indicate error. */ - if (!id) { - goto invalid; - } - - if (PyMapping_HasKey(value, state->_dollar_db_str)) { - database = PyObject_GetItem(value, state->_dollar_db_str); - if (!database) { - goto invalid; - } - db_present = 1; - } else { - database = Py_None; - Py_INCREF(database); - } - - // check types - if (!(PyUnicode_Check(ref) && (database == Py_None || PyUnicode_Check(database)))) { - ret = value; - goto invalid; - } - - PyMapping_DelItem(value, state->_dollar_ref_str); - PyMapping_DelItem(value, state->_dollar_id_str); - if (db_present) { - PyMapping_DelItem(value, state->_dollar_db_str); - } - - ret = PyObject_CallFunctionObjArgs(state->DBRef, ref, id, database, value, NULL); - Py_DECREF(value); - } else { - ret = value; - } -invalid: - Py_XDECREF(ref); - Py_XDECREF(id); - Py_XDECREF(database); - return ret; -} - -static PyObject* get_value(PyObject* self, PyObject* name, const char* buffer, - unsigned* position, unsigned char type, - unsigned max, const codec_options_t* options, int raw_array) { - struct module_state *state = GETSTATE(self); - PyObject* value = NULL; - if (!state) { - return NULL; - } - switch (type) { - case 1: - { - double d; - if (max < 8) { - goto invalid; - } - memcpy(&d, buffer + *position, 8); - value = PyFloat_FromDouble(BSON_DOUBLE_FROM_LE(d)); - *position += 8; - break; - } - case 2: - case 14: - { - uint32_t value_length; - if (max < 4) { - goto invalid; - } - memcpy(&value_length, buffer + *position, 4); - value_length = BSON_UINT32_FROM_LE(value_length); - /* Encoded string length + string */ - if (!value_length || max < value_length || max < 4 + value_length) { - goto invalid; - } - *position += 4; - /* Strings must end in \0 */ - if (buffer[*position + value_length - 1]) { - goto invalid; - } - value = PyUnicode_DecodeUTF8( - buffer + *position, value_length - 1, - options->unicode_decode_error_handler); - if (!value) { - goto invalid; - } - *position += value_length; - break; - } - case 3: - { - uint32_t size; - - if (max < 4) { - goto invalid; - } - memcpy(&size, buffer + *position, 4); - size = BSON_UINT32_FROM_LE(size); - if (size < BSON_MIN_SIZE || max < size) { - goto invalid; - } - /* Check for bad eoo */ - if (buffer[*position + size - 1]) { - goto invalid; - } - - value = elements_to_dict(self, buffer + *position, - size, options); - if (!value) { - goto invalid; - } - - if (options->is_raw_bson) { - *position += size; - break; - } - - /* Hook for DBRefs */ - value = _dbref_hook(self, value); - if (!value) { - goto invalid; - } - - *position += size; - break; - } - case 4: - { - uint32_t size, end; - - if (max < 4) { - goto invalid; - } - memcpy(&size, buffer + *position, 4); - size = BSON_UINT32_FROM_LE(size); - if (size < BSON_MIN_SIZE || max < size) { - goto invalid; - } - - end = *position + size - 1; - /* Check for bad eoo */ - if (buffer[end]) { - goto invalid; - } - - if (raw_array != 0) { - // Treat it as a binary buffer. - value = PyBytes_FromStringAndSize(buffer + *position, size); - *position += size; - break; - } - - *position += 4; - - value = PyList_New(0); - if (!value) { - goto invalid; - } - while (*position < end) { - PyObject* to_append; - - unsigned char bson_type = (unsigned char)buffer[(*position)++]; - - size_t key_size = strlen(buffer + *position); - if (max < key_size) { - Py_DECREF(value); - goto invalid; - } - /* just skip the key, they're in order. */ - *position += (unsigned)key_size + 1; - if (Py_EnterRecursiveCall(" while decoding a list value")) { - Py_DECREF(value); - goto invalid; - } - to_append = get_value(self, name, buffer, position, bson_type, - max - (unsigned)key_size, options, raw_array); - Py_LeaveRecursiveCall(); - if (!to_append) { - Py_DECREF(value); - goto invalid; - } - if (PyList_Append(value, to_append) < 0) { - Py_DECREF(value); - Py_DECREF(to_append); - goto invalid; - } - Py_DECREF(to_append); - } - if (*position != end) { - goto invalid; - } - (*position)++; - break; - } - case 5: - { - PyObject* data; - PyObject* st; - uint32_t length, length2; - unsigned char subtype; - - if (max < 5) { - goto invalid; - } - memcpy(&length, buffer + *position, 4); - length = BSON_UINT32_FROM_LE(length); - if (max < length) { - goto invalid; - } - - subtype = (unsigned char)buffer[*position + 4]; - *position += 5; - if (subtype == 2) { - if (length < 4) { - goto invalid; - } - memcpy(&length2, buffer + *position, 4); - length2 = BSON_UINT32_FROM_LE(length2); - if (length2 != length - 4) { - goto invalid; - } - } - /* Python3 special case. Decode BSON binary subtype 0 to bytes. */ - if (subtype == 0) { - value = PyBytes_FromStringAndSize(buffer + *position, length); - *position += length; - break; - } - if (subtype == 2) { - data = PyBytes_FromStringAndSize(buffer + *position + 4, length - 4); - } else { - data = PyBytes_FromStringAndSize(buffer + *position, length); - } - if (!data) { - goto invalid; - } - /* Encode as UUID or Binary based on options->uuid_rep */ - if (subtype == 3 || subtype == 4) { - PyObject* binary_value = NULL; - char uuid_rep = options->uuid_rep; - - /* UUID should always be 16 bytes */ - if (length != 16) { - goto uuiderror; - } - - binary_value = PyObject_CallFunction(state->Binary, "(Oi)", data, subtype); - if (binary_value == NULL) { - goto uuiderror; - } - - if ((uuid_rep == UNSPECIFIED) || - (subtype == 4 && uuid_rep != STANDARD) || - (subtype == 3 && uuid_rep == STANDARD)) { - value = binary_value; - Py_INCREF(value); - } else { - PyObject *uuid_rep_obj = PyLong_FromLong(uuid_rep); - if (!uuid_rep_obj) { - goto uuiderror; - } - value = PyObject_CallMethodObjArgs(binary_value, state->_as_uuid_str, uuid_rep_obj, NULL); - Py_DECREF(uuid_rep_obj); - } - - uuiderror: - Py_XDECREF(binary_value); - Py_DECREF(data); - if (!value) { - goto invalid; - } - *position += length; - break; - } - - st = PyLong_FromLong(subtype); - if (!st) { - Py_DECREF(data); - goto invalid; - } - value = PyObject_CallFunctionObjArgs(state->Binary, data, st, NULL); - Py_DECREF(st); - Py_DECREF(data); - if (!value) { - goto invalid; - } - *position += length; - break; - } - case 6: - case 10: - { - value = Py_None; - Py_INCREF(value); - break; - } - case 7: - { - if (max < 12) { - goto invalid; - } - value = PyObject_CallFunction(state->ObjectId, "y#", buffer + *position, (Py_ssize_t)12); - *position += 12; - break; - } - case 8: - { - char boolean_raw = buffer[(*position)++]; - if (0 == boolean_raw) { - value = Py_False; - } else if (1 == boolean_raw) { - value = Py_True; - } else { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_Format(InvalidBSON, "invalid boolean value: %x", boolean_raw); - Py_DECREF(InvalidBSON); - } - return NULL; - } - Py_INCREF(value); - break; - } - case 9: - { - int64_t millis; - if (max < 8) { - goto invalid; - } - memcpy(&millis, buffer + *position, 8); - millis = (int64_t)BSON_UINT64_FROM_LE(millis); - *position += 8; - - value = decode_datetime(self, millis, options); - break; - } - case 11: - { - PyObject* pattern; - int flags; - size_t flags_length, i; - size_t pattern_length = strlen(buffer + *position); - if (pattern_length > BSON_MAX_SIZE || max < pattern_length) { - goto invalid; - } - pattern = PyUnicode_DecodeUTF8( - buffer + *position, pattern_length, - options->unicode_decode_error_handler); - if (!pattern) { - goto invalid; - } - *position += (unsigned)pattern_length + 1; - flags_length = strlen(buffer + *position); - if (flags_length > BSON_MAX_SIZE || - (BSON_MAX_SIZE - pattern_length) < flags_length) { - Py_DECREF(pattern); - goto invalid; - } - if (max < pattern_length + flags_length) { - Py_DECREF(pattern); - goto invalid; - } - flags = 0; - for (i = 0; i < flags_length; i++) { - if (buffer[*position + i] == 'i') { - flags |= 2; - } else if (buffer[*position + i] == 'l') { - flags |= 4; - } else if (buffer[*position + i] == 'm') { - flags |= 8; - } else if (buffer[*position + i] == 's') { - flags |= 16; - } else if (buffer[*position + i] == 'u') { - flags |= 32; - } else if (buffer[*position + i] == 'x') { - flags |= 64; - } - } - *position += (unsigned)flags_length + 1; - - value = PyObject_CallFunction(state->Regex, "Oi", pattern, flags); - Py_DECREF(pattern); - break; - } - case 12: - { - uint32_t coll_length; - PyObject* collection; - PyObject* id = NULL; - - if (max < 4) { - goto invalid; - } - memcpy(&coll_length, buffer + *position, 4); - coll_length = BSON_UINT32_FROM_LE(coll_length); - /* Encoded string length + string + 12 byte ObjectId */ - if (!coll_length || max < coll_length || max < 4 + coll_length + 12) { - goto invalid; - } - *position += 4; - /* Strings must end in \0 */ - if (buffer[*position + coll_length - 1]) { - goto invalid; - } - - collection = PyUnicode_DecodeUTF8( - buffer + *position, coll_length - 1, - options->unicode_decode_error_handler); - if (!collection) { - goto invalid; - } - *position += coll_length; - - id = PyObject_CallFunction(state->ObjectId, "y#", buffer + *position, (Py_ssize_t)12); - if (!id) { - Py_DECREF(collection); - goto invalid; - } - *position += 12; - value = PyObject_CallFunctionObjArgs(state->DBRef, collection, id, NULL); - Py_DECREF(collection); - Py_DECREF(id); - break; - } - case 13: - { - PyObject* code; - uint32_t value_length; - if (max < 4) { - goto invalid; - } - memcpy(&value_length, buffer + *position, 4); - value_length = BSON_UINT32_FROM_LE(value_length); - /* Encoded string length + string */ - if (!value_length || max < value_length || max < 4 + value_length) { - goto invalid; - } - *position += 4; - /* Strings must end in \0 */ - if (buffer[*position + value_length - 1]) { - goto invalid; - } - code = PyUnicode_DecodeUTF8( - buffer + *position, value_length - 1, - options->unicode_decode_error_handler); - if (!code) { - goto invalid; - } - *position += value_length; - value = PyObject_CallFunctionObjArgs(state->Code, code, NULL, NULL); - Py_DECREF(code); - break; - } - case 15: - { - uint32_t c_w_s_size; - uint32_t code_size; - uint32_t scope_size; - uint32_t len; - PyObject* code; - PyObject* scope; - - if (max < 8) { - goto invalid; - } - - memcpy(&c_w_s_size, buffer + *position, 4); - c_w_s_size = BSON_UINT32_FROM_LE(c_w_s_size); - *position += 4; - - if (max < c_w_s_size) { - goto invalid; - } - - memcpy(&code_size, buffer + *position, 4); - code_size = BSON_UINT32_FROM_LE(code_size); - /* code_w_scope length + code length + code + scope length */ - len = 4 + 4 + code_size + 4; - if (!code_size || max < code_size || max < len || len < code_size) { - goto invalid; - } - *position += 4; - /* Strings must end in \0 */ - if (buffer[*position + code_size - 1]) { - goto invalid; - } - code = PyUnicode_DecodeUTF8( - buffer + *position, code_size - 1, - options->unicode_decode_error_handler); - if (!code) { - goto invalid; - } - *position += code_size; - - memcpy(&scope_size, buffer + *position, 4); - scope_size = BSON_UINT32_FROM_LE(scope_size); - /* code length + code + scope length + scope */ - len = 4 + 4 + code_size + scope_size; - if (scope_size < BSON_MIN_SIZE || len != c_w_s_size || len < scope_size) { - Py_DECREF(code); - goto invalid; - } - - /* Check for bad eoo */ - if (buffer[*position + scope_size - 1]) { - goto invalid; - } - scope = elements_to_dict(self, buffer + *position, - scope_size, options); - if (!scope) { - Py_DECREF(code); - goto invalid; - } - *position += scope_size; - - value = PyObject_CallFunctionObjArgs(state->Code, code, scope, NULL); - Py_DECREF(code); - Py_DECREF(scope); - break; - } - case 16: - { - int32_t i; - if (max < 4) { - goto invalid; - } - memcpy(&i, buffer + *position, 4); - i = (int32_t)BSON_UINT32_FROM_LE(i); - value = PyLong_FromLong(i); - if (!value) { - goto invalid; - } - *position += 4; - break; - } - case 17: - { - uint32_t time, inc; - if (max < 8) { - goto invalid; - } - memcpy(&inc, buffer + *position, 4); - memcpy(&time, buffer + *position + 4, 4); - inc = BSON_UINT32_FROM_LE(inc); - time = BSON_UINT32_FROM_LE(time); - value = PyObject_CallFunction(state->Timestamp, "II", time, inc); - *position += 8; - break; - } - case 18: - { - int64_t ll; - if (max < 8) { - goto invalid; - } - memcpy(&ll, buffer + *position, 8); - ll = (int64_t)BSON_UINT64_FROM_LE(ll); - value = PyObject_CallFunction(state->BSONInt64, "L", ll); - *position += 8; - break; - } - case 19: - { - if (max < 16) { - goto invalid; - } - PyObject *_bytes_obj = PyBytes_FromStringAndSize(buffer + *position, (Py_ssize_t)16); - if (!_bytes_obj) { - goto invalid; - } - value = PyObject_CallMethodObjArgs(state->Decimal128, state->_from_bid_str, _bytes_obj, NULL); - Py_DECREF(_bytes_obj); - *position += 16; - break; - } - case 255: - { - value = PyObject_CallFunctionObjArgs(state->MinKey, NULL); - break; - } - case 127: - { - value = PyObject_CallFunctionObjArgs(state->MaxKey, NULL); - break; - } - default: - { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyObject* bobj = PyBytes_FromFormat("%c", type); - if (bobj) { - PyObject* repr = PyObject_Repr(bobj); - Py_DECREF(bobj); - /* - * See http://bugs.python.org/issue22023 for why we can't - * just use PyUnicode_FromFormat with %S or %R to do this - * work. - */ - if (repr) { - PyObject* left = PyUnicode_FromString( - "Detected unknown BSON type "); - if (left) { - PyObject* lmsg = PyUnicode_Concat(left, repr); - Py_DECREF(left); - if (lmsg) { - PyObject* errmsg = PyUnicode_FromFormat( - "%U for fieldname '%U'. Are you using the " - "latest driver version?", lmsg, name); - if (errmsg) { - PyErr_SetObject(InvalidBSON, errmsg); - Py_DECREF(errmsg); - } - Py_DECREF(lmsg); - } - } - Py_DECREF(repr); - } - } - Py_DECREF(InvalidBSON); - } - goto invalid; - } - } - - if (value) { - if (!options->type_registry.is_decoder_empty) { - PyObject* value_type = NULL; - PyObject* converter = NULL; - value_type = PyObject_Type(value); - if (value_type == NULL) { - goto invalid; - } - converter = PyDict_GetItem(options->type_registry.decoder_map, value_type); - if (converter != NULL) { - PyObject* new_value = PyObject_CallFunctionObjArgs(converter, value, NULL); - Py_DECREF(value_type); - Py_DECREF(value); - return new_value; - } else { - Py_DECREF(value_type); - return value; - } - } - return value; - } - - invalid: - - /* - * Wrap any non-InvalidBSON errors in InvalidBSON. - */ - if (PyErr_Occurred()) { - PyObject *etype = NULL, *evalue = NULL, *etrace = NULL; - PyObject *InvalidBSON = NULL; - - /* - * Calling _error clears the error state, so fetch it first. - */ - PyErr_Fetch(&etype, &evalue, &etrace); - - /* Dont reraise anything but PyExc_Exceptions as InvalidBSON. */ - if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) { - InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - if (!PyErr_GivenExceptionMatches(etype, InvalidBSON)) { - /* - * Raise InvalidBSON(str(e)). - */ - Py_DECREF(etype); - etype = InvalidBSON; - - if (evalue) { - PyObject *msg = PyObject_Str(evalue); - Py_DECREF(evalue); - evalue = msg; - } - PyErr_NormalizeException(&etype, &evalue, &etrace); - } else { - /* - * The current exception matches InvalidBSON, so we don't - * need this reference after all. - */ - Py_DECREF(InvalidBSON); - } - } - } - /* Steals references to args. */ - PyErr_Restore(etype, evalue, etrace); - } else { - PyObject *InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "invalid length or type code"); - Py_DECREF(InvalidBSON); - } - } - return NULL; -} - -/* - * Get the next 'name' and 'value' from a document in a string, whose position - * is provided. - * - * Returns the position of the next element in the document, or -1 on error. - */ -static int _element_to_dict(PyObject* self, const char* string, - unsigned position, unsigned max, - const codec_options_t* options, - int raw_array, - PyObject** name, PyObject** value) { - unsigned char type = (unsigned char)string[position++]; - size_t name_length = strlen(string + position); - if (name_length > BSON_MAX_SIZE || position + name_length >= max) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "field name too large"); - Py_DECREF(InvalidBSON); - } - return -1; - } - *name = PyUnicode_DecodeUTF8( - string + position, name_length, - options->unicode_decode_error_handler); - if (!*name) { - /* If NULL is returned then wrap the UnicodeDecodeError - in an InvalidBSON error */ - PyObject *etype = NULL, *evalue = NULL, *etrace = NULL; - PyObject *InvalidBSON = NULL; - - PyErr_Fetch(&etype, &evalue, &etrace); - if (PyErr_GivenExceptionMatches(etype, PyExc_Exception)) { - InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - Py_DECREF(etype); - etype = InvalidBSON; - - if (evalue) { - PyObject *msg = PyObject_Str(evalue); - Py_DECREF(evalue); - evalue = msg; - } - PyErr_NormalizeException(&etype, &evalue, &etrace); - } - } - PyErr_Restore(etype, evalue, etrace); - return -1; - } - position += (unsigned)name_length + 1; - *value = get_value(self, *name, string, &position, type, - max - position, options, raw_array); - if (!*value) { - Py_DECREF(*name); - return -1; - } - return position; -} - -static PyObject* _cbson_element_to_dict(PyObject* self, PyObject* args) { - /* TODO: Support buffer protocol */ - char* string; - PyObject* bson; - PyObject* options_obj = NULL; - codec_options_t options; - unsigned position; - unsigned max; - int new_position; - int raw_array = 0; - PyObject* name; - PyObject* value; - PyObject* result_tuple; - - if (!(PyArg_ParseTuple(args, "OIIOp", &bson, &position, &max, - &options_obj, &raw_array) && - convert_codec_options(self, options_obj, &options))) { - return NULL; - } - - if (!PyBytes_Check(bson)) { - PyErr_SetString(PyExc_TypeError, "argument to _element_to_dict must be a bytes object"); - return NULL; - } - string = PyBytes_AS_STRING(bson); - - new_position = _element_to_dict(self, string, position, max, &options, raw_array, &name, &value); - if (new_position < 0) { - return NULL; - } - - result_tuple = Py_BuildValue("NNi", name, value, new_position); - if (!result_tuple) { - Py_DECREF(name); - Py_DECREF(value); - return NULL; - } - - destroy_codec_options(&options); - return result_tuple; -} - -static PyObject* _elements_to_dict(PyObject* self, const char* string, - unsigned max, - const codec_options_t* options) { - unsigned position = 0; - PyObject* dict = PyObject_CallObject(options->document_class, NULL); - if (!dict) { - return NULL; - } - int raw_array = 0; - while (position < max) { - PyObject* name = NULL; - PyObject* value = NULL; - int new_position; - - new_position = _element_to_dict( - self, string, position, max, options, raw_array, &name, &value); - if (new_position < 0) { - Py_DECREF(dict); - return NULL; - } else { - position = (unsigned)new_position; - } - - PyObject_SetItem(dict, name, value); - Py_DECREF(name); - Py_DECREF(value); - } - return dict; -} - -static PyObject* elements_to_dict(PyObject* self, const char* string, - unsigned max, - const codec_options_t* options) { - PyObject* result; - if (options->is_raw_bson) { - return PyObject_CallFunction( - options->document_class, "y#O", - string, max, options->options_obj); - } - if (Py_EnterRecursiveCall(" while decoding a BSON document")) - return NULL; - result = _elements_to_dict(self, string + 4, max - 5, options); - Py_LeaveRecursiveCall(); - return result; -} - -static int _get_buffer(PyObject *exporter, Py_buffer *view) { - if (PyObject_GetBuffer(exporter, view, PyBUF_SIMPLE) == -1) { - return 0; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - PyErr_SetString(PyExc_ValueError, - "must be a contiguous buffer"); - goto fail; - } - if (!view->buf || view->len < 0) { - PyErr_SetString(PyExc_ValueError, "invalid buffer"); - goto fail; - } - if (view->itemsize != 1) { - PyErr_SetString(PyExc_ValueError, - "buffer data must be ascii or utf8"); - goto fail; - } - return 1; -fail: - PyBuffer_Release(view); - return 0; -} - -static PyObject* _cbson_bson_to_dict(PyObject* self, PyObject* args) { - int32_t size; - Py_ssize_t total_size; - const char* string; - PyObject* bson = NULL; - codec_options_t options; - PyObject* result = NULL; - PyObject* options_obj; - Py_buffer view = {0}; - - if (! (PyArg_ParseTuple(args, "OO", &bson, &options_obj) && - convert_codec_options(self, options_obj, &options))) { - return result; - } - - if (!_get_buffer(bson, &view)) { - destroy_codec_options(&options); - return result; - } - - total_size = view.len; - - if (total_size < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, - "not enough data for a BSON document"); - Py_DECREF(InvalidBSON); - } - goto done;; - } - - string = (char*)view.buf; - memcpy(&size, string, 4); - size = (int32_t)BSON_UINT32_FROM_LE(size); - if (size < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "invalid message size"); - Py_DECREF(InvalidBSON); - } - goto done; - } - - if (total_size < size || total_size > BSON_MAX_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "objsize too large"); - Py_DECREF(InvalidBSON); - } - goto done; - } - - if (size != total_size || string[size - 1]) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "bad eoo"); - Py_DECREF(InvalidBSON); - } - goto done; - } - - result = elements_to_dict(self, string, (unsigned)size, &options); -done: - PyBuffer_Release(&view); - destroy_codec_options(&options); - return result; -} - -static PyObject* _cbson_decode_all(PyObject* self, PyObject* args) { - int32_t size; - Py_ssize_t total_size; - const char* string; - PyObject* bson; - PyObject* dict; - PyObject* result = NULL; - codec_options_t options; - PyObject* options_obj = NULL; - Py_buffer view = {0}; - - if (!(PyArg_ParseTuple(args, "OO", &bson, &options_obj) && - convert_codec_options(self, options_obj, &options))) { - return NULL; - } - - if (!_get_buffer(bson, &view)) { - destroy_codec_options(&options); - return NULL; - } - total_size = view.len; - string = (char*)view.buf; - - if (!(result = PyList_New(0))) { - goto fail; - } - - while (total_size > 0) { - if (total_size < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, - "not enough data for a BSON document"); - Py_DECREF(InvalidBSON); - } - Py_DECREF(result); - goto fail; - } - - memcpy(&size, string, 4); - size = (int32_t)BSON_UINT32_FROM_LE(size); - if (size < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "invalid message size"); - Py_DECREF(InvalidBSON); - } - Py_DECREF(result); - goto fail; - } - - if (total_size < size) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "objsize too large"); - Py_DECREF(InvalidBSON); - } - Py_DECREF(result); - goto fail; - } - - if (string[size - 1]) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "bad eoo"); - Py_DECREF(InvalidBSON); - } - Py_DECREF(result); - goto fail; - } - - dict = elements_to_dict(self, string, (unsigned)size, &options); - if (!dict) { - Py_DECREF(result); - goto fail; - } - if (PyList_Append(result, dict) < 0) { - Py_DECREF(dict); - Py_DECREF(result); - goto fail; - } - Py_DECREF(dict); - string += size; - total_size -= size; - } - goto done; -fail: - result = NULL; -done: - PyBuffer_Release(&view); - destroy_codec_options(&options); - return result; -} - - -static PyObject* _cbson_array_of_documents_to_buffer(PyObject* self, PyObject* args) { - uint32_t size; - uint32_t value_length; - uint32_t position = 0; - buffer_t buffer; - const char* string; - PyObject* arr; - PyObject* result = NULL; - Py_buffer view = {0}; - - if (!PyArg_ParseTuple(args, "O", &arr)) { - return NULL; - } - - if (!_get_buffer(arr, &view)) { - return NULL; - } - - buffer = pymongo_buffer_new(); - if (!buffer) { - PyBuffer_Release(&view); - return NULL; - } - - string = (char*)view.buf; - - if (view.len < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, - "not enough data for a BSON document"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - memcpy(&size, string, 4); - size = BSON_UINT32_FROM_LE(size); - - /* validate the size of the array */ - if (view.len != (int32_t)size || (int32_t)size < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "objsize too large"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - if (string[size - 1]) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "bad eoo"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - /* save space for length */ - if (pymongo_buffer_save_space(buffer, size) == -1) { - goto fail; - } - pymongo_buffer_update_position(buffer, 0); - - position += 4; - while (position < size - 1) { - // Verify the value is an object. - unsigned char type = (unsigned char)string[position]; - if (type != 3) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "array element was not an object"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - // Just skip the keys. - position = position + strlen(string + position) + 1; - - if (position >= size || (size - position) < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "invalid array content"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - memcpy(&value_length, string + position, 4); - value_length = BSON_UINT32_FROM_LE(value_length); - if (value_length < BSON_MIN_SIZE) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, "invalid message size"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - if (pymongo_buffer_write(buffer, string + position, value_length) == 1) { - goto fail; - } - position += value_length; - } - - if (position != size - 1) { - PyObject* InvalidBSON = _error("InvalidBSON"); - if (InvalidBSON) { - PyErr_SetString(InvalidBSON, - "bad object or element length"); - Py_DECREF(InvalidBSON); - } - goto fail; - } - - /* objectify buffer */ - result = Py_BuildValue("y#", pymongo_buffer_get_buffer(buffer), - (Py_ssize_t)pymongo_buffer_get_position(buffer)); - goto done; -fail: - result = NULL; -done: - PyBuffer_Release(&view); - pymongo_buffer_free(buffer); - return result; -} - - -static PyMethodDef _CBSONMethods[] = { - {"_dict_to_bson", _cbson_dict_to_bson, METH_VARARGS, - "convert a dictionary to a string containing its BSON representation."}, - {"_bson_to_dict", _cbson_bson_to_dict, METH_VARARGS, - "convert a BSON string to a SON object."}, - {"_decode_all", _cbson_decode_all, METH_VARARGS, - "convert binary data to a sequence of documents."}, - {"_element_to_dict", _cbson_element_to_dict, METH_VARARGS, - "Decode a single key, value pair."}, - {"_array_of_documents_to_buffer", _cbson_array_of_documents_to_buffer, METH_VARARGS, "Convert raw array of documents to a stream of BSON documents"}, - {"_test_long_long_to_str", _test_long_long_to_str, METH_VARARGS, "Test conversion of extreme and common Py_ssize_t values to str."}, - {NULL, NULL, 0, NULL} -}; - -#define INITERROR return -1; -static int _cbson_traverse(PyObject *m, visitproc visit, void *arg) { - struct module_state *state = GETSTATE(m); - if (!state) { - return 0; - } - Py_VISIT(state->Binary); - Py_VISIT(state->Code); - Py_VISIT(state->ObjectId); - Py_VISIT(state->DBRef); - Py_VISIT(state->Regex); - Py_VISIT(state->UUID); - Py_VISIT(state->Timestamp); - Py_VISIT(state->MinKey); - Py_VISIT(state->MaxKey); - Py_VISIT(state->UTC); - Py_VISIT(state->REType); - Py_VISIT(state->_type_marker_str); - Py_VISIT(state->_flags_str); - Py_VISIT(state->_pattern_str); - Py_VISIT(state->_encoder_map_str); - Py_VISIT(state->_decoder_map_str); - Py_VISIT(state->_fallback_encoder_str); - Py_VISIT(state->_raw_str); - Py_VISIT(state->_subtype_str); - Py_VISIT(state->_binary_str); - Py_VISIT(state->_scope_str); - Py_VISIT(state->_inc_str); - Py_VISIT(state->_time_str); - Py_VISIT(state->_bid_str); - Py_VISIT(state->_replace_str); - Py_VISIT(state->_astimezone_str); - Py_VISIT(state->_id_str); - Py_VISIT(state->_dollar_ref_str); - Py_VISIT(state->_dollar_id_str); - Py_VISIT(state->_dollar_db_str); - Py_VISIT(state->_tzinfo_str); - Py_VISIT(state->_as_doc_str); - Py_VISIT(state->_utcoffset_str); - Py_VISIT(state->_from_uuid_str); - Py_VISIT(state->_as_uuid_str); - Py_VISIT(state->_from_bid_str); - Py_VISIT(state->min_datetime); - Py_VISIT(state->max_datetime); - Py_VISIT(state->replace_args); - Py_VISIT(state->replace_kwargs); - return 0; -} - -static int _cbson_clear(PyObject *m) { - struct module_state *state = GETSTATE(m); - if (!state) { - return 0; - } - Py_CLEAR(state->Binary); - Py_CLEAR(state->Code); - Py_CLEAR(state->ObjectId); - Py_CLEAR(state->DBRef); - Py_CLEAR(state->Regex); - Py_CLEAR(state->UUID); - Py_CLEAR(state->Timestamp); - Py_CLEAR(state->MinKey); - Py_CLEAR(state->MaxKey); - Py_CLEAR(state->UTC); - Py_CLEAR(state->REType); - Py_CLEAR(state->_type_marker_str); - Py_CLEAR(state->_flags_str); - Py_CLEAR(state->_pattern_str); - Py_CLEAR(state->_encoder_map_str); - Py_CLEAR(state->_decoder_map_str); - Py_CLEAR(state->_fallback_encoder_str); - Py_CLEAR(state->_raw_str); - Py_CLEAR(state->_subtype_str); - Py_CLEAR(state->_binary_str); - Py_CLEAR(state->_scope_str); - Py_CLEAR(state->_inc_str); - Py_CLEAR(state->_time_str); - Py_CLEAR(state->_bid_str); - Py_CLEAR(state->_replace_str); - Py_CLEAR(state->_astimezone_str); - Py_CLEAR(state->_id_str); - Py_CLEAR(state->_dollar_ref_str); - Py_CLEAR(state->_dollar_id_str); - Py_CLEAR(state->_dollar_db_str); - Py_CLEAR(state->_tzinfo_str); - Py_CLEAR(state->_as_doc_str); - Py_CLEAR(state->_utcoffset_str); - Py_CLEAR(state->_from_uuid_str); - Py_CLEAR(state->_as_uuid_str); - Py_CLEAR(state->_from_bid_str); - Py_CLEAR(state->min_datetime); - Py_CLEAR(state->max_datetime); - Py_CLEAR(state->replace_args); - Py_CLEAR(state->replace_kwargs); - return 0; -} - -/* Multi-phase extension module initialization code. - * See https://peps.python.org/pep-0489/. -*/ -static int -_cbson_exec(PyObject *m) -{ - PyObject *c_api_object; - static void *_cbson_API[_cbson_API_POINTER_COUNT]; - - PyDateTime_IMPORT; - if (PyDateTimeAPI == NULL) { - INITERROR; - } - - /* Export C API */ - _cbson_API[_cbson_buffer_write_bytes_INDEX] = (void *) buffer_write_bytes; - _cbson_API[_cbson_write_dict_INDEX] = (void *) write_dict; - _cbson_API[_cbson_write_pair_INDEX] = (void *) write_pair; - _cbson_API[_cbson_decode_and_write_pair_INDEX] = (void *) decode_and_write_pair; - _cbson_API[_cbson_convert_codec_options_INDEX] = (void *) convert_codec_options; - _cbson_API[_cbson_destroy_codec_options_INDEX] = (void *) destroy_codec_options; - _cbson_API[_cbson_buffer_write_double_INDEX] = (void *) buffer_write_double; - _cbson_API[_cbson_buffer_write_int32_INDEX] = (void *) buffer_write_int32; - _cbson_API[_cbson_buffer_write_int64_INDEX] = (void *) buffer_write_int64; - _cbson_API[_cbson_buffer_write_int32_at_position_INDEX] = - (void *) buffer_write_int32_at_position; - _cbson_API[_cbson_downcast_and_check_INDEX] = (void *) _downcast_and_check; - - c_api_object = PyCapsule_New((void *) _cbson_API, "_cbson._C_API", NULL); - if (c_api_object == NULL) - INITERROR; - - /* Import several python objects */ - if (_load_python_objects(m)) { - Py_DECREF(c_api_object); - Py_DECREF(m); - INITERROR; - } - - if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) { - Py_DECREF(c_api_object); - Py_DECREF(m); - INITERROR; - } - - return 0; -} - -static PyModuleDef_Slot _cbson_slots[] = { - {Py_mod_exec, _cbson_exec}, -#if defined(Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED) - {Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED}, -#endif -#if PY_VERSION_HEX >= 0x030D0000 - {Py_mod_gil, Py_MOD_GIL_NOT_USED}, -#endif - {0, NULL}, -}; - - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "_cbson", - NULL, - sizeof(struct module_state), - _CBSONMethods, - _cbson_slots, - _cbson_traverse, - _cbson_clear, - NULL -}; - -PyMODINIT_FUNC -PyInit__cbson(void) -{ - return PyModuleDef_Init(&moduledef); -} diff --git a/venv/Lib/site-packages/bson/_cbsonmodule.h b/venv/Lib/site-packages/bson/_cbsonmodule.h deleted file mode 100644 index 3be2b74..0000000 --- a/venv/Lib/site-packages/bson/_cbsonmodule.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2009-present MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "bson-endian.h" - -#ifndef _CBSONMODULE_H -#define _CBSONMODULE_H - -#if defined(WIN32) || defined(_MSC_VER) -/* - * This macro is basically an implementation of asprintf for win32 - * We print to the provided buffer to get the string value as an int. - * USE LL2STR. This is kept only to test LL2STR. - */ -#if defined(_MSC_VER) && (_MSC_VER >= 1400) -#define INT2STRING(buffer, i) \ - _snprintf_s((buffer), \ - _scprintf("%lld", (i)) + 1, \ - _scprintf("%lld", (i)) + 1, \ - "%lld", \ - (i)) -#define STRCAT(dest, n, src) strcat_s((dest), (n), (src)) -#else -#define INT2STRING(buffer, i) \ - _snprintf((buffer), \ - _scprintf("%lld", (i)) + 1, \ - "%lld", \ - (i)) -#define STRCAT(dest, n, src) strcat((dest), (src)) -#endif -#else -#define INT2STRING(buffer, i) snprintf((buffer), sizeof((buffer)), "%lld", (i)) -#define STRCAT(dest, n, src) strcat((dest), (src)) -#endif - -/* Just enough space in char array to hold LLONG_MIN and null terminator */ -#define BUF_SIZE 21 -/* Converts integer to its string representation in decimal notation. */ -extern int cbson_long_long_to_str(long long int num, char* str, size_t size); -#define LL2STR(buffer, i) cbson_long_long_to_str((i), (buffer), sizeof(buffer)) - -typedef struct type_registry_t { - PyObject* encoder_map; - PyObject* decoder_map; - PyObject* fallback_encoder; - PyObject* registry_obj; - unsigned char is_encoder_empty; - unsigned char is_decoder_empty; - unsigned char has_fallback_encoder; -} type_registry_t; - -typedef struct codec_options_t { - PyObject* document_class; - unsigned char tz_aware; - unsigned char uuid_rep; - char* unicode_decode_error_handler; - PyObject* tzinfo; - type_registry_t type_registry; - unsigned char datetime_conversion; - PyObject* options_obj; - unsigned char is_raw_bson; -} codec_options_t; - -/* C API functions */ -#define _cbson_buffer_write_bytes_INDEX 0 -#define _cbson_buffer_write_bytes_RETURN int -#define _cbson_buffer_write_bytes_PROTO (buffer_t buffer, const char* data, int size) - -#define _cbson_write_dict_INDEX 1 -#define _cbson_write_dict_RETURN int -#define _cbson_write_dict_PROTO (PyObject* self, buffer_t buffer, PyObject* dict, unsigned char check_keys, const codec_options_t* options, unsigned char top_level) - -#define _cbson_write_pair_INDEX 2 -#define _cbson_write_pair_RETURN int -#define _cbson_write_pair_PROTO (PyObject* self, buffer_t buffer, const char* name, int name_length, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char allow_id) - -#define _cbson_decode_and_write_pair_INDEX 3 -#define _cbson_decode_and_write_pair_RETURN int -#define _cbson_decode_and_write_pair_PROTO (PyObject* self, buffer_t buffer, PyObject* key, PyObject* value, unsigned char check_keys, const codec_options_t* options, unsigned char top_level) - -#define _cbson_convert_codec_options_INDEX 4 -#define _cbson_convert_codec_options_RETURN int -#define _cbson_convert_codec_options_PROTO (PyObject* self, PyObject* options_obj, codec_options_t* options) - -#define _cbson_destroy_codec_options_INDEX 5 -#define _cbson_destroy_codec_options_RETURN void -#define _cbson_destroy_codec_options_PROTO (codec_options_t* options) - -#define _cbson_buffer_write_double_INDEX 6 -#define _cbson_buffer_write_double_RETURN int -#define _cbson_buffer_write_double_PROTO (buffer_t buffer, double data) - -#define _cbson_buffer_write_int32_INDEX 7 -#define _cbson_buffer_write_int32_RETURN int -#define _cbson_buffer_write_int32_PROTO (buffer_t buffer, int32_t data) - -#define _cbson_buffer_write_int64_INDEX 8 -#define _cbson_buffer_write_int64_RETURN int -#define _cbson_buffer_write_int64_PROTO (buffer_t buffer, int64_t data) - -#define _cbson_buffer_write_int32_at_position_INDEX 9 -#define _cbson_buffer_write_int32_at_position_RETURN void -#define _cbson_buffer_write_int32_at_position_PROTO (buffer_t buffer, int position, int32_t data) - -#define _cbson_downcast_and_check_INDEX 10 -#define _cbson_downcast_and_check_RETURN int -#define _cbson_downcast_and_check_PROTO (Py_ssize_t size, uint8_t extra) - -/* Total number of C API pointers */ -#define _cbson_API_POINTER_COUNT 11 - -#ifdef _CBSON_MODULE -/* This section is used when compiling _cbsonmodule */ - -static _cbson_buffer_write_bytes_RETURN buffer_write_bytes _cbson_buffer_write_bytes_PROTO; - -static _cbson_write_dict_RETURN write_dict _cbson_write_dict_PROTO; - -static _cbson_write_pair_RETURN write_pair _cbson_write_pair_PROTO; - -static _cbson_decode_and_write_pair_RETURN decode_and_write_pair _cbson_decode_and_write_pair_PROTO; - -static _cbson_convert_codec_options_RETURN convert_codec_options _cbson_convert_codec_options_PROTO; - -static _cbson_destroy_codec_options_RETURN destroy_codec_options _cbson_destroy_codec_options_PROTO; - -static _cbson_buffer_write_double_RETURN buffer_write_double _cbson_buffer_write_double_PROTO; - -static _cbson_buffer_write_int32_RETURN buffer_write_int32 _cbson_buffer_write_int32_PROTO; - -static _cbson_buffer_write_int64_RETURN buffer_write_int64 _cbson_buffer_write_int64_PROTO; - -static _cbson_buffer_write_int32_at_position_RETURN buffer_write_int32_at_position _cbson_buffer_write_int32_at_position_PROTO; - -static _cbson_downcast_and_check_RETURN _downcast_and_check _cbson_downcast_and_check_PROTO; - -#else -/* This section is used in modules that use _cbsonmodule's API */ - -static void **_cbson_API; - -#define buffer_write_bytes (*(_cbson_buffer_write_bytes_RETURN (*)_cbson_buffer_write_bytes_PROTO) _cbson_API[_cbson_buffer_write_bytes_INDEX]) - -#define write_dict (*(_cbson_write_dict_RETURN (*)_cbson_write_dict_PROTO) _cbson_API[_cbson_write_dict_INDEX]) - -#define write_pair (*(_cbson_write_pair_RETURN (*)_cbson_write_pair_PROTO) _cbson_API[_cbson_write_pair_INDEX]) - -#define decode_and_write_pair (*(_cbson_decode_and_write_pair_RETURN (*)_cbson_decode_and_write_pair_PROTO) _cbson_API[_cbson_decode_and_write_pair_INDEX]) - -#define convert_codec_options (*(_cbson_convert_codec_options_RETURN (*)_cbson_convert_codec_options_PROTO) _cbson_API[_cbson_convert_codec_options_INDEX]) - -#define destroy_codec_options (*(_cbson_destroy_codec_options_RETURN (*)_cbson_destroy_codec_options_PROTO) _cbson_API[_cbson_destroy_codec_options_INDEX]) - -#define buffer_write_double (*(_cbson_buffer_write_double_RETURN (*)_cbson_buffer_write_double_PROTO) _cbson_API[_cbson_buffer_write_double_INDEX]) - -#define buffer_write_int32 (*(_cbson_buffer_write_int32_RETURN (*)_cbson_buffer_write_int32_PROTO) _cbson_API[_cbson_buffer_write_int32_INDEX]) - -#define buffer_write_int64 (*(_cbson_buffer_write_int64_RETURN (*)_cbson_buffer_write_int64_PROTO) _cbson_API[_cbson_buffer_write_int64_INDEX]) - -#define buffer_write_int32_at_position (*(_cbson_buffer_write_int32_at_position_RETURN (*)_cbson_buffer_write_int32_at_position_PROTO) _cbson_API[_cbson_buffer_write_int32_at_position_INDEX]) - -#define _downcast_and_check (*(_cbson_downcast_and_check_RETURN (*)_cbson_downcast_and_check_PROTO) _cbson_API[_cbson_downcast_and_check_INDEX]) - -#define _cbson_IMPORT _cbson_API = (void **)PyCapsule_Import("_cbson._C_API", 0) - -#endif - -#endif // _CBSONMODULE_H diff --git a/venv/Lib/site-packages/bson/_helpers.py b/venv/Lib/site-packages/bson/_helpers.py deleted file mode 100644 index 5a47986..0000000 --- a/venv/Lib/site-packages/bson/_helpers.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright 2021-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Setstate and getstate functions for objects with __slots__, allowing -compatibility with default pickling protocol -""" -from __future__ import annotations - -from typing import Any, Mapping - - -def _setstate_slots(self: Any, state: Any) -> None: - for slot, value in state.items(): - setattr(self, slot, value) - - -def _mangle_name(name: str, prefix: str) -> str: - if name.startswith("__"): - prefix = "_" + prefix - else: - prefix = "" - return prefix + name - - -def _getstate_slots(self: Any) -> Mapping[Any, Any]: - prefix = self.__class__.__name__ - ret = {} - for name in self.__slots__: - mangled_name = _mangle_name(name, prefix) - if hasattr(self, mangled_name): - ret[mangled_name] = getattr(self, mangled_name) - return ret diff --git a/venv/Lib/site-packages/bson/binary.py b/venv/Lib/site-packages/bson/binary.py deleted file mode 100644 index 6698e55..0000000 --- a/venv/Lib/site-packages/bson/binary.py +++ /dev/null @@ -1,551 +0,0 @@ -# Copyright 2009-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -from __future__ import annotations - -import struct -from enum import Enum -from typing import TYPE_CHECKING, Any, Optional, Sequence, Tuple, Type, Union, overload -from uuid import UUID - -"""Tools for representing BSON binary data. -""" - -BINARY_SUBTYPE = 0 -"""BSON binary subtype for binary data. - -This is the default subtype for binary data. -""" - -FUNCTION_SUBTYPE = 1 -"""BSON binary subtype for functions. -""" - -OLD_BINARY_SUBTYPE = 2 -"""Old BSON binary subtype for binary data. - -This is the old default subtype, the current -default is :data:`BINARY_SUBTYPE`. -""" - -OLD_UUID_SUBTYPE = 3 -"""Old BSON binary subtype for a UUID. - -:class:`uuid.UUID` instances will automatically be encoded -by :mod:`bson` using this subtype when using -:data:`UuidRepresentation.PYTHON_LEGACY`, -:data:`UuidRepresentation.JAVA_LEGACY`, or -:data:`UuidRepresentation.CSHARP_LEGACY`. - -.. versionadded:: 2.1 -""" - -UUID_SUBTYPE = 4 -"""BSON binary subtype for a UUID. - -This is the standard BSON binary subtype for UUIDs. -:class:`uuid.UUID` instances will automatically be encoded -by :mod:`bson` using this subtype when using -:data:`UuidRepresentation.STANDARD`. -""" - - -if TYPE_CHECKING: - from array import array as _array - from mmap import mmap as _mmap - - -class UuidRepresentation: - UNSPECIFIED = 0 - """An unspecified UUID representation. - - When configured, :class:`uuid.UUID` instances will **not** be - automatically encoded to or decoded from :class:`~bson.binary.Binary`. - When encoding a :class:`uuid.UUID` instance, an error will be raised. - To encode a :class:`uuid.UUID` instance with this configuration, it must - be wrapped in the :class:`~bson.binary.Binary` class by the application - code. When decoding a BSON binary field with a UUID subtype, a - :class:`~bson.binary.Binary` instance will be returned instead of a - :class:`uuid.UUID` instance. - - See :ref:`unspecified-representation-details` for details. - - .. versionadded:: 3.11 - """ - - STANDARD = UUID_SUBTYPE - """The standard UUID representation. - - :class:`uuid.UUID` instances will automatically be encoded to - and decoded from BSON binary, using RFC-4122 byte order with - binary subtype :data:`UUID_SUBTYPE`. - - See :ref:`standard-representation-details` for details. - - .. versionadded:: 3.11 - """ - - PYTHON_LEGACY = OLD_UUID_SUBTYPE - """The Python legacy UUID representation. - - :class:`uuid.UUID` instances will automatically be encoded to - and decoded from BSON binary, using RFC-4122 byte order with - binary subtype :data:`OLD_UUID_SUBTYPE`. - - See :ref:`python-legacy-representation-details` for details. - - .. versionadded:: 3.11 - """ - - JAVA_LEGACY = 5 - """The Java legacy UUID representation. - - :class:`uuid.UUID` instances will automatically be encoded to - and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`, - using the Java driver's legacy byte order. - - See :ref:`java-legacy-representation-details` for details. - - .. versionadded:: 3.11 - """ - - CSHARP_LEGACY = 6 - """The C#/.net legacy UUID representation. - - :class:`uuid.UUID` instances will automatically be encoded to - and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`, - using the C# driver's legacy byte order. - - See :ref:`csharp-legacy-representation-details` for details. - - .. versionadded:: 3.11 - """ - - -STANDARD = UuidRepresentation.STANDARD -"""An alias for :data:`UuidRepresentation.STANDARD`. - -.. versionadded:: 3.0 -""" - -PYTHON_LEGACY = UuidRepresentation.PYTHON_LEGACY -"""An alias for :data:`UuidRepresentation.PYTHON_LEGACY`. - -.. versionadded:: 3.0 -""" - -JAVA_LEGACY = UuidRepresentation.JAVA_LEGACY -"""An alias for :data:`UuidRepresentation.JAVA_LEGACY`. - -.. versionchanged:: 3.6 - BSON binary subtype 4 is decoded using RFC-4122 byte order. -.. versionadded:: 2.3 -""" - -CSHARP_LEGACY = UuidRepresentation.CSHARP_LEGACY -"""An alias for :data:`UuidRepresentation.CSHARP_LEGACY`. - -.. versionchanged:: 3.6 - BSON binary subtype 4 is decoded using RFC-4122 byte order. -.. versionadded:: 2.3 -""" - -ALL_UUID_SUBTYPES = (OLD_UUID_SUBTYPE, UUID_SUBTYPE) -ALL_UUID_REPRESENTATIONS = ( - UuidRepresentation.UNSPECIFIED, - UuidRepresentation.STANDARD, - UuidRepresentation.PYTHON_LEGACY, - UuidRepresentation.JAVA_LEGACY, - UuidRepresentation.CSHARP_LEGACY, -) -UUID_REPRESENTATION_NAMES = { - UuidRepresentation.UNSPECIFIED: "UuidRepresentation.UNSPECIFIED", - UuidRepresentation.STANDARD: "UuidRepresentation.STANDARD", - UuidRepresentation.PYTHON_LEGACY: "UuidRepresentation.PYTHON_LEGACY", - UuidRepresentation.JAVA_LEGACY: "UuidRepresentation.JAVA_LEGACY", - UuidRepresentation.CSHARP_LEGACY: "UuidRepresentation.CSHARP_LEGACY", -} - -MD5_SUBTYPE = 5 -"""BSON binary subtype for an MD5 hash. -""" - -COLUMN_SUBTYPE = 7 -"""BSON binary subtype for columns. - -.. versionadded:: 4.0 -""" - -SENSITIVE_SUBTYPE = 8 -"""BSON binary subtype for sensitive data. - -.. versionadded:: 4.5 -""" - - -VECTOR_SUBTYPE = 9 -"""BSON binary subtype for densely packed vector data. - -.. versionadded:: 4.10 -""" - - -USER_DEFINED_SUBTYPE = 128 -"""BSON binary subtype for any user defined structure. -""" - - -class BinaryVectorDtype(Enum): - """Datatypes of vector subtype. - - :param FLOAT32: (0x27) Pack list of :class:`float` as float32 - :param INT8: (0x03) Pack list of :class:`int` in [-128, 127] as signed int8 - :param PACKED_BIT: (0x10) Pack list of :class:`int` in [0, 255] as unsigned uint8 - - The `PACKED_BIT` value represents a special case where vector values themselves - can only be of two values (0 or 1) but these are packed together into groups of 8, - a byte. In Python, these are displayed as ints in range [0, 255] - - Each value is of type bytes with a length of one. - - .. versionadded:: 4.10 - """ - - INT8 = b"\x03" - FLOAT32 = b"\x27" - PACKED_BIT = b"\x10" - - -class BinaryVector: - """Vector of numbers along with metadata for binary interoperability. - .. versionadded:: 4.10 - """ - - __slots__ = ("data", "dtype", "padding") - - def __init__(self, data: Sequence[float | int], dtype: BinaryVectorDtype, padding: int = 0): - """ - :param data: Sequence of numbers representing the mathematical vector. - :param dtype: The data type stored in binary - :param padding: The number of bits in the final byte that are to be ignored - when a vector element's size is less than a byte - and the length of the vector is not a multiple of 8. - """ - self.data = data - self.dtype = dtype - self.padding = padding - - def __repr__(self) -> str: - return f"BinaryVector(dtype={self.dtype}, padding={self.padding}, data={self.data})" - - def __eq__(self, other: Any) -> bool: - if not isinstance(other, BinaryVector): - return False - return ( - self.dtype == other.dtype and self.padding == other.padding and self.data == other.data - ) - - -class Binary(bytes): - """Representation of BSON binary data. - - We want to represent Python strings as the BSON string type. - We need to wrap binary data so that we can tell - the difference between what should be considered binary data and - what should be considered a string when we encode to BSON. - - Subtype 9 provides a space-efficient representation of 1-dimensional vector data. - Its data is prepended with two bytes of metadata. - The first (dtype) describes its data type, such as float32 or int8. - The second (padding) prescribes the number of bits to ignore in the final byte. - This is relevant when the element size of the dtype is not a multiple of 8. - - Raises TypeError if `subtype` is not an instance of :class:`int`. - Raises ValueError if `subtype` is not in [0, 256). - - .. note:: - Instances of Binary with subtype 0 will be decoded directly to :class:`bytes`. - - :param data: the binary data to represent. Can be any bytes-like type - that implements the buffer protocol. - :param subtype: the `binary subtype - `_ - to use - - .. versionchanged:: 3.9 - Support any bytes-like type that implements the buffer protocol. - - .. versionchanged:: 4.10 - Addition of vector subtype. - """ - - _type_marker = 5 - __subtype: int - - def __new__( - cls: Type[Binary], - data: Union[memoryview, bytes, _mmap, _array[Any]], - subtype: int = BINARY_SUBTYPE, - ) -> Binary: - if not isinstance(subtype, int): - raise TypeError(f"subtype must be an instance of int, not {type(subtype)}") - if subtype >= 256 or subtype < 0: - raise ValueError("subtype must be contained in [0, 256)") - # Support any type that implements the buffer protocol. - self = bytes.__new__(cls, memoryview(data).tobytes()) - self.__subtype = subtype - return self - - @classmethod - def from_uuid( - cls: Type[Binary], uuid: UUID, uuid_representation: int = UuidRepresentation.STANDARD - ) -> Binary: - """Create a BSON Binary object from a Python UUID. - - Creates a :class:`~bson.binary.Binary` object from a - :class:`uuid.UUID` instance. Assumes that the native - :class:`uuid.UUID` instance uses the byte-order implied by the - provided ``uuid_representation``. - - Raises :exc:`TypeError` if `uuid` is not an instance of - :class:`~uuid.UUID`. - - :param uuid: A :class:`uuid.UUID` instance. - :param uuid_representation: A member of - :class:`~bson.binary.UuidRepresentation`. Default: - :const:`~bson.binary.UuidRepresentation.STANDARD`. - See :ref:`handling-uuid-data-example` for details. - - .. versionadded:: 3.11 - """ - if not isinstance(uuid, UUID): - raise TypeError(f"uuid must be an instance of uuid.UUID, not {type(uuid)}") - - if uuid_representation not in ALL_UUID_REPRESENTATIONS: - raise ValueError( - "uuid_representation must be a value from bson.binary.UuidRepresentation" - ) - - if uuid_representation == UuidRepresentation.UNSPECIFIED: - raise ValueError( - "cannot encode native uuid.UUID with " - "UuidRepresentation.UNSPECIFIED. UUIDs can be manually " - "converted to bson.Binary instances using " - "bson.Binary.from_uuid() or a different UuidRepresentation " - "can be configured. See the documentation for " - "UuidRepresentation for more information." - ) - - subtype = OLD_UUID_SUBTYPE - if uuid_representation == UuidRepresentation.PYTHON_LEGACY: - payload = uuid.bytes - elif uuid_representation == UuidRepresentation.JAVA_LEGACY: - from_uuid = uuid.bytes - payload = from_uuid[0:8][::-1] + from_uuid[8:16][::-1] - elif uuid_representation == UuidRepresentation.CSHARP_LEGACY: - payload = uuid.bytes_le - else: - # uuid_representation == UuidRepresentation.STANDARD - subtype = UUID_SUBTYPE - payload = uuid.bytes - - return cls(payload, subtype) - - def as_uuid(self, uuid_representation: int = UuidRepresentation.STANDARD) -> UUID: - """Create a Python UUID from this BSON Binary object. - - Decodes this binary object as a native :class:`uuid.UUID` instance - with the provided ``uuid_representation``. - - Raises :exc:`ValueError` if this :class:`~bson.binary.Binary` instance - does not contain a UUID. - - :param uuid_representation: A member of - :class:`~bson.binary.UuidRepresentation`. Default: - :const:`~bson.binary.UuidRepresentation.STANDARD`. - See :ref:`handling-uuid-data-example` for details. - - .. versionadded:: 3.11 - """ - if self.subtype not in ALL_UUID_SUBTYPES: - raise ValueError(f"cannot decode subtype {self.subtype} as a uuid") - - if uuid_representation not in ALL_UUID_REPRESENTATIONS: - raise ValueError( - "uuid_representation must be a value from bson.binary.UuidRepresentation" - ) - - if uuid_representation == UuidRepresentation.UNSPECIFIED: - raise ValueError("uuid_representation cannot be UNSPECIFIED") - elif uuid_representation == UuidRepresentation.PYTHON_LEGACY: - if self.subtype == OLD_UUID_SUBTYPE: - return UUID(bytes=self) - elif uuid_representation == UuidRepresentation.JAVA_LEGACY: - if self.subtype == OLD_UUID_SUBTYPE: - return UUID(bytes=self[0:8][::-1] + self[8:16][::-1]) - elif uuid_representation == UuidRepresentation.CSHARP_LEGACY: - if self.subtype == OLD_UUID_SUBTYPE: - return UUID(bytes_le=self) - else: - # uuid_representation == UuidRepresentation.STANDARD - if self.subtype == UUID_SUBTYPE: - return UUID(bytes=self) - - raise ValueError( - f"cannot decode subtype {self.subtype} to {UUID_REPRESENTATION_NAMES[uuid_representation]}" - ) - - @classmethod - @overload - def from_vector(cls: Type[Binary], vector: BinaryVector) -> Binary: - ... - - @classmethod - @overload - def from_vector( - cls: Type[Binary], - vector: Union[list[int], list[float]], - dtype: BinaryVectorDtype, - padding: int = 0, - ) -> Binary: - ... - - @classmethod - def from_vector( - cls: Type[Binary], - vector: Union[BinaryVector, list[int], list[float]], - dtype: Optional[BinaryVectorDtype] = None, - padding: Optional[int] = None, - ) -> Binary: - """Create a BSON :class:`~bson.binary.Binary` of Vector subtype. - - To interpret the representation of the numbers, a data type must be included. - See :class:`~bson.binary.BinaryVectorDtype` for available types and descriptions. - - The dtype and padding are prepended to the binary data's value. - - :param vector: Either a List of values, or a :class:`~bson.binary.BinaryVector` dataclass. - :param dtype: Data type of the values - :param padding: For fractional bytes, number of bits to ignore at end of vector. - :return: Binary packed data identified by dtype and padding. - - .. versionadded:: 4.10 - """ - if isinstance(vector, BinaryVector): - if dtype or padding: - raise ValueError( - "The first argument, vector, has type BinaryVector. " - "dtype or padding cannot be separately defined, but were." - ) - dtype = vector.dtype - padding = vector.padding - vector = vector.data # type: ignore - - padding = 0 if padding is None else padding - if dtype == BinaryVectorDtype.INT8: # pack ints in [-128, 127] as signed int8 - format_str = "b" - if padding: - raise ValueError(f"padding does not apply to {dtype=}") - elif dtype == BinaryVectorDtype.PACKED_BIT: # pack ints in [0, 255] as unsigned uint8 - format_str = "B" - if 0 <= padding > 7: - raise ValueError(f"{padding=}. It must be in [0,1, ..7].") - if padding and not vector: - raise ValueError("Empty vector with non-zero padding.") - elif dtype == BinaryVectorDtype.FLOAT32: # pack floats as float32 - format_str = "f" - if padding: - raise ValueError(f"padding does not apply to {dtype=}") - else: - raise NotImplementedError("%s not yet supported" % dtype) - - metadata = struct.pack(" BinaryVector: - """From the Binary, create a list of numbers, along with dtype and padding. - - :return: BinaryVector - - .. versionadded:: 4.10 - """ - - if self.subtype != VECTOR_SUBTYPE: - raise ValueError(f"Cannot decode subtype {self.subtype} as a vector") - - position = 0 - dtype, padding = struct.unpack_from(" int: - """Subtype of this binary data.""" - return self.__subtype - - def __getnewargs__(self) -> Tuple[bytes, int]: # type: ignore[override] - # Work around http://bugs.python.org/issue7382 - data = super().__getnewargs__()[0] - if not isinstance(data, bytes): - data = data.encode("latin-1") - return data, self.__subtype - - def __eq__(self, other: Any) -> bool: - if isinstance(other, Binary): - return (self.__subtype, bytes(self)) == (other.subtype, bytes(other)) - # We don't return NotImplemented here because if we did then - # Binary("foo") == "foo" would return True, since Binary is a - # subclass of str... - return False - - def __hash__(self) -> int: - return super().__hash__() ^ hash(self.__subtype) - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __repr__(self) -> str: - if self.__subtype == SENSITIVE_SUBTYPE: - return f"" - else: - return f"Binary({bytes.__repr__(self)}, {self.__subtype})" diff --git a/venv/Lib/site-packages/bson/bson-endian.h b/venv/Lib/site-packages/bson/bson-endian.h deleted file mode 100644 index e906b07..0000000 --- a/venv/Lib/site-packages/bson/bson-endian.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2013-2016 MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef BSON_ENDIAN_H -#define BSON_ENDIAN_H - - -#if defined(__sun) -# include -#endif - - -#ifdef _MSC_VER -# define BSON_INLINE __inline -#else -# include -# define BSON_INLINE __inline__ -#endif - - -#define BSON_BIG_ENDIAN 4321 -#define BSON_LITTLE_ENDIAN 1234 - - -/* WORDS_BIGENDIAN from pyconfig.h / Python.h */ -#ifdef WORDS_BIGENDIAN -# define BSON_BYTE_ORDER BSON_BIG_ENDIAN -#else -# define BSON_BYTE_ORDER BSON_LITTLE_ENDIAN -#endif - - -#if defined(__sun) -# define BSON_UINT16_SWAP_LE_BE(v) BSWAP_16((uint16_t)v) -# define BSON_UINT32_SWAP_LE_BE(v) BSWAP_32((uint32_t)v) -# define BSON_UINT64_SWAP_LE_BE(v) BSWAP_64((uint64_t)v) -#elif defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__) && \ - (__clang_major__ >= 3) && (__clang_minor__ >= 1) -# if __has_builtin(__builtin_bswap16) -# define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16(v) -# endif -# if __has_builtin(__builtin_bswap32) -# define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32(v) -# endif -# if __has_builtin(__builtin_bswap64) -# define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64(v) -# endif -#elif defined(__GNUC__) && (__GNUC__ >= 4) -# if __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 3 -# define BSON_UINT32_SWAP_LE_BE(v) __builtin_bswap32 ((uint32_t)v) -# define BSON_UINT64_SWAP_LE_BE(v) __builtin_bswap64 ((uint64_t)v) -# endif -# if __GNUC__ >= 4 && defined (__GNUC_MINOR__) && __GNUC_MINOR__ >= 8 -# define BSON_UINT16_SWAP_LE_BE(v) __builtin_bswap16 ((uint32_t)v) -# endif -#endif - - -#ifndef BSON_UINT16_SWAP_LE_BE -# define BSON_UINT16_SWAP_LE_BE(v) __bson_uint16_swap_slow ((uint16_t)v) -#endif - - -#ifndef BSON_UINT32_SWAP_LE_BE -# define BSON_UINT32_SWAP_LE_BE(v) __bson_uint32_swap_slow ((uint32_t)v) -#endif - - -#ifndef BSON_UINT64_SWAP_LE_BE -# define BSON_UINT64_SWAP_LE_BE(v) __bson_uint64_swap_slow ((uint64_t)v) -#endif - - -#if BSON_BYTE_ORDER == BSON_LITTLE_ENDIAN -# define BSON_UINT16_FROM_LE(v) ((uint16_t)v) -# define BSON_UINT16_TO_LE(v) ((uint16_t)v) -# define BSON_UINT16_FROM_BE(v) BSON_UINT16_SWAP_LE_BE (v) -# define BSON_UINT16_TO_BE(v) BSON_UINT16_SWAP_LE_BE (v) -# define BSON_UINT32_FROM_LE(v) ((uint32_t)v) -# define BSON_UINT32_TO_LE(v) ((uint32_t)v) -# define BSON_UINT32_FROM_BE(v) BSON_UINT32_SWAP_LE_BE (v) -# define BSON_UINT32_TO_BE(v) BSON_UINT32_SWAP_LE_BE (v) -# define BSON_UINT64_FROM_LE(v) ((uint64_t)v) -# define BSON_UINT64_TO_LE(v) ((uint64_t)v) -# define BSON_UINT64_FROM_BE(v) BSON_UINT64_SWAP_LE_BE (v) -# define BSON_UINT64_TO_BE(v) BSON_UINT64_SWAP_LE_BE (v) -# define BSON_DOUBLE_FROM_LE(v) ((double)v) -# define BSON_DOUBLE_TO_LE(v) ((double)v) -#elif BSON_BYTE_ORDER == BSON_BIG_ENDIAN -# define BSON_UINT16_FROM_LE(v) BSON_UINT16_SWAP_LE_BE (v) -# define BSON_UINT16_TO_LE(v) BSON_UINT16_SWAP_LE_BE (v) -# define BSON_UINT16_FROM_BE(v) ((uint16_t)v) -# define BSON_UINT16_TO_BE(v) ((uint16_t)v) -# define BSON_UINT32_FROM_LE(v) BSON_UINT32_SWAP_LE_BE (v) -# define BSON_UINT32_TO_LE(v) BSON_UINT32_SWAP_LE_BE (v) -# define BSON_UINT32_FROM_BE(v) ((uint32_t)v) -# define BSON_UINT32_TO_BE(v) ((uint32_t)v) -# define BSON_UINT64_FROM_LE(v) BSON_UINT64_SWAP_LE_BE (v) -# define BSON_UINT64_TO_LE(v) BSON_UINT64_SWAP_LE_BE (v) -# define BSON_UINT64_FROM_BE(v) ((uint64_t)v) -# define BSON_UINT64_TO_BE(v) ((uint64_t)v) -# define BSON_DOUBLE_FROM_LE(v) (__bson_double_swap_slow (v)) -# define BSON_DOUBLE_TO_LE(v) (__bson_double_swap_slow (v)) -#else -# error "The endianness of target architecture is unknown." -#endif - - -/* - *-------------------------------------------------------------------------- - * - * __bson_uint16_swap_slow -- - * - * Fallback endianness conversion for 16-bit integers. - * - * Returns: - * The endian swapped version. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ - -static BSON_INLINE uint16_t -__bson_uint16_swap_slow (uint16_t v) /* IN */ -{ - return ((v & 0x00FF) << 8) | - ((v & 0xFF00) >> 8); -} - - -/* - *-------------------------------------------------------------------------- - * - * __bson_uint32_swap_slow -- - * - * Fallback endianness conversion for 32-bit integers. - * - * Returns: - * The endian swapped version. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ - -static BSON_INLINE uint32_t -__bson_uint32_swap_slow (uint32_t v) /* IN */ -{ - return ((v & 0x000000FFU) << 24) | - ((v & 0x0000FF00U) << 8) | - ((v & 0x00FF0000U) >> 8) | - ((v & 0xFF000000U) >> 24); -} - - -/* - *-------------------------------------------------------------------------- - * - * __bson_uint64_swap_slow -- - * - * Fallback endianness conversion for 64-bit integers. - * - * Returns: - * The endian swapped version. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ - -static BSON_INLINE uint64_t -__bson_uint64_swap_slow (uint64_t v) /* IN */ -{ - return ((v & 0x00000000000000FFULL) << 56) | - ((v & 0x000000000000FF00ULL) << 40) | - ((v & 0x0000000000FF0000ULL) << 24) | - ((v & 0x00000000FF000000ULL) << 8) | - ((v & 0x000000FF00000000ULL) >> 8) | - ((v & 0x0000FF0000000000ULL) >> 24) | - ((v & 0x00FF000000000000ULL) >> 40) | - ((v & 0xFF00000000000000ULL) >> 56); -} - - -/* - *-------------------------------------------------------------------------- - * - * __bson_double_swap_slow -- - * - * Fallback endianness conversion for double floating point. - * - * Returns: - * The endian swapped version. - * - * Side effects: - * None. - * - *-------------------------------------------------------------------------- - */ - - -static BSON_INLINE double -__bson_double_swap_slow (double v) /* IN */ -{ - uint64_t uv; - - memcpy(&uv, &v, sizeof(v)); - uv = BSON_UINT64_SWAP_LE_BE(uv); - memcpy(&v, &uv, sizeof(v)); - - return v; -} - - -#endif /* BSON_ENDIAN_H */ diff --git a/venv/Lib/site-packages/bson/buffer.c b/venv/Lib/site-packages/bson/buffer.c deleted file mode 100644 index cc75202..0000000 --- a/venv/Lib/site-packages/bson/buffer.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright 2009-2015 MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Include Python.h so we can set Python's error indicator. */ -#define PY_SSIZE_T_CLEAN -#include "Python.h" - -#include -#include - -#include "buffer.h" - -#define INITIAL_BUFFER_SIZE 256 - -struct buffer { - char* buffer; - int size; - int position; -}; - -/* Set Python's error indicator to MemoryError. - * Called after allocation failures. */ -static void set_memory_error(void) { - PyErr_NoMemory(); -} - -/* Allocate and return a new buffer. - * Return NULL and sets MemoryError on allocation failure. */ -buffer_t pymongo_buffer_new(void) { - buffer_t buffer; - buffer = (buffer_t)malloc(sizeof(struct buffer)); - if (buffer == NULL) { - set_memory_error(); - return NULL; - } - - buffer->size = INITIAL_BUFFER_SIZE; - buffer->position = 0; - buffer->buffer = (char*)malloc(sizeof(char) * INITIAL_BUFFER_SIZE); - if (buffer->buffer == NULL) { - free(buffer); - set_memory_error(); - return NULL; - } - - return buffer; -} - -/* Free the memory allocated for `buffer`. - * Return non-zero on failure. */ -int pymongo_buffer_free(buffer_t buffer) { - if (buffer == NULL) { - return 1; - } - /* Buffer will be NULL when buffer_grow fails. */ - if (buffer->buffer != NULL) { - free(buffer->buffer); - } - free(buffer); - return 0; -} - -/* Grow `buffer` to at least `min_length`. - * Return non-zero and sets MemoryError on allocation failure. */ -static int buffer_grow(buffer_t buffer, int min_length) { - int old_size = 0; - int size = buffer->size; - char* old_buffer = buffer->buffer; - if (size >= min_length) { - return 0; - } - while (size < min_length) { - old_size = size; - size *= 2; - if (size <= old_size) { - /* Size did not increase. Could be an overflow - * or size < 1. Just go with min_length. */ - size = min_length; - } - } - buffer->buffer = (char*)realloc(buffer->buffer, sizeof(char) * size); - if (buffer->buffer == NULL) { - free(old_buffer); - set_memory_error(); - return 1; - } - buffer->size = size; - return 0; -} - -/* Assure that `buffer` has at least `size` free bytes (and grow if needed). - * Return non-zero and sets MemoryError on allocation failure. - * Return non-zero and sets ValueError if `size` would exceed 2GiB. */ -static int buffer_assure_space(buffer_t buffer, int size) { - int new_size = buffer->position + size; - /* Check for overflow. */ - if (new_size < buffer->position) { - PyErr_SetString(PyExc_ValueError, - "Document would overflow BSON size limit"); - return 1; - } - - if (new_size <= buffer->size) { - return 0; - } - return buffer_grow(buffer, new_size); -} - -/* Save `size` bytes from the current position in `buffer` (and grow if needed). - * Return offset for writing, or -1 on failure. - * Sets MemoryError or ValueError on failure. */ -buffer_position pymongo_buffer_save_space(buffer_t buffer, int size) { - int position = buffer->position; - if (buffer_assure_space(buffer, size) != 0) { - return -1; - } - buffer->position += size; - return position; -} - -/* Write `size` bytes from `data` to `buffer` (and grow if needed). - * Return non-zero on failure. - * Sets MemoryError or ValueError on failure. */ -int pymongo_buffer_write(buffer_t buffer, const char* data, int size) { - if (buffer_assure_space(buffer, size) != 0) { - return 1; - } - - memcpy(buffer->buffer + buffer->position, data, size); - buffer->position += size; - return 0; -} - -int pymongo_buffer_get_position(buffer_t buffer) { - return buffer->position; -} - -char* pymongo_buffer_get_buffer(buffer_t buffer) { - return buffer->buffer; -} - -void pymongo_buffer_update_position(buffer_t buffer, buffer_position new_position) { - buffer->position = new_position; -} diff --git a/venv/Lib/site-packages/bson/buffer.h b/venv/Lib/site-packages/bson/buffer.h deleted file mode 100644 index a78e34e..0000000 --- a/venv/Lib/site-packages/bson/buffer.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2009-2015 MongoDB, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BUFFER_H -#define BUFFER_H - -/* Note: if any of these functions return a failure condition then the buffer - * has already been freed. */ - -/* A buffer */ -typedef struct buffer* buffer_t; -/* A position in the buffer */ -typedef int buffer_position; - -/* Allocate and return a new buffer. - * Return NULL on allocation failure. */ -buffer_t pymongo_buffer_new(void); - -/* Free the memory allocated for `buffer`. - * Return non-zero on failure. */ -int pymongo_buffer_free(buffer_t buffer); - -/* Save `size` bytes from the current position in `buffer` (and grow if needed). - * Return offset for writing, or -1 on allocation failure. */ -buffer_position pymongo_buffer_save_space(buffer_t buffer, int size); - -/* Write `size` bytes from `data` to `buffer` (and grow if needed). - * Return non-zero on allocation failure. */ -int pymongo_buffer_write(buffer_t buffer, const char* data, int size); - -/* Getters for the internals of a buffer_t. - * Should try to avoid using these as much as possible - * since they break the abstraction. */ -buffer_position pymongo_buffer_get_position(buffer_t buffer); -char* pymongo_buffer_get_buffer(buffer_t buffer); -void pymongo_buffer_update_position(buffer_t buffer, buffer_position new_position); - -#endif diff --git a/venv/Lib/site-packages/bson/code.py b/venv/Lib/site-packages/bson/code.py deleted file mode 100644 index f0523b2..0000000 --- a/venv/Lib/site-packages/bson/code.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright 2009-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for representing JavaScript code in BSON.""" -from __future__ import annotations - -from collections.abc import Mapping as _Mapping -from typing import Any, Mapping, Optional, Type, Union - - -class Code(str): - """BSON's JavaScript code type. - - Raises :class:`TypeError` if `code` is not an instance of - :class:`str` or `scope` is not ``None`` or an instance - of :class:`dict`. - - Scope variables can be set by passing a dictionary as the `scope` - argument or by using keyword arguments. If a variable is set as a - keyword argument it will override any setting for that variable in - the `scope` dictionary. - - :param code: A string containing JavaScript code to be evaluated or another - instance of Code. In the latter case, the scope of `code` becomes this - Code's :attr:`scope`. - :param scope: dictionary representing the scope in which - `code` should be evaluated - a mapping from identifiers (as - strings) to values. Defaults to ``None``. This is applied after any - scope associated with a given `code` above. - :param kwargs: scope variables can also be passed as - keyword arguments. These are applied after `scope` and `code`. - - .. versionchanged:: 3.4 - The default value for :attr:`scope` is ``None`` instead of ``{}``. - - """ - - _type_marker = 13 - __scope: Union[Mapping[str, Any], None] - - def __new__( - cls: Type[Code], - code: Union[str, Code], - scope: Optional[Mapping[str, Any]] = None, - **kwargs: Any, - ) -> Code: - if not isinstance(code, str): - raise TypeError(f"code must be an instance of str, not {type(code)}") - - self = str.__new__(cls, code) - - try: - self.__scope = code.scope # type: ignore - except AttributeError: - self.__scope = None - - if scope is not None: - if not isinstance(scope, _Mapping): - raise TypeError(f"scope must be an instance of dict, not {type(scope)}") - if self.__scope is not None: - self.__scope.update(scope) # type: ignore - else: - self.__scope = scope - - if kwargs: - if self.__scope is not None: - self.__scope.update(kwargs) # type: ignore - else: - self.__scope = kwargs - - return self - - @property - def scope(self) -> Optional[Mapping[str, Any]]: - """Scope dictionary for this instance or ``None``.""" - return self.__scope - - def __repr__(self) -> str: - return f"Code({str.__repr__(self)}, {self.__scope!r})" - - def __eq__(self, other: Any) -> bool: - if isinstance(other, Code): - return (self.__scope, str(self)) == (other.__scope, str(other)) - return False - - __hash__: Any = None - - def __ne__(self, other: Any) -> bool: - return not self == other diff --git a/venv/Lib/site-packages/bson/codec_options.py b/venv/Lib/site-packages/bson/codec_options.py deleted file mode 100644 index 258a777..0000000 --- a/venv/Lib/site-packages/bson/codec_options.py +++ /dev/null @@ -1,511 +0,0 @@ -# Copyright 2014-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for specifying BSON codec options.""" -from __future__ import annotations - -import abc -import datetime -import enum -from collections.abc import MutableMapping as _MutableMapping -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Generic, - Iterable, - Mapping, - NamedTuple, - Optional, - Tuple, - Type, - Union, - cast, -) - -from bson.binary import ( - ALL_UUID_REPRESENTATIONS, - UUID_REPRESENTATION_NAMES, - UuidRepresentation, -) -from bson.typings import _DocumentType - -_RAW_BSON_DOCUMENT_MARKER = 101 - - -def _raw_document_class(document_class: Any) -> bool: - """Determine if a document_class is a RawBSONDocument class.""" - marker = getattr(document_class, "_type_marker", None) - return marker == _RAW_BSON_DOCUMENT_MARKER - - -class TypeEncoder(abc.ABC): - """Base class for defining type codec classes which describe how a - custom type can be transformed to one of the types BSON understands. - - Codec classes must implement the ``python_type`` attribute, and the - ``transform_python`` method to support encoding. - - See :ref:`custom-type-type-codec` documentation for an example. - """ - - @abc.abstractproperty - def python_type(self) -> Any: - """The Python type to be converted into something serializable.""" - - @abc.abstractmethod - def transform_python(self, value: Any) -> Any: - """Convert the given Python object into something serializable.""" - - -class TypeDecoder(abc.ABC): - """Base class for defining type codec classes which describe how a - BSON type can be transformed to a custom type. - - Codec classes must implement the ``bson_type`` attribute, and the - ``transform_bson`` method to support decoding. - - See :ref:`custom-type-type-codec` documentation for an example. - """ - - @abc.abstractproperty - def bson_type(self) -> Any: - """The BSON type to be converted into our own type.""" - - @abc.abstractmethod - def transform_bson(self, value: Any) -> Any: - """Convert the given BSON value into our own type.""" - - -class TypeCodec(TypeEncoder, TypeDecoder): - """Base class for defining type codec classes which describe how a - custom type can be transformed to/from one of the types :mod:`bson` - can already encode/decode. - - Codec classes must implement the ``python_type`` attribute, and the - ``transform_python`` method to support encoding, as well as the - ``bson_type`` attribute, and the ``transform_bson`` method to support - decoding. - - See :ref:`custom-type-type-codec` documentation for an example. - """ - - -_Codec = Union[TypeEncoder, TypeDecoder, TypeCodec] -_Fallback = Callable[[Any], Any] - - -class TypeRegistry: - """Encapsulates type codecs used in encoding and / or decoding BSON, as - well as the fallback encoder. Type registries cannot be modified after - instantiation. - - ``TypeRegistry`` can be initialized with an iterable of type codecs, and - a callable for the fallback encoder:: - - >>> from bson.codec_options import TypeRegistry - >>> type_registry = TypeRegistry([Codec1, Codec2, Codec3, ...], - ... fallback_encoder) - - See :ref:`custom-type-type-registry` documentation for an example. - - :param type_codecs: iterable of type codec instances. If - ``type_codecs`` contains multiple codecs that transform a single - python or BSON type, the transformation specified by the type codec - occurring last prevails. A TypeError will be raised if one or more - type codecs modify the encoding behavior of a built-in :mod:`bson` - type. - :param fallback_encoder: callable that accepts a single, - unencodable python value and transforms it into a type that - :mod:`bson` can encode. See :ref:`fallback-encoder-callable` - documentation for an example. - """ - - def __init__( - self, - type_codecs: Optional[Iterable[_Codec]] = None, - fallback_encoder: Optional[_Fallback] = None, - ) -> None: - self.__type_codecs = list(type_codecs or []) - self._fallback_encoder = fallback_encoder - self._encoder_map: dict[Any, Any] = {} - self._decoder_map: dict[Any, Any] = {} - - if self._fallback_encoder is not None: - if not callable(fallback_encoder): - raise TypeError("fallback_encoder %r is not a callable" % (fallback_encoder)) - - for codec in self.__type_codecs: - is_valid_codec = False - if isinstance(codec, TypeEncoder): - self._validate_type_encoder(codec) - is_valid_codec = True - self._encoder_map[codec.python_type] = codec.transform_python - if isinstance(codec, TypeDecoder): - is_valid_codec = True - self._decoder_map[codec.bson_type] = codec.transform_bson - if not is_valid_codec: - raise TypeError( - f"Expected an instance of {TypeEncoder.__name__}, {TypeDecoder.__name__}, or {TypeCodec.__name__}, got {codec!r} instead" - ) - - def _validate_type_encoder(self, codec: _Codec) -> None: - from bson import _BUILT_IN_TYPES - - for pytype in _BUILT_IN_TYPES: - if issubclass(cast(TypeCodec, codec).python_type, pytype): - err_msg = ( - "TypeEncoders cannot change how built-in types are " - f"encoded (encoder {codec} transforms type {pytype})" - ) - raise TypeError(err_msg) - - def __repr__(self) -> str: - return "{}(type_codecs={!r}, fallback_encoder={!r})".format( - self.__class__.__name__, - self.__type_codecs, - self._fallback_encoder, - ) - - def __eq__(self, other: Any) -> Any: - if not isinstance(other, type(self)): - return NotImplemented - return ( - (self._decoder_map == other._decoder_map) - and (self._encoder_map == other._encoder_map) - and (self._fallback_encoder == other._fallback_encoder) - ) - - -class DatetimeConversion(int, enum.Enum): - """Options for decoding BSON datetimes.""" - - DATETIME = 1 - """Decode a BSON UTC datetime as a :class:`datetime.datetime`. - - BSON UTC datetimes that cannot be represented as a - :class:`~datetime.datetime` will raise an :class:`OverflowError` - or a :class:`ValueError`. - - .. versionadded 4.3 - """ - - DATETIME_CLAMP = 2 - """Decode a BSON UTC datetime as a :class:`datetime.datetime`, clamping - to :attr:`~datetime.datetime.min` and :attr:`~datetime.datetime.max`. - - .. versionadded 4.3 - """ - - DATETIME_MS = 3 - """Decode a BSON UTC datetime as a :class:`~bson.datetime_ms.DatetimeMS` - object. - - .. versionadded 4.3 - """ - - DATETIME_AUTO = 4 - """Decode a BSON UTC datetime as a :class:`datetime.datetime` if possible, - and a :class:`~bson.datetime_ms.DatetimeMS` if not. - - .. versionadded 4.3 - """ - - -class _BaseCodecOptions(NamedTuple): - document_class: Type[Mapping[str, Any]] - tz_aware: bool - uuid_representation: int - unicode_decode_error_handler: str - tzinfo: Optional[datetime.tzinfo] - type_registry: TypeRegistry - datetime_conversion: Optional[DatetimeConversion] - - -if TYPE_CHECKING: - - class CodecOptions(Tuple[_DocumentType], Generic[_DocumentType]): - document_class: Type[_DocumentType] - tz_aware: bool - uuid_representation: int - unicode_decode_error_handler: Optional[str] - tzinfo: Optional[datetime.tzinfo] - type_registry: TypeRegistry - datetime_conversion: Optional[int] - - def __new__( - cls: Type[CodecOptions[_DocumentType]], - document_class: Optional[Type[_DocumentType]] = ..., - tz_aware: bool = ..., - uuid_representation: Optional[int] = ..., - unicode_decode_error_handler: Optional[str] = ..., - tzinfo: Optional[datetime.tzinfo] = ..., - type_registry: Optional[TypeRegistry] = ..., - datetime_conversion: Optional[int] = ..., - ) -> CodecOptions[_DocumentType]: - ... - - # CodecOptions API - def with_options(self, **kwargs: Any) -> CodecOptions[Any]: - ... - - def _arguments_repr(self) -> str: - ... - - def _options_dict(self) -> dict[Any, Any]: - ... - - # NamedTuple API - @classmethod - def _make(cls, obj: Iterable[Any]) -> CodecOptions[_DocumentType]: - ... - - def _asdict(self) -> dict[str, Any]: - ... - - def _replace(self, **kwargs: Any) -> CodecOptions[_DocumentType]: - ... - - _source: str - _fields: Tuple[str] - -else: - - class CodecOptions(_BaseCodecOptions): - """Encapsulates options used encoding and / or decoding BSON.""" - - def __init__(self, *args, **kwargs): - """Encapsulates options used encoding and / or decoding BSON. - - The `document_class` option is used to define a custom type for use - decoding BSON documents. Access to the underlying raw BSON bytes for - a document is available using the :class:`~bson.raw_bson.RawBSONDocument` - type:: - - >>> from bson.raw_bson import RawBSONDocument - >>> from bson.codec_options import CodecOptions - >>> codec_options = CodecOptions(document_class=RawBSONDocument) - >>> coll = db.get_collection('test', codec_options=codec_options) - >>> doc = coll.find_one() - >>> doc.raw - '\\x16\\x00\\x00\\x00\\x07_id\\x00[0\\x165\\x91\\x10\\xea\\x14\\xe8\\xc5\\x8b\\x93\\x00' - - The document class can be any type that inherits from - :class:`~collections.abc.MutableMapping`:: - - >>> class AttributeDict(dict): - ... # A dict that supports attribute access. - ... def __getattr__(self, key): - ... return self[key] - ... def __setattr__(self, key, value): - ... self[key] = value - ... - >>> codec_options = CodecOptions(document_class=AttributeDict) - >>> coll = db.get_collection('test', codec_options=codec_options) - >>> doc = coll.find_one() - >>> doc._id - ObjectId('5b3016359110ea14e8c58b93') - - See :doc:`/examples/datetimes` for examples using the `tz_aware` and - `tzinfo` options. - - See :doc:`/examples/uuid` for examples using the `uuid_representation` - option. - - :param document_class: BSON documents returned in queries will be decoded - to an instance of this class. Must be a subclass of - :class:`~collections.abc.MutableMapping`. Defaults to :class:`dict`. - :param tz_aware: If ``True``, BSON datetimes will be decoded to timezone - aware instances of :class:`~datetime.datetime`. Otherwise they will be - naive. Defaults to ``False``. - :param uuid_representation: The BSON representation to use when encoding - and decoding instances of :class:`~uuid.UUID`. Defaults to - :data:`~bson.binary.UuidRepresentation.UNSPECIFIED`. New - applications should consider setting this to - :data:`~bson.binary.UuidRepresentation.STANDARD` for cross language - compatibility. See :ref:`handling-uuid-data-example` for details. - :param unicode_decode_error_handler: The error handler to apply when - a Unicode-related error occurs during BSON decoding that would - otherwise raise :exc:`UnicodeDecodeError`. Valid options include - 'strict', 'replace', 'backslashreplace', 'surrogateescape', and - 'ignore'. Defaults to 'strict'. - :param tzinfo: A :class:`~datetime.tzinfo` subclass that specifies the - timezone to/from which :class:`~datetime.datetime` objects should be - encoded/decoded. - :param type_registry: Instance of :class:`TypeRegistry` used to customize - encoding and decoding behavior. - :param datetime_conversion: Specifies how UTC datetimes should be decoded - within BSON. Valid options include 'datetime_ms' to return as a - DatetimeMS, 'datetime' to return as a datetime.datetime and - raising a ValueError for out-of-range values, 'datetime_auto' to - return DatetimeMS objects when the underlying datetime is - out-of-range and 'datetime_clamp' to clamp to the minimum and - maximum possible datetimes. Defaults to 'datetime'. - - .. versionchanged:: 4.0 - The default for `uuid_representation` was changed from - :const:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` to - :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`. - - .. versionadded:: 3.8 - `type_registry` attribute. - - .. warning:: Care must be taken when changing - `unicode_decode_error_handler` from its default value ('strict'). - The 'replace' and 'ignore' modes should not be used when documents - retrieved from the server will be modified in the client application - and stored back to the server. - """ - super().__init__() - - def __new__( - cls: Type[CodecOptions], - document_class: Optional[Type[Mapping[str, Any]]] = None, - tz_aware: bool = False, - uuid_representation: Optional[int] = UuidRepresentation.UNSPECIFIED, - unicode_decode_error_handler: str = "strict", - tzinfo: Optional[datetime.tzinfo] = None, - type_registry: Optional[TypeRegistry] = None, - datetime_conversion: Optional[DatetimeConversion] = DatetimeConversion.DATETIME, - ) -> CodecOptions: - doc_class = document_class or dict - # issubclass can raise TypeError for generic aliases like SON[str, Any]. - # In that case we can use the base class for the comparison. - is_mapping = False - try: - is_mapping = issubclass(doc_class, _MutableMapping) - except TypeError: - if hasattr(doc_class, "__origin__"): - is_mapping = issubclass(doc_class.__origin__, _MutableMapping) - if not (is_mapping or _raw_document_class(doc_class)): - raise TypeError( - "document_class must be dict, bson.son.SON, " - "bson.raw_bson.RawBSONDocument, or a " - "subclass of collections.abc.MutableMapping" - ) - if not isinstance(tz_aware, bool): - raise TypeError(f"tz_aware must be True or False, was: tz_aware={tz_aware}") - if uuid_representation not in ALL_UUID_REPRESENTATIONS: - raise ValueError( - "uuid_representation must be a value from bson.binary.UuidRepresentation" - ) - if not isinstance(unicode_decode_error_handler, str): - raise ValueError( - f"unicode_decode_error_handler must be a string, not {type(unicode_decode_error_handler)}" - ) - if tzinfo is not None: - if not isinstance(tzinfo, datetime.tzinfo): - raise TypeError( - f"tzinfo must be an instance of datetime.tzinfo, not {type(tzinfo)}" - ) - if not tz_aware: - raise ValueError("cannot specify tzinfo without also setting tz_aware=True") - - type_registry = type_registry or TypeRegistry() - - if not isinstance(type_registry, TypeRegistry): - raise TypeError( - f"type_registry must be an instance of TypeRegistry, not {type(type_registry)}" - ) - - return tuple.__new__( - cls, - ( - doc_class, - tz_aware, - uuid_representation, - unicode_decode_error_handler, - tzinfo, - type_registry, - datetime_conversion, - ), - ) - - def _arguments_repr(self) -> str: - """Representation of the arguments used to create this object.""" - document_class_repr = ( - "dict" if self.document_class is dict else repr(self.document_class) - ) - - uuid_rep_repr = UUID_REPRESENTATION_NAMES.get( - self.uuid_representation, self.uuid_representation - ) - - return ( - "document_class={}, tz_aware={!r}, uuid_representation={}, " - "unicode_decode_error_handler={!r}, tzinfo={!r}, " - "type_registry={!r}, datetime_conversion={!s}".format( - document_class_repr, - self.tz_aware, - uuid_rep_repr, - self.unicode_decode_error_handler, - self.tzinfo, - self.type_registry, - self.datetime_conversion, - ) - ) - - def _options_dict(self) -> dict[str, Any]: - """Dictionary of the arguments used to create this object.""" - # TODO: PYTHON-2442 use _asdict() instead - return { - "document_class": self.document_class, - "tz_aware": self.tz_aware, - "uuid_representation": self.uuid_representation, - "unicode_decode_error_handler": self.unicode_decode_error_handler, - "tzinfo": self.tzinfo, - "type_registry": self.type_registry, - "datetime_conversion": self.datetime_conversion, - } - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self._arguments_repr()})" - - def with_options(self, **kwargs: Any) -> CodecOptions: - """Make a copy of this CodecOptions, overriding some options:: - - >>> from bson.codec_options import DEFAULT_CODEC_OPTIONS - >>> DEFAULT_CODEC_OPTIONS.tz_aware - False - >>> options = DEFAULT_CODEC_OPTIONS.with_options(tz_aware=True) - >>> options.tz_aware - True - - .. versionadded:: 3.5 - """ - opts = self._options_dict() - opts.update(kwargs) - return CodecOptions(**opts) - - -DEFAULT_CODEC_OPTIONS: CodecOptions[dict[str, Any]] = CodecOptions() - - -def _parse_codec_options(options: Any) -> CodecOptions[Any]: - """Parse BSON codec options.""" - kwargs = {} - for k in set(options) & { - "document_class", - "tz_aware", - "uuidrepresentation", - "unicode_decode_error_handler", - "tzinfo", - "type_registry", - "datetime_conversion", - }: - if k == "uuidrepresentation": - kwargs["uuid_representation"] = options[k] - else: - kwargs[k] = options[k] - return CodecOptions(**kwargs) diff --git a/venv/Lib/site-packages/bson/datetime_ms.py b/venv/Lib/site-packages/bson/datetime_ms.py deleted file mode 100644 index 679524c..0000000 --- a/venv/Lib/site-packages/bson/datetime_ms.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright 2022-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you -# may not use this file except in compliance with the License. You -# may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. - -"""Tools for representing the BSON datetime type. - -.. versionadded:: 4.3 -""" -from __future__ import annotations - -import calendar -import datetime -from typing import Any, Union, cast - -from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions, DatetimeConversion -from bson.errors import InvalidBSON -from bson.tz_util import utc - -EPOCH_AWARE = datetime.datetime.fromtimestamp(0, utc) -EPOCH_NAIVE = EPOCH_AWARE.replace(tzinfo=None) -_DATETIME_ERROR_SUGGESTION = ( - "(Consider Using CodecOptions(datetime_conversion=DATETIME_AUTO)" - " or MongoClient(datetime_conversion='DATETIME_AUTO'))." - " See: https://www.mongodb.com/docs/languages/python/pymongo-driver/current/data-formats/dates-and-times/#handling-out-of-range-datetimes" -) - - -class DatetimeMS: - """Represents a BSON UTC datetime.""" - - __slots__ = ("_value",) - - def __init__(self, value: Union[int, datetime.datetime]): - """Represents a BSON UTC datetime. - - BSON UTC datetimes are defined as an int64 of milliseconds since the - Unix epoch. The principal use of DatetimeMS is to represent - datetimes outside the range of the Python builtin - :class:`~datetime.datetime` class when - encoding/decoding BSON. - - To decode UTC datetimes as a ``DatetimeMS``, `datetime_conversion` in - :class:`~bson.codec_options.CodecOptions` must be set to 'datetime_ms' or - 'datetime_auto'. See :ref:`handling-out-of-range-datetimes` for - details. - - :param value: An instance of :class:`datetime.datetime` to be - represented as milliseconds since the Unix epoch, or int of - milliseconds since the Unix epoch. - """ - if isinstance(value, int): - if not (-(2**63) <= value <= 2**63 - 1): - raise OverflowError("Must be a 64-bit integer of milliseconds") - self._value = value - elif isinstance(value, datetime.datetime): - self._value = _datetime_to_millis(value) - else: - raise TypeError(f"{type(value)} is not a valid type for DatetimeMS") - - def __hash__(self) -> int: - return hash(self._value) - - def __repr__(self) -> str: - return type(self).__name__ + "(" + str(self._value) + ")" - - def __lt__(self, other: Union[DatetimeMS, int]) -> bool: - return self._value < other - - def __le__(self, other: Union[DatetimeMS, int]) -> bool: - return self._value <= other - - def __eq__(self, other: Any) -> bool: - if isinstance(other, DatetimeMS): - return self._value == other._value - return False - - def __ne__(self, other: Any) -> bool: - if isinstance(other, DatetimeMS): - return self._value != other._value - return True - - def __gt__(self, other: Union[DatetimeMS, int]) -> bool: - return self._value > other - - def __ge__(self, other: Union[DatetimeMS, int]) -> bool: - return self._value >= other - - _type_marker = 9 - - def as_datetime( - self, codec_options: CodecOptions[Any] = DEFAULT_CODEC_OPTIONS - ) -> datetime.datetime: - """Create a Python :class:`~datetime.datetime` from this DatetimeMS object. - - :param codec_options: A CodecOptions instance for specifying how the - resulting DatetimeMS object will be formatted using ``tz_aware`` - and ``tz_info``. Defaults to - :const:`~bson.codec_options.DEFAULT_CODEC_OPTIONS`. - """ - return cast(datetime.datetime, _millis_to_datetime(self._value, codec_options)) - - def __int__(self) -> int: - return self._value - - -def _datetime_to_millis(dtm: datetime.datetime) -> int: - """Convert datetime to milliseconds since epoch UTC.""" - if dtm.utcoffset() is not None: - dtm = dtm - dtm.utcoffset() # type: ignore - return int(calendar.timegm(dtm.timetuple()) * 1000 + dtm.microsecond // 1000) - - -_MIN_UTC = datetime.datetime.min.replace(tzinfo=utc) -_MAX_UTC = datetime.datetime.max.replace(tzinfo=utc) -_MIN_UTC_MS = _datetime_to_millis(_MIN_UTC) -_MAX_UTC_MS = _datetime_to_millis(_MAX_UTC) - - -# Inclusive min and max for timezones. -def _min_datetime_ms(tz: datetime.tzinfo = utc) -> int: - delta = tz.utcoffset(_MIN_UTC) - if delta is not None: - offset_millis = (delta.days * 86400 + delta.seconds) * 1000 + delta.microseconds // 1000 - else: - offset_millis = 0 - return max(_MIN_UTC_MS, _MIN_UTC_MS - offset_millis) - - -def _max_datetime_ms(tz: datetime.tzinfo = utc) -> int: - delta = tz.utcoffset(_MAX_UTC) - if delta is not None: - offset_millis = (delta.days * 86400 + delta.seconds) * 1000 + delta.microseconds // 1000 - else: - offset_millis = 0 - return min(_MAX_UTC_MS, _MAX_UTC_MS - offset_millis) - - -def _millis_to_datetime( - millis: int, opts: CodecOptions[Any] -) -> Union[datetime.datetime, DatetimeMS]: - """Convert milliseconds since epoch UTC to datetime.""" - if ( - opts.datetime_conversion == DatetimeConversion.DATETIME - or opts.datetime_conversion == DatetimeConversion.DATETIME_CLAMP - or opts.datetime_conversion == DatetimeConversion.DATETIME_AUTO - ): - tz = opts.tzinfo or utc - if opts.datetime_conversion == DatetimeConversion.DATETIME_CLAMP: - millis = max(_min_datetime_ms(tz), min(millis, _max_datetime_ms(tz))) - elif opts.datetime_conversion == DatetimeConversion.DATETIME_AUTO: - if not (_min_datetime_ms(tz) <= millis <= _max_datetime_ms(tz)): - return DatetimeMS(millis) - - diff = ((millis % 1000) + 1000) % 1000 - seconds = (millis - diff) // 1000 - micros = diff * 1000 - - try: - if opts.tz_aware: - dt = EPOCH_AWARE + datetime.timedelta(seconds=seconds, microseconds=micros) - if opts.tzinfo: - dt = dt.astimezone(tz) - return dt - else: - return EPOCH_NAIVE + datetime.timedelta(seconds=seconds, microseconds=micros) - except ArithmeticError as err: - raise InvalidBSON(f"{err} {_DATETIME_ERROR_SUGGESTION}") from err - - elif opts.datetime_conversion == DatetimeConversion.DATETIME_MS: - return DatetimeMS(millis) - else: - raise ValueError("datetime_conversion must be an element of DatetimeConversion") diff --git a/venv/Lib/site-packages/bson/dbref.py b/venv/Lib/site-packages/bson/dbref.py deleted file mode 100644 index 40bdb73..0000000 --- a/venv/Lib/site-packages/bson/dbref.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2009-2015 MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for manipulating DBRefs (references to MongoDB documents).""" -from __future__ import annotations - -from copy import deepcopy -from typing import Any, Mapping, Optional - -from bson._helpers import _getstate_slots, _setstate_slots -from bson.son import SON - - -class DBRef: - """A reference to a document stored in MongoDB.""" - - __slots__ = "__collection", "__id", "__database", "__kwargs" - __getstate__ = _getstate_slots - __setstate__ = _setstate_slots - # DBRef isn't actually a BSON "type" so this number was arbitrarily chosen. - _type_marker = 100 - - def __init__( - self, - collection: str, - id: Any, - database: Optional[str] = None, - _extra: Optional[Mapping[str, Any]] = None, - **kwargs: Any, - ) -> None: - """Initialize a new :class:`DBRef`. - - Raises :class:`TypeError` if `collection` or `database` is not - an instance of :class:`str`. `database` is optional and allows - references to documents to work across databases. Any additional - keyword arguments will create additional fields in the resultant - embedded document. - - :param collection: name of the collection the document is stored in - :param id: the value of the document's ``"_id"`` field - :param database: name of the database to reference - :param kwargs: additional keyword arguments will - create additional, custom fields - - .. seealso:: The MongoDB documentation on `dbrefs `_. - """ - if not isinstance(collection, str): - raise TypeError(f"collection must be an instance of str, not {type(collection)}") - if database is not None and not isinstance(database, str): - raise TypeError(f"database must be an instance of str, not {type(database)}") - - self.__collection = collection - self.__id = id - self.__database = database - kwargs.update(_extra or {}) - self.__kwargs = kwargs - - @property - def collection(self) -> str: - """Get the name of this DBRef's collection.""" - return self.__collection - - @property - def id(self) -> Any: - """Get this DBRef's _id.""" - return self.__id - - @property - def database(self) -> Optional[str]: - """Get the name of this DBRef's database. - - Returns None if this DBRef doesn't specify a database. - """ - return self.__database - - def __getattr__(self, key: Any) -> Any: - try: - return self.__kwargs[key] - except KeyError: - raise AttributeError(key) from None - - def as_doc(self) -> SON[str, Any]: - """Get the SON document representation of this DBRef. - - Generally not needed by application developers - """ - doc = SON([("$ref", self.collection), ("$id", self.id)]) - if self.database is not None: - doc["$db"] = self.database - doc.update(self.__kwargs) - return doc - - def __repr__(self) -> str: - extra = "".join([f", {k}={v!r}" for k, v in self.__kwargs.items()]) - if self.database is None: - return f"DBRef({self.collection!r}, {self.id!r}{extra})" - return f"DBRef({self.collection!r}, {self.id!r}, {self.database!r}{extra})" - - def __eq__(self, other: Any) -> bool: - if isinstance(other, DBRef): - us = (self.__database, self.__collection, self.__id, self.__kwargs) - them = (other.__database, other.__collection, other.__id, other.__kwargs) - return us == them - return NotImplemented - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __hash__(self) -> int: - """Get a hash value for this :class:`DBRef`.""" - return hash( - (self.__collection, self.__id, self.__database, tuple(sorted(self.__kwargs.items()))) - ) - - def __deepcopy__(self, memo: Any) -> DBRef: - """Support function for `copy.deepcopy()`.""" - return DBRef( - deepcopy(self.__collection, memo), - deepcopy(self.__id, memo), - deepcopy(self.__database, memo), - deepcopy(self.__kwargs, memo), - ) diff --git a/venv/Lib/site-packages/bson/decimal128.py b/venv/Lib/site-packages/bson/decimal128.py deleted file mode 100644 index 92c054d..0000000 --- a/venv/Lib/site-packages/bson/decimal128.py +++ /dev/null @@ -1,312 +0,0 @@ -# Copyright 2016-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for working with the BSON decimal128 type. - -.. versionadded:: 3.4 -""" -from __future__ import annotations - -import decimal -import struct -from typing import Any, Sequence, Tuple, Type, Union - -_PACK_64 = struct.Struct(" decimal.Context: - """Returns an instance of :class:`decimal.Context` appropriate - for working with IEEE-754 128-bit decimal floating point values. - """ - opts = _CTX_OPTIONS.copy() - opts["traps"] = [] - return decimal.Context(**opts) # type: ignore - - -def _decimal_to_128(value: _VALUE_OPTIONS) -> Tuple[int, int]: - """Converts a decimal.Decimal to BID (high bits, low bits). - - :param value: An instance of decimal.Decimal - """ - with decimal.localcontext(_DEC128_CTX) as ctx: - value = ctx.create_decimal(value) - - if value.is_infinite(): - return _NINF if value.is_signed() else _PINF - - sign, digits, exponent = value.as_tuple() - - if value.is_nan(): - if digits: - raise ValueError("NaN with debug payload is not supported") - if value.is_snan(): - return _NSNAN if value.is_signed() else _PSNAN - return _NNAN if value.is_signed() else _PNAN - - significand = int("".join([str(digit) for digit in digits])) - bit_length = significand.bit_length() - - high = 0 - low = 0 - for i in range(min(64, bit_length)): - if significand & (1 << i): - low |= 1 << i - - for i in range(64, bit_length): - if significand & (1 << i): - high |= 1 << (i - 64) - - biased_exponent = exponent + _EXPONENT_BIAS # type: ignore[operator] - - if high >> 49 == 1: - high = high & 0x7FFFFFFFFFFF - high |= _EXPONENT_MASK - high |= (biased_exponent & 0x3FFF) << 47 - else: - high |= biased_exponent << 49 - - if sign: - high |= _SIGN - - return high, low - - -class Decimal128: - """BSON Decimal128 type:: - - >>> Decimal128(Decimal("0.0005")) - Decimal128('0.0005') - >>> Decimal128("0.0005") - Decimal128('0.0005') - >>> Decimal128((3474527112516337664, 5)) - Decimal128('0.0005') - - :param value: An instance of :class:`decimal.Decimal`, string, or tuple of - (high bits, low bits) from Binary Integer Decimal (BID) format. - - .. note:: :class:`~Decimal128` uses an instance of :class:`decimal.Context` - configured for IEEE-754 Decimal128 when validating parameters. - Signals like :class:`decimal.InvalidOperation`, :class:`decimal.Inexact`, - and :class:`decimal.Overflow` are trapped and raised as exceptions:: - - >>> Decimal128(".13.1") - Traceback (most recent call last): - File "", line 1, in - ... - decimal.InvalidOperation: [] - >>> - >>> Decimal128("1E-6177") - Traceback (most recent call last): - File "", line 1, in - ... - decimal.Inexact: [] - >>> - >>> Decimal128("1E6145") - Traceback (most recent call last): - File "", line 1, in - ... - decimal.Overflow: [, ] - - To ensure the result of a calculation can always be stored as BSON - Decimal128 use the context returned by - :func:`create_decimal128_context`:: - - >>> import decimal - >>> decimal128_ctx = create_decimal128_context() - >>> with decimal.localcontext(decimal128_ctx) as ctx: - ... Decimal128(ctx.create_decimal(".13.3")) - ... - Decimal128('NaN') - >>> - >>> with decimal.localcontext(decimal128_ctx) as ctx: - ... Decimal128(ctx.create_decimal("1E-6177")) - ... - Decimal128('0E-6176') - >>> - >>> with decimal.localcontext(DECIMAL128_CTX) as ctx: - ... Decimal128(ctx.create_decimal("1E6145")) - ... - Decimal128('Infinity') - - To match the behavior of MongoDB's Decimal128 implementation - str(Decimal(value)) may not match str(Decimal128(value)) for NaN values:: - - >>> Decimal128(Decimal('NaN')) - Decimal128('NaN') - >>> Decimal128(Decimal('-NaN')) - Decimal128('NaN') - >>> Decimal128(Decimal('sNaN')) - Decimal128('NaN') - >>> Decimal128(Decimal('-sNaN')) - Decimal128('NaN') - - However, :meth:`~Decimal128.to_decimal` will return the exact value:: - - >>> Decimal128(Decimal('NaN')).to_decimal() - Decimal('NaN') - >>> Decimal128(Decimal('-NaN')).to_decimal() - Decimal('-NaN') - >>> Decimal128(Decimal('sNaN')).to_decimal() - Decimal('sNaN') - >>> Decimal128(Decimal('-sNaN')).to_decimal() - Decimal('-sNaN') - - Two instances of :class:`Decimal128` compare equal if their Binary - Integer Decimal encodings are equal:: - - >>> Decimal128('NaN') == Decimal128('NaN') - True - >>> Decimal128('NaN').bid == Decimal128('NaN').bid - True - - This differs from :class:`decimal.Decimal` comparisons for NaN:: - - >>> Decimal('NaN') == Decimal('NaN') - False - """ - - __slots__ = ("__high", "__low") - - _type_marker = 19 - - def __init__(self, value: _VALUE_OPTIONS) -> None: - if isinstance(value, (str, decimal.Decimal)): - self.__high, self.__low = _decimal_to_128(value) - elif isinstance(value, (list, tuple)): - if len(value) != 2: - raise ValueError( - "Invalid size for creation of Decimal128 " - "from list or tuple. Must have exactly 2 " - "elements." - ) - self.__high, self.__low = value - else: - raise TypeError(f"Cannot convert {value!r} to Decimal128") - - def to_decimal(self) -> decimal.Decimal: - """Returns an instance of :class:`decimal.Decimal` for this - :class:`Decimal128`. - """ - high = self.__high - low = self.__low - sign = 1 if (high & _SIGN) else 0 - - if (high & _SNAN) == _SNAN: - return decimal.Decimal((sign, (), "N")) # type: ignore - elif (high & _NAN) == _NAN: - return decimal.Decimal((sign, (), "n")) # type: ignore - elif (high & _INF) == _INF: - return decimal.Decimal((sign, (), "F")) # type: ignore - - if (high & _EXPONENT_MASK) == _EXPONENT_MASK: - exponent = ((high & 0x1FFFE00000000000) >> 47) - _EXPONENT_BIAS - return decimal.Decimal((sign, (0,), exponent)) - else: - exponent = ((high & 0x7FFF800000000000) >> 49) - _EXPONENT_BIAS - - arr = bytearray(15) - mask = 0x00000000000000FF - for i in range(14, 6, -1): - arr[i] = (low & mask) >> ((14 - i) << 3) - mask = mask << 8 - - mask = 0x00000000000000FF - for i in range(6, 0, -1): - arr[i] = (high & mask) >> ((6 - i) << 3) - mask = mask << 8 - - mask = 0x0001000000000000 - arr[0] = (high & mask) >> 48 - - # cdecimal only accepts a tuple for digits. - digits = tuple(int(digit) for digit in str(int.from_bytes(arr, "big"))) - - with decimal.localcontext(_DEC128_CTX) as ctx: - return ctx.create_decimal((sign, digits, exponent)) - - @classmethod - def from_bid(cls: Type[Decimal128], value: bytes) -> Decimal128: - """Create an instance of :class:`Decimal128` from Binary Integer - Decimal string. - - :param value: 16 byte string (128-bit IEEE 754-2008 decimal floating - point in Binary Integer Decimal (BID) format). - """ - if not isinstance(value, bytes): - raise TypeError(f"value must be an instance of bytes, not {type(value)}") - if len(value) != 16: - raise ValueError("value must be exactly 16 bytes") - return cls((_UNPACK_64(value[8:])[0], _UNPACK_64(value[:8])[0])) # type: ignore - - @property - def bid(self) -> bytes: - """The Binary Integer Decimal (BID) encoding of this instance.""" - return _PACK_64(self.__low) + _PACK_64(self.__high) - - def __str__(self) -> str: - dec = self.to_decimal() - if dec.is_nan(): - # Required by the drivers spec to match MongoDB behavior. - return "NaN" - return str(dec) - - def __repr__(self) -> str: - return f"Decimal128('{self!s}')" - - def __setstate__(self, value: Tuple[int, int]) -> None: - self.__high, self.__low = value - - def __getstate__(self) -> Tuple[int, int]: - return self.__high, self.__low - - def __eq__(self, other: Any) -> bool: - if isinstance(other, Decimal128): - return self.bid == other.bid - return NotImplemented - - def __ne__(self, other: Any) -> bool: - return not self == other diff --git a/venv/Lib/site-packages/bson/errors.py b/venv/Lib/site-packages/bson/errors.py deleted file mode 100644 index a3699e7..0000000 --- a/venv/Lib/site-packages/bson/errors.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2009-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Exceptions raised by the BSON package.""" -from __future__ import annotations - - -class BSONError(Exception): - """Base class for all BSON exceptions.""" - - -class InvalidBSON(BSONError): - """Raised when trying to create a BSON object from invalid data.""" - - -class InvalidStringData(BSONError): - """Raised when trying to encode a string containing non-UTF8 data.""" - - -class InvalidDocument(BSONError): - """Raised when trying to create a BSON object from an invalid document.""" - - -class InvalidId(BSONError): - """Raised when trying to create an ObjectId from invalid data.""" diff --git a/venv/Lib/site-packages/bson/int64.py b/venv/Lib/site-packages/bson/int64.py deleted file mode 100644 index 5846504..0000000 --- a/venv/Lib/site-packages/bson/int64.py +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2014-2015 MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""A BSON wrapper for long (int in python3)""" -from __future__ import annotations - -from typing import Any - - -class Int64(int): - """Representation of the BSON int64 type. - - This is necessary because every integral number is an :class:`int` in - Python 3. Small integral numbers are encoded to BSON int32 by default, - but Int64 numbers will always be encoded to BSON int64. - - :param value: the numeric value to represent - """ - - __slots__ = () - - _type_marker = 18 - - def __getstate__(self) -> Any: - return {} - - def __setstate__(self, state: Any) -> None: - pass diff --git a/venv/Lib/site-packages/bson/json_util.py b/venv/Lib/site-packages/bson/json_util.py deleted file mode 100644 index ecae103..0000000 --- a/venv/Lib/site-packages/bson/json_util.py +++ /dev/null @@ -1,1164 +0,0 @@ -# Copyright 2009-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for using Python's :mod:`json` module with BSON documents. - -This module provides two helper methods `dumps` and `loads` that wrap the -native :mod:`json` methods and provide explicit BSON conversion to and from -JSON. :class:`~bson.json_util.JSONOptions` provides a way to control how JSON -is emitted and parsed, with the default being the Relaxed Extended JSON format. -:mod:`~bson.json_util` can also generate Canonical or legacy `Extended JSON`_ -when :const:`CANONICAL_JSON_OPTIONS` or :const:`LEGACY_JSON_OPTIONS` is -provided, respectively. - -.. _Extended JSON: https://github.com/mongodb/specifications/blob/master/source/extended-json/extended-json.md - -Example usage (deserialization): - -.. doctest:: - - >>> from bson.json_util import loads - >>> loads( - ... '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]' - ... ) - [{'foo': [1, 2]}, {'bar': {'hello': 'world'}}, {'code': Code('function x() { return 1; }', {})}, {'bin': Binary(b'...', 128)}] - -Example usage with :const:`RELAXED_JSON_OPTIONS` (the default): - -.. doctest:: - - >>> from bson import Binary, Code - >>> from bson.json_util import dumps - >>> dumps( - ... [ - ... {"foo": [1, 2]}, - ... {"bar": {"hello": "world"}}, - ... {"code": Code("function x() { return 1; }")}, - ... {"bin": Binary(b"\x01\x02\x03\x04")}, - ... ] - ... ) - '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' - -Example usage (with :const:`CANONICAL_JSON_OPTIONS`): - -.. doctest:: - - >>> from bson import Binary, Code - >>> from bson.json_util import dumps, CANONICAL_JSON_OPTIONS - >>> dumps( - ... [ - ... {"foo": [1, 2]}, - ... {"bar": {"hello": "world"}}, - ... {"code": Code("function x() { return 1; }")}, - ... {"bin": Binary(b"\x01\x02\x03\x04")}, - ... ], - ... json_options=CANONICAL_JSON_OPTIONS, - ... ) - '[{"foo": [{"$numberInt": "1"}, {"$numberInt": "2"}]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]' - -Example usage (with :const:`LEGACY_JSON_OPTIONS`): - -.. doctest:: - - >>> from bson import Binary, Code - >>> from bson.json_util import dumps, LEGACY_JSON_OPTIONS - >>> dumps( - ... [ - ... {"foo": [1, 2]}, - ... {"bar": {"hello": "world"}}, - ... {"code": Code("function x() { return 1; }", {})}, - ... {"bin": Binary(b"\x01\x02\x03\x04")}, - ... ], - ... json_options=LEGACY_JSON_OPTIONS, - ... ) - '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]' - -Alternatively, you can manually pass the `default` to :func:`json.dumps`. -It won't handle :class:`~bson.binary.Binary` and :class:`~bson.code.Code` -instances (as they are extended strings you can't provide custom defaults), -but it will be faster as there is less recursion. - -.. note:: - If your application does not need the flexibility offered by - :class:`JSONOptions` and spends a large amount of time in the `json_util` - module, look to - `python-bsonjs `_ for a nice - performance improvement. `python-bsonjs` is a fast BSON to MongoDB - Extended JSON converter for Python built on top of - `libbson `_. `python-bsonjs` works best - with PyMongo when using :class:`~bson.raw_bson.RawBSONDocument`. -""" -from __future__ import annotations - -import base64 -import datetime -import json -import math -import re -import uuid -from typing import ( - TYPE_CHECKING, - Any, - Callable, - Mapping, - MutableMapping, - Optional, - Sequence, - Tuple, - Type, - Union, - cast, -) - -from bson.binary import ALL_UUID_SUBTYPES, UUID_SUBTYPE, Binary, UuidRepresentation -from bson.code import Code -from bson.codec_options import CodecOptions, DatetimeConversion -from bson.datetime_ms import ( - _MAX_UTC_MS, - EPOCH_AWARE, - DatetimeMS, - _datetime_to_millis, - _millis_to_datetime, -) -from bson.dbref import DBRef -from bson.decimal128 import Decimal128 -from bson.int64 import Int64 -from bson.max_key import MaxKey -from bson.min_key import MinKey -from bson.objectid import ObjectId -from bson.regex import Regex -from bson.son import RE_TYPE -from bson.timestamp import Timestamp -from bson.tz_util import utc - -_RE_OPT_TABLE = { - "i": re.I, - "l": re.L, - "m": re.M, - "s": re.S, - "u": re.U, - "x": re.X, -} - - -class DatetimeRepresentation: - LEGACY = 0 - """Legacy MongoDB Extended JSON datetime representation. - - :class:`datetime.datetime` instances will be encoded to JSON in the - format `{"$date": }`, where `dateAsMilliseconds` is - a 64-bit signed integer giving the number of milliseconds since the Unix - epoch UTC. This was the default encoding before PyMongo version 3.4. - - .. versionadded:: 3.4 - """ - - NUMBERLONG = 1 - """NumberLong datetime representation. - - :class:`datetime.datetime` instances will be encoded to JSON in the - format `{"$date": {"$numberLong": ""}}`, - where `dateAsMilliseconds` is the string representation of a 64-bit signed - integer giving the number of milliseconds since the Unix epoch UTC. - - .. versionadded:: 3.4 - """ - - ISO8601 = 2 - """ISO-8601 datetime representation. - - :class:`datetime.datetime` instances greater than or equal to the Unix - epoch UTC will be encoded to JSON in the format `{"$date": ""}`. - :class:`datetime.datetime` instances before the Unix epoch UTC will be - encoded as if the datetime representation is - :const:`~DatetimeRepresentation.NUMBERLONG`. - - .. versionadded:: 3.4 - """ - - -class JSONMode: - LEGACY = 0 - """Legacy Extended JSON representation. - - In this mode, :func:`~bson.json_util.dumps` produces PyMongo's legacy - non-standard JSON output. Consider using - :const:`~bson.json_util.JSONMode.RELAXED` or - :const:`~bson.json_util.JSONMode.CANONICAL` instead. - - .. versionadded:: 3.5 - """ - - RELAXED = 1 - """Relaxed Extended JSON representation. - - In this mode, :func:`~bson.json_util.dumps` produces Relaxed Extended JSON, - a mostly JSON-like format. Consider using this for things like a web API, - where one is sending a document (or a projection of a document) that only - uses ordinary JSON type primitives. In particular, the ``int``, - :class:`~bson.int64.Int64`, and ``float`` numeric types are represented in - the native JSON number format. This output is also the most human readable - and is useful for debugging and documentation. - - .. seealso:: The specification for Relaxed `Extended JSON`_. - - .. versionadded:: 3.5 - """ - - CANONICAL = 2 - """Canonical Extended JSON representation. - - In this mode, :func:`~bson.json_util.dumps` produces Canonical Extended - JSON, a type preserving format. Consider using this for things like - testing, where one has to precisely specify expected types in JSON. In - particular, the ``int``, :class:`~bson.int64.Int64`, and ``float`` numeric - types are encoded with type wrappers. - - .. seealso:: The specification for Canonical `Extended JSON`_. - - .. versionadded:: 3.5 - """ - - -if TYPE_CHECKING: - _BASE_CLASS = CodecOptions[MutableMapping[str, Any]] -else: - _BASE_CLASS = CodecOptions - -_INT32_MAX = 2**31 - - -class JSONOptions(_BASE_CLASS): - json_mode: int - strict_number_long: bool - datetime_representation: int - strict_uuid: bool - document_class: Type[MutableMapping[str, Any]] - - def __init__(self, *args: Any, **kwargs: Any): - """Encapsulates JSON options for :func:`dumps` and :func:`loads`. - - :param strict_number_long: If ``True``, :class:`~bson.int64.Int64` objects - are encoded to MongoDB Extended JSON's *Strict mode* type - `NumberLong`, ie ``'{"$numberLong": "" }'``. Otherwise they - will be encoded as an `int`. Defaults to ``False``. - :param datetime_representation: The representation to use when encoding - instances of :class:`datetime.datetime`. Defaults to - :const:`~DatetimeRepresentation.LEGACY`. - :param strict_uuid: If ``True``, :class:`uuid.UUID` object are encoded to - MongoDB Extended JSON's *Strict mode* type `Binary`. Otherwise it - will be encoded as ``'{"$uuid": "" }'``. Defaults to ``False``. - :param json_mode: The :class:`JSONMode` to use when encoding BSON types to - Extended JSON. Defaults to :const:`~JSONMode.LEGACY`. - :param document_class: BSON documents returned by :func:`loads` will be - decoded to an instance of this class. Must be a subclass of - :class:`collections.MutableMapping`. Defaults to :class:`dict`. - :param uuid_representation: The :class:`~bson.binary.UuidRepresentation` - to use when encoding and decoding instances of :class:`uuid.UUID`. - Defaults to :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`. - :param tz_aware: If ``True``, MongoDB Extended JSON's *Strict mode* type - `Date` will be decoded to timezone aware instances of - :class:`datetime.datetime`. Otherwise they will be naive. Defaults - to ``False``. - :param tzinfo: A :class:`datetime.tzinfo` subclass that specifies the - timezone from which :class:`~datetime.datetime` objects should be - decoded. Defaults to :const:`~bson.tz_util.utc`. - :param datetime_conversion: Specifies how UTC datetimes should be decoded - within BSON. Valid options include 'datetime_ms' to return as a - DatetimeMS, 'datetime' to return as a datetime.datetime and - raising a ValueError for out-of-range values, 'datetime_auto' to - return DatetimeMS objects when the underlying datetime is - out-of-range and 'datetime_clamp' to clamp to the minimum and - maximum possible datetimes. Defaults to 'datetime'. See - :ref:`handling-out-of-range-datetimes` for details. - :param args: arguments to :class:`~bson.codec_options.CodecOptions` - :param kwargs: arguments to :class:`~bson.codec_options.CodecOptions` - - .. seealso:: The specification for Relaxed and Canonical `Extended JSON`_. - - .. versionchanged:: 4.0 - The default for `json_mode` was changed from :const:`JSONMode.LEGACY` - to :const:`JSONMode.RELAXED`. - The default for `uuid_representation` was changed from - :const:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` to - :const:`~bson.binary.UuidRepresentation.UNSPECIFIED`. - - .. versionchanged:: 3.5 - Accepts the optional parameter `json_mode`. - - .. versionchanged:: 4.0 - Changed default value of `tz_aware` to False. - """ - super().__init__() - - def __new__( - cls: Type[JSONOptions], - strict_number_long: Optional[bool] = None, - datetime_representation: Optional[int] = None, - strict_uuid: Optional[bool] = None, - json_mode: int = JSONMode.RELAXED, - *args: Any, - **kwargs: Any, - ) -> JSONOptions: - kwargs["tz_aware"] = kwargs.get("tz_aware", False) - if kwargs["tz_aware"]: - kwargs["tzinfo"] = kwargs.get("tzinfo", utc) - if datetime_representation not in ( - DatetimeRepresentation.LEGACY, - DatetimeRepresentation.NUMBERLONG, - DatetimeRepresentation.ISO8601, - None, - ): - raise ValueError( - "JSONOptions.datetime_representation must be one of LEGACY, " - "NUMBERLONG, or ISO8601 from DatetimeRepresentation." - ) - self = cast(JSONOptions, super().__new__(cls, *args, **kwargs)) - if json_mode not in (JSONMode.LEGACY, JSONMode.RELAXED, JSONMode.CANONICAL): - raise ValueError( - "JSONOptions.json_mode must be one of LEGACY, RELAXED, " - "or CANONICAL from JSONMode." - ) - self.json_mode = json_mode - if self.json_mode == JSONMode.RELAXED: - if strict_number_long: - raise ValueError("Cannot specify strict_number_long=True with JSONMode.RELAXED") - if datetime_representation not in (None, DatetimeRepresentation.ISO8601): - raise ValueError( - "datetime_representation must be DatetimeRepresentation." - "ISO8601 or omitted with JSONMode.RELAXED" - ) - if strict_uuid not in (None, True): - raise ValueError("Cannot specify strict_uuid=False with JSONMode.RELAXED") - self.strict_number_long = False - self.datetime_representation = DatetimeRepresentation.ISO8601 - self.strict_uuid = True - elif self.json_mode == JSONMode.CANONICAL: - if strict_number_long not in (None, True): - raise ValueError("Cannot specify strict_number_long=False with JSONMode.RELAXED") - if datetime_representation not in (None, DatetimeRepresentation.NUMBERLONG): - raise ValueError( - "datetime_representation must be DatetimeRepresentation." - "NUMBERLONG or omitted with JSONMode.RELAXED" - ) - if strict_uuid not in (None, True): - raise ValueError("Cannot specify strict_uuid=False with JSONMode.RELAXED") - self.strict_number_long = True - self.datetime_representation = DatetimeRepresentation.NUMBERLONG - self.strict_uuid = True - else: # JSONMode.LEGACY - self.strict_number_long = False - self.datetime_representation = DatetimeRepresentation.LEGACY - self.strict_uuid = False - if strict_number_long is not None: - self.strict_number_long = strict_number_long - if datetime_representation is not None: - self.datetime_representation = datetime_representation - if strict_uuid is not None: - self.strict_uuid = strict_uuid - return self - - def _arguments_repr(self) -> str: - return ( - "strict_number_long={!r}, " - "datetime_representation={!r}, " - "strict_uuid={!r}, json_mode={!r}, {}".format( - self.strict_number_long, - self.datetime_representation, - self.strict_uuid, - self.json_mode, - super()._arguments_repr(), - ) - ) - - def _options_dict(self) -> dict[Any, Any]: - # TODO: PYTHON-2442 use _asdict() instead - options_dict = super()._options_dict() - options_dict.update( - { - "strict_number_long": self.strict_number_long, - "datetime_representation": self.datetime_representation, - "strict_uuid": self.strict_uuid, - "json_mode": self.json_mode, - } - ) - return options_dict - - def with_options(self, **kwargs: Any) -> JSONOptions: - """ - Make a copy of this JSONOptions, overriding some options:: - - >>> from bson.json_util import CANONICAL_JSON_OPTIONS - >>> CANONICAL_JSON_OPTIONS.tz_aware - True - >>> json_options = CANONICAL_JSON_OPTIONS.with_options(tz_aware=False, tzinfo=None) - >>> json_options.tz_aware - False - - .. versionadded:: 3.12 - """ - opts = self._options_dict() - for opt in ("strict_number_long", "datetime_representation", "strict_uuid", "json_mode"): - opts[opt] = kwargs.get(opt, getattr(self, opt)) - opts.update(kwargs) - return JSONOptions(**opts) - - -LEGACY_JSON_OPTIONS: JSONOptions = JSONOptions(json_mode=JSONMode.LEGACY) -""":class:`JSONOptions` for encoding to PyMongo's legacy JSON format. - -.. seealso:: The documentation for :const:`bson.json_util.JSONMode.LEGACY`. - -.. versionadded:: 3.5 -""" - -CANONICAL_JSON_OPTIONS: JSONOptions = JSONOptions(json_mode=JSONMode.CANONICAL) -""":class:`JSONOptions` for Canonical Extended JSON. - -.. seealso:: The documentation for :const:`bson.json_util.JSONMode.CANONICAL`. - -.. versionadded:: 3.5 -""" - -RELAXED_JSON_OPTIONS: JSONOptions = JSONOptions(json_mode=JSONMode.RELAXED) -""":class:`JSONOptions` for Relaxed Extended JSON. - -.. seealso:: The documentation for :const:`bson.json_util.JSONMode.RELAXED`. - -.. versionadded:: 3.5 -""" - -DEFAULT_JSON_OPTIONS: JSONOptions = RELAXED_JSON_OPTIONS -"""The default :class:`JSONOptions` for JSON encoding/decoding. - -The same as :const:`RELAXED_JSON_OPTIONS`. - -.. versionchanged:: 4.0 - Changed from :const:`LEGACY_JSON_OPTIONS` to - :const:`RELAXED_JSON_OPTIONS`. - -.. versionadded:: 3.4 -""" - - -def dumps(obj: Any, *args: Any, **kwargs: Any) -> str: - """Helper function that wraps :func:`json.dumps`. - - Recursive function that handles all BSON types including - :class:`~bson.binary.Binary` and :class:`~bson.code.Code`. - - :param json_options: A :class:`JSONOptions` instance used to modify the - encoding of MongoDB Extended JSON types. Defaults to - :const:`DEFAULT_JSON_OPTIONS`. - - .. versionchanged:: 4.0 - Now outputs MongoDB Relaxed Extended JSON by default (using - :const:`DEFAULT_JSON_OPTIONS`). - - .. versionchanged:: 3.4 - Accepts optional parameter `json_options`. See :class:`JSONOptions`. - """ - json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) - return json.dumps(_json_convert(obj, json_options), *args, **kwargs) - - -def loads(s: Union[str, bytes, bytearray], *args: Any, **kwargs: Any) -> Any: - """Helper function that wraps :func:`json.loads`. - - Automatically passes the object_hook for BSON type conversion. - - Raises ``TypeError``, ``ValueError``, ``KeyError``, or - :exc:`~bson.errors.InvalidId` on invalid MongoDB Extended JSON. - - :param json_options: A :class:`JSONOptions` instance used to modify the - decoding of MongoDB Extended JSON types. Defaults to - :const:`DEFAULT_JSON_OPTIONS`. - - .. versionchanged:: 4.0 - Now loads :class:`datetime.datetime` instances as naive by default. To - load timezone aware instances utilize the `json_options` parameter. - See :ref:`tz_aware_default_change` for an example. - - .. versionchanged:: 3.5 - Parses Relaxed and Canonical Extended JSON as well as PyMongo's legacy - format. Now raises ``TypeError`` or ``ValueError`` when parsing JSON - type wrappers with values of the wrong type or any extra keys. - - .. versionchanged:: 3.4 - Accepts optional parameter `json_options`. See :class:`JSONOptions`. - """ - json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) - # Execution time optimization if json_options.document_class is dict - if json_options.document_class is dict: - kwargs["object_hook"] = lambda obj: object_hook(obj, json_options) - else: - kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook(pairs, json_options) - return json.loads(s, *args, **kwargs) - - -def _json_convert(obj: Any, json_options: JSONOptions = DEFAULT_JSON_OPTIONS) -> Any: - """Recursive helper method that converts BSON types so they can be - converted into json. - """ - if hasattr(obj, "items"): - return {k: _json_convert(v, json_options) for k, v in obj.items()} - elif hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes)): - return [_json_convert(v, json_options) for v in obj] - try: - return default(obj, json_options) - except TypeError: - return obj - - -def object_pairs_hook( - pairs: Sequence[Tuple[str, Any]], json_options: JSONOptions = DEFAULT_JSON_OPTIONS -) -> Any: - return object_hook(json_options.document_class(pairs), json_options) # type:ignore[call-arg] - - -def object_hook(dct: Mapping[str, Any], json_options: JSONOptions = DEFAULT_JSON_OPTIONS) -> Any: - match = None - for k in dct: - if k in _PARSERS_SET: - match = k - break - if match: - return _PARSERS[match](dct, json_options) - return dct - - -def _parse_legacy_regex(doc: Any, dummy0: Any) -> Any: - pattern = doc["$regex"] - # Check if this is the $regex query operator. - if not isinstance(pattern, (str, bytes)): - return doc - flags = 0 - # PyMongo always adds $options but some other tools may not. - for opt in doc.get("$options", ""): - flags |= _RE_OPT_TABLE.get(opt, 0) - return Regex(pattern, flags) - - -def _parse_legacy_uuid(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: - """Decode a JSON legacy $uuid to Python UUID.""" - if len(doc) != 1: - raise TypeError(f"Bad $uuid, extra field(s): {doc}") - if not isinstance(doc["$uuid"], str): - raise TypeError(f"$uuid must be a string: {doc}") - if json_options.uuid_representation == UuidRepresentation.UNSPECIFIED: - return Binary.from_uuid(uuid.UUID(doc["$uuid"])) - else: - return uuid.UUID(doc["$uuid"]) - - -def _binary_or_uuid(data: Any, subtype: int, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: - # special handling for UUID - if subtype in ALL_UUID_SUBTYPES: - uuid_representation = json_options.uuid_representation - binary_value = Binary(data, subtype) - if uuid_representation == UuidRepresentation.UNSPECIFIED: - return binary_value - if subtype == UUID_SUBTYPE: - # Legacy behavior: use STANDARD with binary subtype 4. - uuid_representation = UuidRepresentation.STANDARD - elif uuid_representation == UuidRepresentation.STANDARD: - # subtype == OLD_UUID_SUBTYPE - # Legacy behavior: STANDARD is the same as PYTHON_LEGACY. - uuid_representation = UuidRepresentation.PYTHON_LEGACY - return binary_value.as_uuid(uuid_representation) - - if subtype == 0: - return cast(uuid.UUID, data) - return Binary(data, subtype) - - -def _parse_legacy_binary(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: - if isinstance(doc["$type"], int): - doc["$type"] = "%02x" % doc["$type"] - subtype = int(doc["$type"], 16) - if subtype >= 0xFFFFFF80: # Handle mongoexport values - subtype = int(doc["$type"][6:], 16) - data = base64.b64decode(doc["$binary"].encode()) - return _binary_or_uuid(data, subtype, json_options) - - -def _parse_canonical_binary(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: - binary = doc["$binary"] - b64 = binary["base64"] - subtype = binary["subType"] - if not isinstance(b64, str): - raise TypeError(f"$binary base64 must be a string: {doc}") - if not isinstance(subtype, str) or len(subtype) > 2: - raise TypeError(f"$binary subType must be a string at most 2 characters: {doc}") - if len(binary) != 2: - raise TypeError(f'$binary must include only "base64" and "subType" components: {doc}') - - data = base64.b64decode(b64.encode()) - return _binary_or_uuid(data, int(subtype, 16), json_options) - - -def _parse_canonical_datetime( - doc: Any, json_options: JSONOptions -) -> Union[datetime.datetime, DatetimeMS]: - """Decode a JSON datetime to python datetime.datetime.""" - dtm = doc["$date"] - if len(doc) != 1: - raise TypeError(f"Bad $date, extra field(s): {doc}") - # mongoexport 2.6 and newer - if isinstance(dtm, str): - try: - # Parse offset - if dtm[-1] == "Z": - dt = dtm[:-1] - offset = "Z" - elif dtm[-6] in ("+", "-") and dtm[-3] == ":": - # (+|-)HH:MM - dt = dtm[:-6] - offset = dtm[-6:] - elif dtm[-5] in ("+", "-"): - # (+|-)HHMM - dt = dtm[:-5] - offset = dtm[-5:] - elif dtm[-3] in ("+", "-"): - # (+|-)HH - dt = dtm[:-3] - offset = dtm[-3:] - else: - dt = dtm - offset = "" - except IndexError as exc: - raise ValueError(f"time data {dtm!r} does not match ISO-8601 datetime format") from exc - - # Parse the optional factional seconds portion. - dot_index = dt.rfind(".") - microsecond = 0 - if dot_index != -1: - microsecond = int(float(dt[dot_index:]) * 1000000) - dt = dt[:dot_index] - - aware = datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S").replace( - microsecond=microsecond, tzinfo=utc - ) - - if offset and offset != "Z": - if len(offset) == 6: - hours, minutes = offset[1:].split(":") - secs = int(hours) * 3600 + int(minutes) * 60 - elif len(offset) == 5: - secs = int(offset[1:3]) * 3600 + int(offset[3:]) * 60 - elif len(offset) == 3: - secs = int(offset[1:3]) * 3600 - if offset[0] == "-": - secs *= -1 - aware = aware - datetime.timedelta(seconds=secs) - - if json_options.tz_aware: - if json_options.tzinfo: - aware = aware.astimezone(json_options.tzinfo) - if json_options.datetime_conversion == DatetimeConversion.DATETIME_MS: - return DatetimeMS(aware) - return aware - else: - aware_tzinfo_none = aware.replace(tzinfo=None) - if json_options.datetime_conversion == DatetimeConversion.DATETIME_MS: - return DatetimeMS(aware_tzinfo_none) - return aware_tzinfo_none - return _millis_to_datetime(int(dtm), cast("CodecOptions[Any]", json_options)) - - -def _parse_canonical_oid(doc: Any, dummy0: Any) -> ObjectId: - """Decode a JSON ObjectId to bson.objectid.ObjectId.""" - if len(doc) != 1: - raise TypeError(f"Bad $oid, extra field(s): {doc}") - return ObjectId(doc["$oid"]) - - -def _parse_canonical_symbol(doc: Any, dummy0: Any) -> str: - """Decode a JSON symbol to Python string.""" - symbol = doc["$symbol"] - if len(doc) != 1: - raise TypeError(f"Bad $symbol, extra field(s): {doc}") - return str(symbol) - - -def _parse_canonical_code(doc: Any, dummy0: Any) -> Code: - """Decode a JSON code to bson.code.Code.""" - for key in doc: - if key not in ("$code", "$scope"): - raise TypeError(f"Bad $code, extra field(s): {doc}") - return Code(doc["$code"], scope=doc.get("$scope")) - - -def _parse_canonical_regex(doc: Any, dummy0: Any) -> Regex[str]: - """Decode a JSON regex to bson.regex.Regex.""" - regex = doc["$regularExpression"] - if len(doc) != 1: - raise TypeError(f"Bad $regularExpression, extra field(s): {doc}") - if len(regex) != 2: - raise TypeError( - f'Bad $regularExpression must include only "pattern and "options" components: {doc}' - ) - opts = regex["options"] - if not isinstance(opts, str): - raise TypeError( - "Bad $regularExpression options, options must be string, was type %s" % (type(opts)) - ) - return Regex(regex["pattern"], opts) - - -def _parse_canonical_dbref(doc: Any, dummy0: Any) -> Any: - """Decode a JSON DBRef to bson.dbref.DBRef.""" - if ( - isinstance(doc.get("$ref"), str) - and "$id" in doc - and isinstance(doc.get("$db"), (str, type(None))) - ): - return DBRef(doc.pop("$ref"), doc.pop("$id"), database=doc.pop("$db", None), **doc) - return doc - - -def _parse_canonical_dbpointer(doc: Any, dummy0: Any) -> Any: - """Decode a JSON (deprecated) DBPointer to bson.dbref.DBRef.""" - dbref = doc["$dbPointer"] - if len(doc) != 1: - raise TypeError(f"Bad $dbPointer, extra field(s): {doc}") - if isinstance(dbref, DBRef): - dbref_doc = dbref.as_doc() - # DBPointer must not contain $db in its value. - if dbref.database is not None: - raise TypeError(f"Bad $dbPointer, extra field $db: {dbref_doc}") - if not isinstance(dbref.id, ObjectId): - raise TypeError(f"Bad $dbPointer, $id must be an ObjectId: {dbref_doc}") - if len(dbref_doc) != 2: - raise TypeError(f"Bad $dbPointer, extra field(s) in DBRef: {dbref_doc}") - return dbref - else: - raise TypeError(f"Bad $dbPointer, expected a DBRef: {doc}") - - -def _parse_canonical_int32(doc: Any, dummy0: Any) -> int: - """Decode a JSON int32 to python int.""" - i_str = doc["$numberInt"] - if len(doc) != 1: - raise TypeError(f"Bad $numberInt, extra field(s): {doc}") - if not isinstance(i_str, str): - raise TypeError(f"$numberInt must be string: {doc}") - return int(i_str) - - -def _parse_canonical_int64(doc: Any, dummy0: Any) -> Int64: - """Decode a JSON int64 to bson.int64.Int64.""" - l_str = doc["$numberLong"] - if len(doc) != 1: - raise TypeError(f"Bad $numberLong, extra field(s): {doc}") - return Int64(l_str) - - -def _parse_canonical_double(doc: Any, dummy0: Any) -> float: - """Decode a JSON double to python float.""" - d_str = doc["$numberDouble"] - if len(doc) != 1: - raise TypeError(f"Bad $numberDouble, extra field(s): {doc}") - if not isinstance(d_str, str): - raise TypeError(f"$numberDouble must be string: {doc}") - return float(d_str) - - -def _parse_canonical_decimal128(doc: Any, dummy0: Any) -> Decimal128: - """Decode a JSON decimal128 to bson.decimal128.Decimal128.""" - d_str = doc["$numberDecimal"] - if len(doc) != 1: - raise TypeError(f"Bad $numberDecimal, extra field(s): {doc}") - if not isinstance(d_str, str): - raise TypeError(f"$numberDecimal must be string: {doc}") - return Decimal128(d_str) - - -def _parse_canonical_minkey(doc: Any, dummy0: Any) -> MinKey: - """Decode a JSON MinKey to bson.min_key.MinKey.""" - if type(doc["$minKey"]) is not int or doc["$minKey"] != 1: # noqa: E721 - raise TypeError(f"$minKey value must be 1: {doc}") - if len(doc) != 1: - raise TypeError(f"Bad $minKey, extra field(s): {doc}") - return MinKey() - - -def _parse_canonical_maxkey(doc: Any, dummy0: Any) -> MaxKey: - """Decode a JSON MaxKey to bson.max_key.MaxKey.""" - if type(doc["$maxKey"]) is not int or doc["$maxKey"] != 1: # noqa: E721 - raise TypeError("$maxKey value must be 1: %s", (doc,)) - if len(doc) != 1: - raise TypeError(f"Bad $minKey, extra field(s): {doc}") - return MaxKey() - - -def _parse_binary(doc: Any, json_options: JSONOptions) -> Union[Binary, uuid.UUID]: - if "$type" in doc: - return _parse_legacy_binary(doc, json_options) - else: - return _parse_canonical_binary(doc, json_options) - - -def _parse_timestamp(doc: Any, dummy0: Any) -> Timestamp: - tsp = doc["$timestamp"] - return Timestamp(tsp["t"], tsp["i"]) - - -_PARSERS: dict[str, Callable[[Any, JSONOptions], Any]] = { - "$oid": _parse_canonical_oid, - "$ref": _parse_canonical_dbref, - "$date": _parse_canonical_datetime, - "$regex": _parse_legacy_regex, - "$minKey": _parse_canonical_minkey, - "$maxKey": _parse_canonical_maxkey, - "$binary": _parse_binary, - "$code": _parse_canonical_code, - "$uuid": _parse_legacy_uuid, - "$undefined": lambda _, _1: None, - "$numberLong": _parse_canonical_int64, - "$timestamp": _parse_timestamp, - "$numberDecimal": _parse_canonical_decimal128, - "$dbPointer": _parse_canonical_dbpointer, - "$regularExpression": _parse_canonical_regex, - "$symbol": _parse_canonical_symbol, - "$numberInt": _parse_canonical_int32, - "$numberDouble": _parse_canonical_double, -} -_PARSERS_SET = set(_PARSERS) - - -def _encode_binary(data: bytes, subtype: int, json_options: JSONOptions) -> Any: - if json_options.json_mode == JSONMode.LEGACY: - return {"$binary": base64.b64encode(data).decode(), "$type": "%02x" % subtype} - return {"$binary": {"base64": base64.b64encode(data).decode(), "subType": "%02x" % subtype}} - - -def _encode_datetimems(obj: Any, json_options: JSONOptions) -> dict: - if ( - json_options.datetime_representation == DatetimeRepresentation.ISO8601 - and 0 <= int(obj) <= _MAX_UTC_MS - ): - return _encode_datetime(obj.as_datetime(), json_options) - elif json_options.datetime_representation == DatetimeRepresentation.LEGACY: - return {"$date": int(obj)} - return {"$date": {"$numberLong": str(int(obj))}} - - -def _encode_code(obj: Code, json_options: JSONOptions) -> dict: - if obj.scope is None: - return {"$code": str(obj)} - else: - return {"$code": str(obj), "$scope": _json_convert(obj.scope, json_options)} - - -def _encode_int64(obj: Int64, json_options: JSONOptions) -> Any: - if json_options.strict_number_long: - return {"$numberLong": str(obj)} - else: - return int(obj) - - -def _encode_noop(obj: Any, dummy0: Any) -> Any: - return obj - - -def _encode_regex(obj: Any, json_options: JSONOptions) -> dict: - flags = "" - if obj.flags & re.IGNORECASE: - flags += "i" - if obj.flags & re.LOCALE: - flags += "l" - if obj.flags & re.MULTILINE: - flags += "m" - if obj.flags & re.DOTALL: - flags += "s" - if obj.flags & re.UNICODE: - flags += "u" - if obj.flags & re.VERBOSE: - flags += "x" - if isinstance(obj.pattern, str): - pattern = obj.pattern - else: - pattern = obj.pattern.decode("utf-8") - if json_options.json_mode == JSONMode.LEGACY: - return {"$regex": pattern, "$options": flags} - return {"$regularExpression": {"pattern": pattern, "options": flags}} - - -def _encode_int(obj: int, json_options: JSONOptions) -> Any: - if json_options.json_mode == JSONMode.CANONICAL: - if -_INT32_MAX <= obj < _INT32_MAX: - return {"$numberInt": str(obj)} - return {"$numberLong": str(obj)} - return obj - - -def _encode_float(obj: float, json_options: JSONOptions) -> Any: - if json_options.json_mode != JSONMode.LEGACY: - if math.isnan(obj): - return {"$numberDouble": "NaN"} - elif math.isinf(obj): - representation = "Infinity" if obj > 0 else "-Infinity" - return {"$numberDouble": representation} - elif json_options.json_mode == JSONMode.CANONICAL: - # repr() will return the shortest string guaranteed to produce the - # original value, when float() is called on it. - return {"$numberDouble": str(repr(obj))} - return obj - - -def _encode_datetime(obj: datetime.datetime, json_options: JSONOptions) -> dict: - if json_options.datetime_representation == DatetimeRepresentation.ISO8601: - if not obj.tzinfo: - obj = obj.replace(tzinfo=utc) - assert obj.tzinfo is not None - if obj >= EPOCH_AWARE: - off = obj.tzinfo.utcoffset(obj) - if (off.days, off.seconds, off.microseconds) == (0, 0, 0): # type: ignore - tz_string = "Z" - else: - tz_string = obj.strftime("%z") - millis = int(obj.microsecond / 1000) - fracsecs = ".%03d" % (millis,) if millis else "" - return { - "$date": "{}{}{}".format(obj.strftime("%Y-%m-%dT%H:%M:%S"), fracsecs, tz_string) - } - - millis = _datetime_to_millis(obj) - if json_options.datetime_representation == DatetimeRepresentation.LEGACY: - return {"$date": millis} - return {"$date": {"$numberLong": str(millis)}} - - -def _encode_bytes(obj: bytes, json_options: JSONOptions) -> dict: - return _encode_binary(obj, 0, json_options) - - -def _encode_binary_obj(obj: Binary, json_options: JSONOptions) -> dict: - return _encode_binary(obj, obj.subtype, json_options) - - -def _encode_uuid(obj: uuid.UUID, json_options: JSONOptions) -> dict: - if json_options.strict_uuid: - binval = Binary.from_uuid(obj, uuid_representation=json_options.uuid_representation) - return _encode_binary(binval, binval.subtype, json_options) - else: - return {"$uuid": obj.hex} - - -def _encode_objectid(obj: ObjectId, dummy0: Any) -> dict: - return {"$oid": str(obj)} - - -def _encode_timestamp(obj: Timestamp, dummy0: Any) -> dict: - return {"$timestamp": {"t": obj.time, "i": obj.inc}} - - -def _encode_decimal128(obj: Timestamp, dummy0: Any) -> dict: - return {"$numberDecimal": str(obj)} - - -def _encode_dbref(obj: DBRef, json_options: JSONOptions) -> dict: - return _json_convert(obj.as_doc(), json_options=json_options) - - -def _encode_minkey(dummy0: Any, dummy1: Any) -> dict: - return {"$minKey": 1} - - -def _encode_maxkey(dummy0: Any, dummy1: Any) -> dict: - return {"$maxKey": 1} - - -# Encoders for BSON types -# Each encoder function's signature is: -# - obj: a Python data type, e.g. a Python int for _encode_int -# - json_options: a JSONOptions -_ENCODERS: dict[Type, Callable[[Any, JSONOptions], Any]] = { - bool: _encode_noop, - bytes: _encode_bytes, - datetime.datetime: _encode_datetime, - DatetimeMS: _encode_datetimems, - float: _encode_float, - int: _encode_int, - str: _encode_noop, - type(None): _encode_noop, - uuid.UUID: _encode_uuid, - Binary: _encode_binary_obj, - Int64: _encode_int64, - Code: _encode_code, - DBRef: _encode_dbref, - MaxKey: _encode_maxkey, - MinKey: _encode_minkey, - ObjectId: _encode_objectid, - Regex: _encode_regex, - RE_TYPE: _encode_regex, - Timestamp: _encode_timestamp, - Decimal128: _encode_decimal128, -} - -# Map each _type_marker to its encoder for faster lookup. -_MARKERS: dict[int, Callable[[Any, JSONOptions], Any]] = {} -for _typ in _ENCODERS: - if hasattr(_typ, "_type_marker"): - _MARKERS[_typ._type_marker] = _ENCODERS[_typ] - -_BUILT_IN_TYPES = tuple(t for t in _ENCODERS) - - -def default(obj: Any, json_options: JSONOptions = DEFAULT_JSON_OPTIONS) -> Any: - # First see if the type is already cached. KeyError will only ever - # happen once per subtype. - try: - return _ENCODERS[type(obj)](obj, json_options) - except KeyError: - pass - - # Second, fall back to trying _type_marker. This has to be done - # before the loop below since users could subclass one of our - # custom types that subclasses a python built-in (e.g. Binary) - if hasattr(obj, "_type_marker"): - marker = obj._type_marker - if marker in _MARKERS: - func = _MARKERS[marker] - # Cache this type for faster subsequent lookup. - _ENCODERS[type(obj)] = func - return func(obj, json_options) - - # Third, test each base type. This will only happen once for - # a subtype of a supported base type. - for base in _BUILT_IN_TYPES: - if isinstance(obj, base): - func = _ENCODERS[base] - # Cache this type for faster subsequent lookup. - _ENCODERS[type(obj)] = func - return func(obj, json_options) - - raise TypeError("%r is not JSON serializable" % obj) - - -def _get_str_size(obj: Any) -> int: - return len(obj) - - -def _get_datetime_size(obj: datetime.datetime) -> int: - return 5 + len(str(obj.time())) - - -def _get_regex_size(obj: Regex) -> int: - return 18 + len(obj.pattern) - - -def _get_dbref_size(obj: DBRef) -> int: - return 34 + len(obj.collection) - - -_CONSTANT_SIZE_TABLE: dict[Any, int] = { - ObjectId: 28, - int: 11, - Int64: 11, - Decimal128: 11, - Timestamp: 14, - MinKey: 8, - MaxKey: 8, -} - -_VARIABLE_SIZE_TABLE: dict[Any, Callable[[Any], int]] = { - str: _get_str_size, - bytes: _get_str_size, - datetime.datetime: _get_datetime_size, - Regex: _get_regex_size, - DBRef: _get_dbref_size, -} - - -def get_size(obj: Any, max_size: int, current_size: int = 0) -> int: - """Recursively finds size of objects""" - if current_size >= max_size: - return current_size - - obj_type = type(obj) - - # Check to see if the obj has a constant size estimate - try: - return _CONSTANT_SIZE_TABLE[obj_type] - except KeyError: - pass - - # Check to see if the obj has a variable but simple size estimate - try: - return _VARIABLE_SIZE_TABLE[obj_type](obj) - except KeyError: - pass - - # Special cases that require recursion - if obj_type == Code: - if obj.scope: - current_size += ( - 5 + get_size(obj.scope, max_size, current_size) + len(obj) - len(obj.scope) - ) - else: - current_size += 5 + len(obj) - elif obj_type == dict: - for k, v in obj.items(): - current_size += get_size(k, max_size, current_size) - current_size += get_size(v, max_size, current_size) - if current_size >= max_size: - return current_size - elif hasattr(obj, "__iter__"): - for i in obj: - current_size += get_size(i, max_size, current_size) - if current_size >= max_size: - return current_size - return current_size - - -def _truncate_documents(obj: Any, max_length: int) -> Tuple[Any, int]: - """Recursively truncate documents as needed to fit inside max_length characters.""" - if max_length <= 0: - return None, 0 - remaining = max_length - if hasattr(obj, "items"): - truncated: Any = {} - for k, v in obj.items(): - truncated_v, remaining = _truncate_documents(v, remaining) - if truncated_v: - truncated[k] = truncated_v - if remaining <= 0: - break - return truncated, remaining - elif hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes)): - truncated: Any = [] # type:ignore[no-redef] - for v in obj: - truncated_v, remaining = _truncate_documents(v, remaining) - if truncated_v: - truncated.append(truncated_v) - if remaining <= 0: - break - return truncated, remaining - else: - return _truncate(obj, remaining) - - -def _truncate(obj: Any, remaining: int) -> Tuple[Any, int]: - size = get_size(obj, remaining) - - if size <= remaining: - return obj, remaining - size - else: - try: - truncated = obj[:remaining] - except TypeError: - truncated = obj - return truncated, remaining - size diff --git a/venv/Lib/site-packages/bson/max_key.py b/venv/Lib/site-packages/bson/max_key.py deleted file mode 100644 index 445e12f..0000000 --- a/venv/Lib/site-packages/bson/max_key.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2010-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Representation for the MongoDB internal MaxKey type.""" -from __future__ import annotations - -from typing import Any - - -class MaxKey: - """MongoDB internal MaxKey type.""" - - __slots__ = () - - _type_marker = 127 - - def __getstate__(self) -> Any: - return {} - - def __setstate__(self, state: Any) -> None: - pass - - def __eq__(self, other: Any) -> bool: - return isinstance(other, MaxKey) - - def __hash__(self) -> int: - return hash(self._type_marker) - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __le__(self, other: Any) -> bool: - return isinstance(other, MaxKey) - - def __lt__(self, dummy: Any) -> bool: - return False - - def __ge__(self, dummy: Any) -> bool: - return True - - def __gt__(self, other: Any) -> bool: - return not isinstance(other, MaxKey) - - def __repr__(self) -> str: - return "MaxKey()" diff --git a/venv/Lib/site-packages/bson/min_key.py b/venv/Lib/site-packages/bson/min_key.py deleted file mode 100644 index 37828dc..0000000 --- a/venv/Lib/site-packages/bson/min_key.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2010-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Representation for the MongoDB internal MinKey type.""" -from __future__ import annotations - -from typing import Any - - -class MinKey: - """MongoDB internal MinKey type.""" - - __slots__ = () - - _type_marker = 255 - - def __getstate__(self) -> Any: - return {} - - def __setstate__(self, state: Any) -> None: - pass - - def __eq__(self, other: Any) -> bool: - return isinstance(other, MinKey) - - def __hash__(self) -> int: - return hash(self._type_marker) - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __le__(self, dummy: Any) -> bool: - return True - - def __lt__(self, other: Any) -> bool: - return not isinstance(other, MinKey) - - def __ge__(self, other: Any) -> bool: - return isinstance(other, MinKey) - - def __gt__(self, dummy: Any) -> bool: - return False - - def __repr__(self) -> str: - return "MinKey()" diff --git a/venv/Lib/site-packages/bson/objectid.py b/venv/Lib/site-packages/bson/objectid.py deleted file mode 100644 index 970c4e5..0000000 --- a/venv/Lib/site-packages/bson/objectid.py +++ /dev/null @@ -1,274 +0,0 @@ -# Copyright 2009-2015 MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for working with MongoDB ObjectIds.""" -from __future__ import annotations - -import binascii -import datetime -import os -import struct -import threading -import time -from random import SystemRandom -from typing import Any, NoReturn, Optional, Type, Union - -from bson.datetime_ms import _datetime_to_millis -from bson.errors import InvalidId -from bson.tz_util import utc - -_MAX_COUNTER_VALUE = 0xFFFFFF -_PACK_INT = struct.Struct(">I").pack -_PACK_INT_RANDOM = struct.Struct(">I5s").pack -_UNPACK_INT = struct.Struct(">I").unpack - - -def _raise_invalid_id(oid: str) -> NoReturn: - raise InvalidId( - "%r is not a valid ObjectId, it must be a 12-byte input" - " or a 24-character hex string" % oid - ) - - -def _random_bytes() -> bytes: - """Get the 5-byte random field of an ObjectId.""" - return os.urandom(5) - - -class ObjectId: - """A MongoDB ObjectId.""" - - _pid = os.getpid() - - _inc = SystemRandom().randint(0, _MAX_COUNTER_VALUE) - _inc_lock = threading.Lock() - - __random = _random_bytes() - - __slots__ = ("__id",) - - _type_marker = 7 - - def __init__(self, oid: Optional[Union[str, ObjectId, bytes]] = None) -> None: - """Initialize a new ObjectId. - - An ObjectId is a 12-byte unique identifier consisting of: - - - a 4-byte value representing the seconds since the Unix epoch, - - a 5-byte random value, - - a 3-byte counter, starting with a random value. - - By default, ``ObjectId()`` creates a new unique identifier. The - optional parameter `oid` can be an :class:`ObjectId`, or any 12 - :class:`bytes`. - - For example, the 12 bytes b'foo-bar-quux' do not follow the ObjectId - specification but they are acceptable input:: - - >>> ObjectId(b'foo-bar-quux') - ObjectId('666f6f2d6261722d71757578') - - `oid` can also be a :class:`str` of 24 hex digits:: - - >>> ObjectId('0123456789ab0123456789ab') - ObjectId('0123456789ab0123456789ab') - - Raises :class:`~bson.errors.InvalidId` if `oid` is not 12 bytes nor - 24 hex digits, or :class:`TypeError` if `oid` is not an accepted type. - - :param oid: a valid ObjectId. - - .. seealso:: The MongoDB documentation on `ObjectIds `_. - - .. versionchanged:: 3.8 - :class:`~bson.objectid.ObjectId` now implements the `ObjectID - specification version 0.2 - `_. - """ - if oid is None: - self.__generate() - elif isinstance(oid, bytes) and len(oid) == 12: - self.__id = oid - else: - self.__validate(oid) - - @classmethod - def from_datetime(cls: Type[ObjectId], generation_time: datetime.datetime) -> ObjectId: - """Create a dummy ObjectId instance with a specific generation time. - - This method is useful for doing range queries on a field - containing :class:`ObjectId` instances. - - .. warning:: - It is not safe to insert a document containing an ObjectId - generated using this method. This method deliberately - eliminates the uniqueness guarantee that ObjectIds - generally provide. ObjectIds generated with this method - should be used exclusively in queries. - - `generation_time` will be converted to UTC. Naive datetime - instances will be treated as though they already contain UTC. - - An example using this helper to get documents where ``"_id"`` - was generated before January 1, 2010 would be: - - >>> gen_time = datetime.datetime(2010, 1, 1) - >>> dummy_id = ObjectId.from_datetime(gen_time) - >>> result = collection.find({"_id": {"$lt": dummy_id}}) - - :param generation_time: :class:`~datetime.datetime` to be used - as the generation time for the resulting ObjectId. - """ - oid = ( - _PACK_INT(_datetime_to_millis(generation_time) // 1000) - + b"\x00\x00\x00\x00\x00\x00\x00\x00" - ) - return cls(oid) - - @classmethod - def is_valid(cls: Type[ObjectId], oid: Any) -> bool: - """Checks if a `oid` string is valid or not. - - :param oid: the object id to validate - - .. versionadded:: 2.3 - """ - if not oid: - return False - - try: - ObjectId(oid) - return True - except (InvalidId, TypeError): - return False - - @classmethod - def _random(cls) -> bytes: - """Generate a 5-byte random number once per process.""" - pid = os.getpid() - if pid != cls._pid: - cls._pid = pid - cls.__random = _random_bytes() - return cls.__random - - def __generate(self) -> None: - """Generate a new value for this ObjectId.""" - with ObjectId._inc_lock: - inc = ObjectId._inc - ObjectId._inc = (inc + 1) % (_MAX_COUNTER_VALUE + 1) - - # 4 bytes current time, 5 bytes random, 3 bytes inc. - self.__id = _PACK_INT_RANDOM(int(time.time()), ObjectId._random()) + _PACK_INT(inc)[1:4] - - def __validate(self, oid: Any) -> None: - """Validate and use the given id for this ObjectId. - - Raises TypeError if id is not an instance of :class:`str`, - :class:`bytes`, or ObjectId. Raises InvalidId if it is not a - valid ObjectId. - - :param oid: a valid ObjectId - """ - if isinstance(oid, ObjectId): - self.__id = oid.binary - elif isinstance(oid, str): - if len(oid) == 24: - try: - self.__id = bytes.fromhex(oid) - except (TypeError, ValueError): - _raise_invalid_id(oid) - else: - _raise_invalid_id(oid) - else: - raise TypeError(f"id must be an instance of (bytes, str, ObjectId), not {type(oid)}") - - @property - def binary(self) -> bytes: - """12-byte binary representation of this ObjectId.""" - return self.__id - - @property - def generation_time(self) -> datetime.datetime: - """A :class:`datetime.datetime` instance representing the time of - generation for this :class:`ObjectId`. - - The :class:`datetime.datetime` is timezone aware, and - represents the generation time in UTC. It is precise to the - second. - """ - timestamp = _UNPACK_INT(self.__id[0:4])[0] - return datetime.datetime.fromtimestamp(timestamp, utc) - - def __getstate__(self) -> bytes: - """Return value of object for pickling. - needed explicitly because __slots__() defined. - """ - return self.__id - - def __setstate__(self, value: Any) -> None: - """Explicit state set from pickling""" - # Provide backwards compatibility with OIDs - # pickled with pymongo-1.9 or older. - if isinstance(value, dict): - oid = value["_ObjectId__id"] - else: - oid = value - # ObjectIds pickled in python 2.x used `str` for __id. - # In python 3.x this has to be converted to `bytes` - # by encoding latin-1. - if isinstance(oid, str): - self.__id = oid.encode("latin-1") - else: - self.__id = oid - - def __str__(self) -> str: - return binascii.hexlify(self.__id).decode() - - def __repr__(self) -> str: - return f"ObjectId('{self!s}')" - - def __eq__(self, other: Any) -> bool: - if isinstance(other, ObjectId): - return self.__id == other.binary - return NotImplemented - - def __ne__(self, other: Any) -> bool: - if isinstance(other, ObjectId): - return self.__id != other.binary - return NotImplemented - - def __lt__(self, other: Any) -> bool: - if isinstance(other, ObjectId): - return self.__id < other.binary - return NotImplemented - - def __le__(self, other: Any) -> bool: - if isinstance(other, ObjectId): - return self.__id <= other.binary - return NotImplemented - - def __gt__(self, other: Any) -> bool: - if isinstance(other, ObjectId): - return self.__id > other.binary - return NotImplemented - - def __ge__(self, other: Any) -> bool: - if isinstance(other, ObjectId): - return self.__id >= other.binary - return NotImplemented - - def __hash__(self) -> int: - """Get a hash value for this :class:`ObjectId`.""" - return hash(self.__id) diff --git a/venv/Lib/site-packages/bson/py.typed b/venv/Lib/site-packages/bson/py.typed deleted file mode 100644 index 0f40570..0000000 --- a/venv/Lib/site-packages/bson/py.typed +++ /dev/null @@ -1,2 +0,0 @@ -# PEP-561 Support File. -# "Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing". diff --git a/venv/Lib/site-packages/bson/raw_bson.py b/venv/Lib/site-packages/bson/raw_bson.py deleted file mode 100644 index 2ce5314..0000000 --- a/venv/Lib/site-packages/bson/raw_bson.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2015-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for representing raw BSON documents. - -Inserting and Retrieving RawBSONDocuments -========================================= - -Example: Moving a document between different databases/collections - -.. doctest:: - - >>> import bson - >>> from pymongo import MongoClient - >>> from bson.raw_bson import RawBSONDocument - >>> client = MongoClient(document_class=RawBSONDocument) - >>> client.drop_database("db") - >>> client.drop_database("replica_db") - >>> db = client.db - >>> result = db.test.insert_many( - ... [{"_id": 1, "a": 1}, {"_id": 2, "b": 1}, {"_id": 3, "c": 1}, {"_id": 4, "d": 1}] - ... ) - >>> replica_db = client.replica_db - >>> for doc in db.test.find(): - ... print(f"raw document: {doc.raw}") - ... print(f"decoded document: {bson.decode(doc.raw)}") - ... result = replica_db.test.insert_one(doc) - ... - raw document: b'...' - decoded document: {'_id': 1, 'a': 1} - raw document: b'...' - decoded document: {'_id': 2, 'b': 1} - raw document: b'...' - decoded document: {'_id': 3, 'c': 1} - raw document: b'...' - decoded document: {'_id': 4, 'd': 1} - -For use cases like moving documents across different databases or writing binary -blobs to disk, using raw BSON documents provides better speed and avoids the -overhead of decoding or encoding BSON. -""" -from __future__ import annotations - -from typing import Any, ItemsView, Iterator, Mapping, Optional - -from bson import _get_object_size, _raw_to_dict -from bson.codec_options import _RAW_BSON_DOCUMENT_MARKER, CodecOptions -from bson.codec_options import DEFAULT_CODEC_OPTIONS as DEFAULT - - -def _inflate_bson( - bson_bytes: bytes, codec_options: CodecOptions[RawBSONDocument], raw_array: bool = False -) -> dict[str, Any]: - """Inflates the top level fields of a BSON document. - - :param bson_bytes: the BSON bytes that compose this document - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions` whose ``document_class`` - must be :class:`RawBSONDocument`. - """ - return _raw_to_dict(bson_bytes, 4, len(bson_bytes) - 1, codec_options, {}, raw_array=raw_array) - - -class RawBSONDocument(Mapping[str, Any]): - """Representation for a MongoDB document that provides access to the raw - BSON bytes that compose it. - - Only when a field is accessed or modified within the document does - RawBSONDocument decode its bytes. - """ - - __slots__ = ("__raw", "__inflated_doc", "__codec_options") - _type_marker = _RAW_BSON_DOCUMENT_MARKER - __codec_options: CodecOptions[RawBSONDocument] - - def __init__( - self, bson_bytes: bytes, codec_options: Optional[CodecOptions[RawBSONDocument]] = None - ) -> None: - """Create a new :class:`RawBSONDocument` - - :class:`RawBSONDocument` is a representation of a BSON document that - provides access to the underlying raw BSON bytes. Only when a field is - accessed or modified within the document does RawBSONDocument decode - its bytes. - - :class:`RawBSONDocument` implements the ``Mapping`` abstract base - class from the standard library so it can be used like a read-only - ``dict``:: - - >>> from bson import encode - >>> raw_doc = RawBSONDocument(encode({'_id': 'my_doc'})) - >>> raw_doc.raw - b'...' - >>> raw_doc['_id'] - 'my_doc' - - :param bson_bytes: the BSON bytes that compose this document - :param codec_options: An instance of - :class:`~bson.codec_options.CodecOptions` whose ``document_class`` - must be :class:`RawBSONDocument`. The default is - :attr:`DEFAULT_RAW_BSON_OPTIONS`. - - .. versionchanged:: 3.8 - :class:`RawBSONDocument` now validates that the ``bson_bytes`` - passed in represent a single bson document. - - .. versionchanged:: 3.5 - If a :class:`~bson.codec_options.CodecOptions` is passed in, its - `document_class` must be :class:`RawBSONDocument`. - """ - self.__raw = bson_bytes - self.__inflated_doc: Optional[Mapping[str, Any]] = None - # Can't default codec_options to DEFAULT_RAW_BSON_OPTIONS in signature, - # it refers to this class RawBSONDocument. - if codec_options is None: - codec_options = DEFAULT_RAW_BSON_OPTIONS - elif not issubclass(codec_options.document_class, RawBSONDocument): - raise TypeError( - "RawBSONDocument cannot use CodecOptions with document " - f"class {codec_options.document_class}" - ) - self.__codec_options = codec_options - # Validate the bson object size. - _get_object_size(bson_bytes, 0, len(bson_bytes)) - - @property - def raw(self) -> bytes: - """The raw BSON bytes composing this document.""" - return self.__raw - - def items(self) -> ItemsView[str, Any]: - """Lazily decode and iterate elements in this document.""" - return self.__inflated.items() - - @property - def __inflated(self) -> Mapping[str, Any]: - if self.__inflated_doc is None: - # We already validated the object's size when this document was - # created, so no need to do that again. - self.__inflated_doc = self._inflate_bson(self.__raw, self.__codec_options) - return self.__inflated_doc - - @staticmethod - def _inflate_bson( - bson_bytes: bytes, codec_options: CodecOptions[RawBSONDocument] - ) -> Mapping[str, Any]: - return _inflate_bson(bson_bytes, codec_options) - - def __getitem__(self, item: str) -> Any: - return self.__inflated[item] - - def __iter__(self) -> Iterator[str]: - return iter(self.__inflated) - - def __len__(self) -> int: - return len(self.__inflated) - - def __eq__(self, other: Any) -> bool: - if isinstance(other, RawBSONDocument): - return self.__raw == other.raw - return NotImplemented - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.raw!r}, codec_options={self.__codec_options!r})" - - -class _RawArrayBSONDocument(RawBSONDocument): - """A RawBSONDocument that only expands sub-documents and arrays when accessed.""" - - @staticmethod - def _inflate_bson( - bson_bytes: bytes, codec_options: CodecOptions[RawBSONDocument] - ) -> Mapping[str, Any]: - return _inflate_bson(bson_bytes, codec_options, raw_array=True) - - -DEFAULT_RAW_BSON_OPTIONS: CodecOptions[RawBSONDocument] = DEFAULT.with_options( - document_class=RawBSONDocument -) -_RAW_ARRAY_BSON_OPTIONS: CodecOptions[_RawArrayBSONDocument] = DEFAULT.with_options( - document_class=_RawArrayBSONDocument -) -"""The default :class:`~bson.codec_options.CodecOptions` for -:class:`RawBSONDocument`. -""" diff --git a/venv/Lib/site-packages/bson/regex.py b/venv/Lib/site-packages/bson/regex.py deleted file mode 100644 index 60cff4f..0000000 --- a/venv/Lib/site-packages/bson/regex.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright 2013-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for representing MongoDB regular expressions.""" -from __future__ import annotations - -import re -from typing import Any, Generic, Pattern, Type, TypeVar, Union - -from bson._helpers import _getstate_slots, _setstate_slots -from bson.son import RE_TYPE - - -def str_flags_to_int(str_flags: str) -> int: - flags = 0 - if "i" in str_flags: - flags |= re.IGNORECASE - if "l" in str_flags: - flags |= re.LOCALE - if "m" in str_flags: - flags |= re.MULTILINE - if "s" in str_flags: - flags |= re.DOTALL - if "u" in str_flags: - flags |= re.UNICODE - if "x" in str_flags: - flags |= re.VERBOSE - - return flags - - -_T = TypeVar("_T", str, bytes) - - -class Regex(Generic[_T]): - """BSON regular expression data.""" - - __slots__ = ("pattern", "flags") - - __getstate__ = _getstate_slots - __setstate__ = _setstate_slots - - _type_marker = 11 - - @classmethod - def from_native(cls: Type[Regex[Any]], regex: Pattern[_T]) -> Regex[_T]: - """Convert a Python regular expression into a ``Regex`` instance. - - Note that in Python 3, a regular expression compiled from a - :class:`str` has the ``re.UNICODE`` flag set. If it is undesirable - to store this flag in a BSON regular expression, unset it first:: - - >>> pattern = re.compile('.*') - >>> regex = Regex.from_native(pattern) - >>> regex.flags ^= re.UNICODE - >>> db.collection.insert_one({'pattern': regex}) - - :param regex: A regular expression object from ``re.compile()``. - - .. warning:: - Python regular expressions use a different syntax and different - set of flags than MongoDB, which uses `PCRE`_. A regular - expression retrieved from the server may not compile in - Python, or may match a different set of strings in Python than - when used in a MongoDB query. - - .. _PCRE: http://www.pcre.org/ - """ - if not isinstance(regex, RE_TYPE): - raise TypeError("regex must be a compiled regular expression, not %s" % type(regex)) - - return Regex(regex.pattern, regex.flags) - - def __init__(self, pattern: _T, flags: Union[str, int] = 0) -> None: - """BSON regular expression data. - - This class is useful to store and retrieve regular expressions that are - incompatible with Python's regular expression dialect. - - :param pattern: string - :param flags: an integer bitmask, or a string of flag - characters like "im" for IGNORECASE and MULTILINE - """ - if not isinstance(pattern, (str, bytes)): - raise TypeError("pattern must be a string, not %s" % type(pattern)) - self.pattern: _T = pattern - - if isinstance(flags, str): - self.flags = str_flags_to_int(flags) - elif isinstance(flags, int): - self.flags = flags - else: - raise TypeError("flags must be a string or int, not %s" % type(flags)) - - def __eq__(self, other: Any) -> bool: - if isinstance(other, Regex): - return self.pattern == other.pattern and self.flags == other.flags - else: - return NotImplemented - - __hash__ = None # type: ignore - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __repr__(self) -> str: - return f"Regex({self.pattern!r}, {self.flags!r})" - - def try_compile(self) -> Pattern[_T]: - """Compile this :class:`Regex` as a Python regular expression. - - .. warning:: - Python regular expressions use a different syntax and different - set of flags than MongoDB, which uses `PCRE`_. A regular - expression retrieved from the server may not compile in - Python, or may match a different set of strings in Python than - when used in a MongoDB query. :meth:`try_compile()` may raise - :exc:`re.error`. - - .. _PCRE: http://www.pcre.org/ - """ - return re.compile(self.pattern, self.flags) diff --git a/venv/Lib/site-packages/bson/son.py b/venv/Lib/site-packages/bson/son.py deleted file mode 100644 index 24275fc..0000000 --- a/venv/Lib/site-packages/bson/son.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright 2009-present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for creating and manipulating SON, the Serialized Ocument Notation. - -Regular dictionaries can be used instead of SON objects, but not when the order -of keys is important. A SON object can be used just like a normal Python -dictionary. -""" -from __future__ import annotations - -import copy -import re -from collections.abc import Mapping as _Mapping -from typing import ( - Any, - Dict, - Iterable, - Iterator, - Mapping, - Optional, - Pattern, - Tuple, - Type, - TypeVar, - Union, - cast, -) - -# This sort of sucks, but seems to be as good as it gets... -# This is essentially the same as re._pattern_type -RE_TYPE: Type[Pattern[Any]] = type(re.compile("")) - -_Key = TypeVar("_Key") -_Value = TypeVar("_Value") -_T = TypeVar("_T") - - -class SON(Dict[_Key, _Value]): - """SON data. - - A subclass of dict that maintains ordering of keys and provides a - few extra niceties for dealing with SON. SON provides an API - similar to collections.OrderedDict. - """ - - __keys: list[Any] - - def __init__( - self, - data: Optional[Union[Mapping[_Key, _Value], Iterable[Tuple[_Key, _Value]]]] = None, - **kwargs: Any, - ) -> None: - self.__keys = [] - dict.__init__(self) - self.update(data) - self.update(kwargs) - - def __new__(cls: Type[SON[_Key, _Value]], *args: Any, **kwargs: Any) -> SON[_Key, _Value]: - instance = super().__new__(cls, *args, **kwargs) - instance.__keys = [] - return instance - - def __repr__(self) -> str: - result = [] - for key in self.__keys: - result.append(f"({key!r}, {self[key]!r})") - return "SON([%s])" % ", ".join(result) - - def __setitem__(self, key: _Key, value: _Value) -> None: - if key not in self.__keys: - self.__keys.append(key) - dict.__setitem__(self, key, value) - - def __delitem__(self, key: _Key) -> None: - self.__keys.remove(key) - dict.__delitem__(self, key) - - def copy(self) -> SON[_Key, _Value]: - other: SON[_Key, _Value] = SON() - other.update(self) - return other - - # TODO this is all from UserDict.DictMixin. it could probably be made more - # efficient. - # second level definitions support higher levels - def __iter__(self) -> Iterator[_Key]: - yield from self.__keys - - def has_key(self, key: _Key) -> bool: - return key in self.__keys - - def iterkeys(self) -> Iterator[_Key]: - return self.__iter__() - - # fourth level uses definitions from lower levels - def itervalues(self) -> Iterator[_Value]: - for _, v in self.items(): - yield v - - def values(self) -> list[_Value]: # type: ignore[override] - return [v for _, v in self.items()] - - def clear(self) -> None: - self.__keys = [] - super().clear() - - def setdefault(self, key: _Key, default: _Value) -> _Value: - try: - return self[key] - except KeyError: - self[key] = default - return default - - def pop(self, key: _Key, *args: Union[_Value, _T]) -> Union[_Value, _T]: - if len(args) > 1: - raise TypeError("pop expected at most 2 arguments, got " + repr(1 + len(args))) - try: - value = self[key] - except KeyError: - if args: - return args[0] - raise - del self[key] - return value - - def popitem(self) -> Tuple[_Key, _Value]: - try: - k, v = next(iter(self.items())) - except StopIteration: - raise KeyError("container is empty") from None - del self[k] - return (k, v) - - def update(self, other: Optional[Any] = None, **kwargs: _Value) -> None: # type: ignore[override] - # Make progressively weaker assumptions about "other" - if other is None: - pass - elif hasattr(other, "items"): - for k, v in other.items(): - self[k] = v - elif hasattr(other, "keys"): - for k in other: - self[k] = other[k] - else: - for k, v in other: - self[k] = v - if kwargs: - self.update(kwargs) - - def get( # type: ignore[override] - self, key: _Key, default: Optional[Union[_Value, _T]] = None - ) -> Union[_Value, _T, None]: - try: - return self[key] - except KeyError: - return default - - def __eq__(self, other: Any) -> bool: - """Comparison to another SON is order-sensitive while comparison to a - regular dictionary is order-insensitive. - """ - if isinstance(other, SON): - return len(self) == len(other) and list(self.items()) == list(other.items()) - return cast(bool, self.to_dict() == other) - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __len__(self) -> int: - return len(self.__keys) - - def to_dict(self) -> dict[_Key, _Value]: - """Convert a SON document to a normal Python dictionary instance. - - This is trickier than just *dict(...)* because it needs to be - recursive. - """ - - def transform_value(value: Any) -> Any: - if isinstance(value, list): - return [transform_value(v) for v in value] - elif isinstance(value, _Mapping): - return {k: transform_value(v) for k, v in value.items()} - else: - return value - - return cast("dict[_Key, _Value]", transform_value(dict(self))) - - def __deepcopy__(self, memo: dict[int, SON[_Key, _Value]]) -> SON[_Key, _Value]: - out: SON[_Key, _Value] = SON() - val_id = id(self) - if val_id in memo: - return memo[val_id] - memo[val_id] = out - for k, v in self.items(): - if not isinstance(v, RE_TYPE): - v = copy.deepcopy(v, memo) # noqa: PLW2901 - out[k] = v - return out diff --git a/venv/Lib/site-packages/bson/time64.c b/venv/Lib/site-packages/bson/time64.c deleted file mode 100644 index a21fbb9..0000000 --- a/venv/Lib/site-packages/bson/time64.c +++ /dev/null @@ -1,781 +0,0 @@ -/* - -Copyright (c) 2007-2010 Michael G Schwern - -This software originally derived from Paul Sheer's pivotal_gmtime_r.c. - -The MIT License: - -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. - -*/ - -/* - -Programmers who have available to them 64-bit time values as a 'long -long' type can use cbson_localtime64_r() and cbson_gmtime64_r() which correctly -converts the time even on 32-bit systems. Whether you have 64-bit time -values will depend on the operating system. - -cbson_localtime64_r() is a 64-bit equivalent of localtime_r(). - -cbson_gmtime64_r() is a 64-bit equivalent of gmtime_r(). - -*/ - -#ifdef _MSC_VER - #define _CRT_SECURE_NO_WARNINGS -#endif - -/* Including Python.h fixes issues with interpreters built with -std=c99. */ -#define PY_SSIZE_T_CLEAN -#include "Python.h" - -#include -#include "time64.h" -#include "time64_limits.h" - - -/* Spec says except for stftime() and the _r() functions, these - all return static memory. Stabbings! */ -static struct TM Static_Return_Date; - -static const int days_in_month[2][12] = { - {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, - {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, -}; - -static const int julian_days_by_month[2][12] = { - {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, - {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}, -}; - -static const int length_of_year[2] = { 365, 366 }; - -/* Some numbers relating to the gregorian cycle */ -static const Year years_in_gregorian_cycle = 400; -#define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1) -static const Time64_T seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL; - -/* Year range we can trust the time functions with */ -#define MAX_SAFE_YEAR 2037 -#define MIN_SAFE_YEAR 1971 - -/* 28 year Julian calendar cycle */ -#define SOLAR_CYCLE_LENGTH 28 - -/* Year cycle from MAX_SAFE_YEAR down. */ -static const int safe_years_high[SOLAR_CYCLE_LENGTH] = { - 2016, 2017, 2018, 2019, - 2020, 2021, 2022, 2023, - 2024, 2025, 2026, 2027, - 2028, 2029, 2030, 2031, - 2032, 2033, 2034, 2035, - 2036, 2037, 2010, 2011, - 2012, 2013, 2014, 2015 -}; - -/* Year cycle from MIN_SAFE_YEAR up */ -static const int safe_years_low[SOLAR_CYCLE_LENGTH] = { - 1996, 1997, 1998, 1971, - 1972, 1973, 1974, 1975, - 1976, 1977, 1978, 1979, - 1980, 1981, 1982, 1983, - 1984, 1985, 1986, 1987, - 1988, 1989, 1990, 1991, - 1992, 1993, 1994, 1995, -}; - -/* Let's assume people are going to be looking for dates in the future. - Let's provide some cheats so you can skip ahead. - This has a 4x speed boost when near 2008. -*/ -/* Number of days since epoch on Jan 1st, 2008 GMT */ -#define CHEAT_DAYS (1199145600 / 24 / 60 / 60) -#define CHEAT_YEARS 108 - -#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0) -#define _TIME64_WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) - -#ifdef USE_SYSTEM_LOCALTIME -# define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \ - (a) <= SYSTEM_LOCALTIME_MAX && \ - (a) >= SYSTEM_LOCALTIME_MIN \ -) -#else -# define SHOULD_USE_SYSTEM_LOCALTIME(a) (0) -#endif - -#ifdef USE_SYSTEM_GMTIME -# define SHOULD_USE_SYSTEM_GMTIME(a) ( \ - (a) <= SYSTEM_GMTIME_MAX && \ - (a) >= SYSTEM_GMTIME_MIN \ -) -#else -# define SHOULD_USE_SYSTEM_GMTIME(a) (0) -#endif - -/* Multi varadic macros are a C99 thing, alas */ -#ifdef TIME_64_DEBUG -# define TIME64_TRACE(format) (fprintf(stderr, format)) -# define TIME64_TRACE1(format, var1) (fprintf(stderr, format, var1)) -# define TIME64_TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2)) -# define TIME64_TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3)) -#else -# define TIME64_TRACE(format) ((void)0) -# define TIME64_TRACE1(format, var1) ((void)0) -# define TIME64_TRACE2(format, var1, var2) ((void)0) -# define TIME64_TRACE3(format, var1, var2, var3) ((void)0) -#endif - - -static int is_exception_century(Year year) -{ - int is_exception = ((year % 100 == 0) && !(year % 400 == 0)); - TIME64_TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no"); - - return(is_exception); -} - - -/* Compare two dates. - The result is like cmp. - Ignores things like gmtoffset and dst -*/ -int cbson_cmp_date( const struct TM* left, const struct tm* right ) { - if( left->tm_year > right->tm_year ) - return 1; - else if( left->tm_year < right->tm_year ) - return -1; - - if( left->tm_mon > right->tm_mon ) - return 1; - else if( left->tm_mon < right->tm_mon ) - return -1; - - if( left->tm_mday > right->tm_mday ) - return 1; - else if( left->tm_mday < right->tm_mday ) - return -1; - - if( left->tm_hour > right->tm_hour ) - return 1; - else if( left->tm_hour < right->tm_hour ) - return -1; - - if( left->tm_min > right->tm_min ) - return 1; - else if( left->tm_min < right->tm_min ) - return -1; - - if( left->tm_sec > right->tm_sec ) - return 1; - else if( left->tm_sec < right->tm_sec ) - return -1; - - return 0; -} - - -/* Check if a date is safely inside a range. - The intention is to check if its a few days inside. -*/ -int cbson_date_in_safe_range( const struct TM* date, const struct tm* min, const struct tm* max ) { - if( cbson_cmp_date(date, min) == -1 ) - return 0; - - if( cbson_cmp_date(date, max) == 1 ) - return 0; - - return 1; -} - - -/* timegm() is not in the C or POSIX spec, but it is such a useful - extension I would be remiss in leaving it out. Also I need it - for cbson_localtime64() -*/ -Time64_T cbson_timegm64(const struct TM *date) { - Time64_T days = 0; - Time64_T seconds = 0; - Year year; - Year orig_year = (Year)date->tm_year; - int cycles = 0; - - if( orig_year > 100 ) { - cycles = (int)((orig_year - 100) / 400); - orig_year -= cycles * 400; - days += (Time64_T)cycles * days_in_gregorian_cycle; - } - else if( orig_year < -300 ) { - cycles = (int)((orig_year - 100) / 400); - orig_year -= cycles * 400; - days += (Time64_T)cycles * days_in_gregorian_cycle; - } - TIME64_TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year); - - if( orig_year > 70 ) { - year = 70; - while( year < orig_year ) { - days += length_of_year[IS_LEAP(year)]; - year++; - } - } - else if ( orig_year < 70 ) { - year = 69; - do { - days -= length_of_year[IS_LEAP(year)]; - year--; - } while( year >= orig_year ); - } - - days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon]; - days += date->tm_mday - 1; - - seconds = days * 60 * 60 * 24; - - seconds += date->tm_hour * 60 * 60; - seconds += date->tm_min * 60; - seconds += date->tm_sec; - - return(seconds); -} - - -#ifndef NDEBUG -static int check_tm(struct TM *tm) -{ - /* Don't forget leap seconds */ - assert(tm->tm_sec >= 0); - assert(tm->tm_sec <= 61); - - assert(tm->tm_min >= 0); - assert(tm->tm_min <= 59); - - assert(tm->tm_hour >= 0); - assert(tm->tm_hour <= 23); - - assert(tm->tm_mday >= 1); - assert(tm->tm_mday <= days_in_month[IS_LEAP(tm->tm_year)][tm->tm_mon]); - - assert(tm->tm_mon >= 0); - assert(tm->tm_mon <= 11); - - assert(tm->tm_wday >= 0); - assert(tm->tm_wday <= 6); - - assert(tm->tm_yday >= 0); - assert(tm->tm_yday <= length_of_year[IS_LEAP(tm->tm_year)]); - -#ifdef HAS_TM_TM_GMTOFF - assert(tm->tm_gmtoff >= -24 * 60 * 60); - assert(tm->tm_gmtoff <= 24 * 60 * 60); -#endif - - return 1; -} -#endif - - -/* The exceptional centuries without leap years cause the cycle to - shift by 16 -*/ -static Year cycle_offset(Year year) -{ - const Year start_year = 2000; - Year year_diff = year - start_year; - Year exceptions; - - if( year > start_year ) - year_diff--; - - exceptions = year_diff / 100; - exceptions -= year_diff / 400; - - TIME64_TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n", - year, exceptions, year_diff); - - return exceptions * 16; -} - -/* For a given year after 2038, pick the latest possible matching - year in the 28 year calendar cycle. - - A matching year... - 1) Starts on the same day of the week. - 2) Has the same leap year status. - - This is so the calendars match up. - - Also the previous year must match. When doing Jan 1st you might - wind up on Dec 31st the previous year when doing a -UTC time zone. - - Finally, the next year must have the same start day of week. This - is for Dec 31st with a +UTC time zone. - It doesn't need the same leap year status since we only care about - January 1st. -*/ -static int safe_year(const Year year) -{ - int safe_year = 0; - Year year_cycle; - - if( year >= MIN_SAFE_YEAR && year <= MAX_SAFE_YEAR ) { - return (int)year; - } - - year_cycle = year + cycle_offset(year); - - /* safe_years_low is off from safe_years_high by 8 years */ - if( year < MIN_SAFE_YEAR ) - year_cycle -= 8; - - /* Change non-leap xx00 years to an equivalent */ - if( is_exception_century(year) ) - year_cycle += 11; - - /* Also xx01 years, since the previous year will be wrong */ - if( is_exception_century(year - 1) ) - year_cycle += 17; - - year_cycle %= SOLAR_CYCLE_LENGTH; - if( year_cycle < 0 ) - year_cycle = SOLAR_CYCLE_LENGTH + year_cycle; - - assert( year_cycle >= 0 ); - assert( year_cycle < SOLAR_CYCLE_LENGTH ); - if( year < MIN_SAFE_YEAR ) - safe_year = safe_years_low[year_cycle]; - else if( year > MAX_SAFE_YEAR ) - safe_year = safe_years_high[year_cycle]; - else - assert(0); - - TIME64_TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n", - year, year_cycle, safe_year); - - assert(safe_year <= MAX_SAFE_YEAR && safe_year >= MIN_SAFE_YEAR); - - return safe_year; -} - - -void pymongo_copy_tm_to_TM64(const struct tm *src, struct TM *dest) { - if( src == NULL ) { - memset(dest, 0, sizeof(*dest)); - } - else { -# ifdef USE_TM64 - dest->tm_sec = src->tm_sec; - dest->tm_min = src->tm_min; - dest->tm_hour = src->tm_hour; - dest->tm_mday = src->tm_mday; - dest->tm_mon = src->tm_mon; - dest->tm_year = (Year)src->tm_year; - dest->tm_wday = src->tm_wday; - dest->tm_yday = src->tm_yday; - dest->tm_isdst = src->tm_isdst; - -# ifdef HAS_TM_TM_GMTOFF - dest->tm_gmtoff = src->tm_gmtoff; -# endif - -# ifdef HAS_TM_TM_ZONE - dest->tm_zone = src->tm_zone; -# endif - -# else - /* They're the same type */ - memcpy(dest, src, sizeof(*dest)); -# endif - } -} - - -void cbson_copy_TM64_to_tm(const struct TM *src, struct tm *dest) { - if( src == NULL ) { - memset(dest, 0, sizeof(*dest)); - } - else { -# ifdef USE_TM64 - dest->tm_sec = src->tm_sec; - dest->tm_min = src->tm_min; - dest->tm_hour = src->tm_hour; - dest->tm_mday = src->tm_mday; - dest->tm_mon = src->tm_mon; - dest->tm_year = (int)src->tm_year; - dest->tm_wday = src->tm_wday; - dest->tm_yday = src->tm_yday; - dest->tm_isdst = src->tm_isdst; - -# ifdef HAS_TM_TM_GMTOFF - dest->tm_gmtoff = src->tm_gmtoff; -# endif - -# ifdef HAS_TM_TM_ZONE - dest->tm_zone = src->tm_zone; -# endif - -# else - /* They're the same type */ - memcpy(dest, src, sizeof(*dest)); -# endif - } -} - - -/* Simulate localtime_r() to the best of our ability */ -struct tm * cbson_fake_localtime_r(const time_t *time, struct tm *result) { - const struct tm *static_result = localtime(time); - - assert(result != NULL); - - if( static_result == NULL ) { - memset(result, 0, sizeof(*result)); - return NULL; - } - else { - memcpy(result, static_result, sizeof(*result)); - return result; - } -} - - -/* Simulate gmtime_r() to the best of our ability */ -struct tm * cbson_fake_gmtime_r(const time_t *time, struct tm *result) { - const struct tm *static_result = gmtime(time); - - assert(result != NULL); - - if( static_result == NULL ) { - memset(result, 0, sizeof(*result)); - return NULL; - } - else { - memcpy(result, static_result, sizeof(*result)); - return result; - } -} - - -static Time64_T seconds_between_years(Year left_year, Year right_year) { - int increment = (left_year > right_year) ? 1 : -1; - Time64_T seconds = 0; - int cycles; - - if( left_year > 2400 ) { - cycles = (int)((left_year - 2400) / 400); - left_year -= cycles * 400; - seconds += cycles * seconds_in_gregorian_cycle; - } - else if( left_year < 1600 ) { - cycles = (int)((left_year - 1600) / 400); - left_year += cycles * 400; - seconds += cycles * seconds_in_gregorian_cycle; - } - - while( left_year != right_year ) { - seconds += length_of_year[IS_LEAP(right_year - 1900)] * 60 * 60 * 24; - right_year += increment; - } - - return seconds * increment; -} - - -Time64_T cbson_mktime64(const struct TM *input_date) { - struct tm safe_date; - struct TM date; - Time64_T time; - Year year = input_date->tm_year + 1900; - - if( cbson_date_in_safe_range(input_date, &SYSTEM_MKTIME_MIN, &SYSTEM_MKTIME_MAX) ) - { - cbson_copy_TM64_to_tm(input_date, &safe_date); - return (Time64_T)mktime(&safe_date); - } - - /* Have to make the year safe in date else it won't fit in safe_date */ - date = *input_date; - date.tm_year = safe_year(year) - 1900; - cbson_copy_TM64_to_tm(&date, &safe_date); - - time = (Time64_T)mktime(&safe_date); - - time += seconds_between_years(year, (Year)(safe_date.tm_year + 1900)); - - return time; -} - - -/* Because I think mktime() is a crappy name */ -Time64_T timelocal64(const struct TM *date) { - return cbson_mktime64(date); -} - - -struct TM *cbson_gmtime64_r (const Time64_T *in_time, struct TM *p) -{ - int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday; - Time64_T v_tm_tday; - int leap; - Time64_T m; - Time64_T time = *in_time; - Year year = 70; - int cycles = 0; - - assert(p != NULL); - -#ifdef USE_SYSTEM_GMTIME - /* Use the system gmtime() if time_t is small enough */ - if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) { - time_t safe_time = (time_t)*in_time; - struct tm safe_date; - GMTIME_R(&safe_time, &safe_date); - - pymongo_copy_tm_to_TM64(&safe_date, p); - assert(check_tm(p)); - - return p; - } -#endif - -#ifdef HAS_TM_TM_GMTOFF - p->tm_gmtoff = 0; -#endif - p->tm_isdst = 0; - -#ifdef HAS_TM_TM_ZONE - p->tm_zone = "UTC"; -#endif - - v_tm_sec = (int)(time % 60); - time /= 60; - v_tm_min = (int)(time % 60); - time /= 60; - v_tm_hour = (int)(time % 24); - time /= 24; - v_tm_tday = time; - - _TIME64_WRAP (v_tm_sec, v_tm_min, 60); - _TIME64_WRAP (v_tm_min, v_tm_hour, 60); - _TIME64_WRAP (v_tm_hour, v_tm_tday, 24); - - v_tm_wday = (int)((v_tm_tday + 4) % 7); - if (v_tm_wday < 0) - v_tm_wday += 7; - m = v_tm_tday; - - if (m >= CHEAT_DAYS) { - year = CHEAT_YEARS; - m -= CHEAT_DAYS; - } - - if (m >= 0) { - /* Gregorian cycles, this is huge optimization for distant times */ - cycles = (int)(m / (Time64_T) days_in_gregorian_cycle); - if( cycles ) { - m -= (cycles * (Time64_T) days_in_gregorian_cycle); - year += (cycles * years_in_gregorian_cycle); - } - - /* Years */ - leap = IS_LEAP (year); - while (m >= (Time64_T) length_of_year[leap]) { - m -= (Time64_T) length_of_year[leap]; - year++; - leap = IS_LEAP (year); - } - - /* Months */ - v_tm_mon = 0; - while (m >= (Time64_T) days_in_month[leap][v_tm_mon]) { - m -= (Time64_T) days_in_month[leap][v_tm_mon]; - v_tm_mon++; - } - } else { - year--; - - /* Gregorian cycles */ - cycles = (int)((m / (Time64_T) days_in_gregorian_cycle) + 1); - if( cycles ) { - m -= (cycles * (Time64_T) days_in_gregorian_cycle); - year += (cycles * years_in_gregorian_cycle); - } - - /* Years */ - leap = IS_LEAP (year); - while (m < (Time64_T) -length_of_year[leap]) { - m += (Time64_T) length_of_year[leap]; - year--; - leap = IS_LEAP (year); - } - - /* Months */ - v_tm_mon = 11; - while (m < (Time64_T) -days_in_month[leap][v_tm_mon]) { - m += (Time64_T) days_in_month[leap][v_tm_mon]; - v_tm_mon--; - } - m += (Time64_T) days_in_month[leap][v_tm_mon]; - } - - p->tm_year = (int)year; - if( p->tm_year != year ) { -#ifdef EOVERFLOW - errno = EOVERFLOW; -#endif - return NULL; - } - - /* At this point m is less than a year so casting to an int is safe */ - p->tm_mday = (int) m + 1; - p->tm_yday = julian_days_by_month[leap][v_tm_mon] + (int)m; - p->tm_sec = v_tm_sec; - p->tm_min = v_tm_min; - p->tm_hour = v_tm_hour; - p->tm_mon = v_tm_mon; - p->tm_wday = v_tm_wday; - - assert(check_tm(p)); - - return p; -} - - -struct TM *cbson_localtime64_r (const Time64_T *time, struct TM *local_tm) -{ - time_t safe_time; - struct tm safe_date; - struct TM gm_tm; - Year orig_year; - int month_diff; - - assert(local_tm != NULL); - -#ifdef USE_SYSTEM_LOCALTIME - /* Use the system localtime() if time_t is small enough */ - if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) { - safe_time = (time_t)*time; - - TIME64_TRACE1("Using system localtime for %lld\n", *time); - - LOCALTIME_R(&safe_time, &safe_date); - - pymongo_copy_tm_to_TM64(&safe_date, local_tm); - assert(check_tm(local_tm)); - - return local_tm; - } -#endif - - if( cbson_gmtime64_r(time, &gm_tm) == NULL ) { - TIME64_TRACE1("cbson_gmtime64_r returned null for %lld\n", *time); - return NULL; - } - - orig_year = gm_tm.tm_year; - - if (gm_tm.tm_year > (2037 - 1900) || - gm_tm.tm_year < (1970 - 1900) - ) - { - TIME64_TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year); - gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900; - } - - safe_time = (time_t)cbson_timegm64(&gm_tm); - if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) { - TIME64_TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time); - return NULL; - } - - pymongo_copy_tm_to_TM64(&safe_date, local_tm); - - local_tm->tm_year = (int)orig_year; - if( local_tm->tm_year != orig_year ) { - TIME64_TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n", - (Year)local_tm->tm_year, (Year)orig_year); - -#ifdef EOVERFLOW - errno = EOVERFLOW; -#endif - return NULL; - } - - - month_diff = local_tm->tm_mon - gm_tm.tm_mon; - - /* When localtime is Dec 31st previous year and - gmtime is Jan 1st next year. - */ - if( month_diff == 11 ) { - local_tm->tm_year--; - } - - /* When localtime is Jan 1st, next year and - gmtime is Dec 31st, previous year. - */ - if( month_diff == -11 ) { - local_tm->tm_year++; - } - - /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st - in a non-leap xx00. There is one point in the cycle - we can't account for which the safe xx00 year is a leap - year. So we need to correct for Dec 31st coming out as - the 366th day of the year. - */ - if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 ) - local_tm->tm_yday--; - - assert(check_tm(local_tm)); - - return local_tm; -} - - -int cbson_valid_tm_wday( const struct TM* date ) { - if( 0 <= date->tm_wday && date->tm_wday <= 6 ) - return 1; - else - return 0; -} - -int cbson_valid_tm_mon( const struct TM* date ) { - if( 0 <= date->tm_mon && date->tm_mon <= 11 ) - return 1; - else - return 0; -} - - -/* Non-thread safe versions of the above */ -struct TM *cbson_localtime64(const Time64_T *time) { -#ifdef _MSC_VER - _tzset(); -#else - tzset(); -#endif - return cbson_localtime64_r(time, &Static_Return_Date); -} - -struct TM *cbson_gmtime64(const Time64_T *time) { - return cbson_gmtime64_r(time, &Static_Return_Date); -} diff --git a/venv/Lib/site-packages/bson/time64.h b/venv/Lib/site-packages/bson/time64.h deleted file mode 100644 index 6321eb3..0000000 --- a/venv/Lib/site-packages/bson/time64.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef TIME64_H -# define TIME64_H - -#include -#include "time64_config.h" - -/* Set our custom types */ -typedef INT_64_T Int64; -typedef Int64 Time64_T; -typedef Int64 Year; - - -/* A copy of the tm struct but with a 64 bit year */ -struct TM64 { - int tm_sec; - int tm_min; - int tm_hour; - int tm_mday; - int tm_mon; - Year tm_year; - int tm_wday; - int tm_yday; - int tm_isdst; - -#ifdef HAS_TM_TM_GMTOFF - long tm_gmtoff; -#endif - -#ifdef HAS_TM_TM_ZONE - char *tm_zone; -#endif -}; - - -/* Decide which tm struct to use */ -#ifdef USE_TM64 -#define TM TM64 -#else -#define TM tm -#endif - - -/* Declare public functions */ -struct TM *cbson_gmtime64_r (const Time64_T *, struct TM *); -struct TM *cbson_localtime64_r (const Time64_T *, struct TM *); -struct TM *cbson_gmtime64 (const Time64_T *); -struct TM *cbson_localtime64 (const Time64_T *); - -Time64_T cbson_timegm64 (const struct TM *); -Time64_T cbson_mktime64 (const struct TM *); -Time64_T timelocal64 (const struct TM *); - - -/* Not everyone has gm/localtime_r(), provide a replacement */ -#ifdef HAS_LOCALTIME_R -# define LOCALTIME_R(clock, result) localtime_r(clock, result) -#else -# define LOCALTIME_R(clock, result) cbson_fake_localtime_r(clock, result) -#endif -#ifdef HAS_GMTIME_R -# define GMTIME_R(clock, result) gmtime_r(clock, result) -#else -# define GMTIME_R(clock, result) cbson_fake_gmtime_r(clock, result) -#endif - - -#endif diff --git a/venv/Lib/site-packages/bson/time64_config.h b/venv/Lib/site-packages/bson/time64_config.h deleted file mode 100644 index 9d4c111..0000000 --- a/venv/Lib/site-packages/bson/time64_config.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Configuration - ------------- - Define as appropriate for your system. - Sensible defaults provided. -*/ - - -#ifndef TIME64_CONFIG_H -# define TIME64_CONFIG_H - -/* Debugging - TIME_64_DEBUG - Define if you want debugging messages -*/ -/* #define TIME_64_DEBUG */ - - -/* INT_64_T - A 64 bit integer type to use to store time and others. - Must be defined. -*/ -#define INT_64_T long long - - -/* USE_TM64 - Should we use a 64 bit safe replacement for tm? This will - let you go past year 2 billion but the struct will be incompatible - with tm. Conversion functions will be provided. -*/ -/* #define USE_TM64 */ - - -/* Availability of system functions. - - HAS_GMTIME_R - Define if your system has gmtime_r() - - HAS_LOCALTIME_R - Define if your system has localtime_r() - - HAS_TIMEGM - Define if your system has timegm(), a GNU extension. -*/ -#if !defined(WIN32) && !defined(_MSC_VER) -#define HAS_GMTIME_R -#define HAS_LOCALTIME_R -#endif -/* #define HAS_TIMEGM */ - - -/* Details of non-standard tm struct elements. - - HAS_TM_TM_GMTOFF - True if your tm struct has a "tm_gmtoff" element. - A BSD extension. - - HAS_TM_TM_ZONE - True if your tm struct has a "tm_zone" element. - A BSD extension. -*/ -/* #define HAS_TM_TM_GMTOFF */ -/* #define HAS_TM_TM_ZONE */ - - -/* USE_SYSTEM_LOCALTIME - USE_SYSTEM_GMTIME - USE_SYSTEM_MKTIME - USE_SYSTEM_TIMEGM - Should we use the system functions if the time is inside their range? - Your system localtime() is probably more accurate, but our gmtime() is - fast and safe. -*/ -#define USE_SYSTEM_LOCALTIME -/* #define USE_SYSTEM_GMTIME */ -#define USE_SYSTEM_MKTIME -/* #define USE_SYSTEM_TIMEGM */ - -#endif /* TIME64_CONFIG_H */ diff --git a/venv/Lib/site-packages/bson/time64_limits.h b/venv/Lib/site-packages/bson/time64_limits.h deleted file mode 100644 index 1d30607..0000000 --- a/venv/Lib/site-packages/bson/time64_limits.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - Maximum and minimum inputs your system's respective time functions - can correctly handle. time64.h will use your system functions if - the input falls inside these ranges and corresponding USE_SYSTEM_* - constant is defined. -*/ - -#ifndef TIME64_LIMITS_H -#define TIME64_LIMITS_H - -/* Max/min for localtime() */ -#define SYSTEM_LOCALTIME_MAX 2147483647 -#define SYSTEM_LOCALTIME_MIN -2147483647-1 - -/* Max/min for gmtime() */ -#define SYSTEM_GMTIME_MAX 2147483647 -#define SYSTEM_GMTIME_MIN -2147483647-1 - -/* Max/min for mktime() */ -static const struct tm SYSTEM_MKTIME_MAX = { - 7, - 14, - 19, - 18, - 0, - 138, - 1, - 17, - 0 -#ifdef HAS_TM_TM_GMTOFF - ,-28800 -#endif -#ifdef HAS_TM_TM_ZONE - ,"PST" -#endif -}; - -static const struct tm SYSTEM_MKTIME_MIN = { - 52, - 45, - 12, - 13, - 11, - 1, - 5, - 346, - 0 -#ifdef HAS_TM_TM_GMTOFF - ,-28800 -#endif -#ifdef HAS_TM_TM_ZONE - ,"PST" -#endif -}; - -/* Max/min for timegm() */ -#ifdef HAS_TIMEGM -static const struct tm SYSTEM_TIMEGM_MAX = { - 7, - 14, - 3, - 19, - 0, - 138, - 2, - 18, - 0 - #ifdef HAS_TM_TM_GMTOFF - ,0 - #endif - #ifdef HAS_TM_TM_ZONE - ,"UTC" - #endif -}; - -static const struct tm SYSTEM_TIMEGM_MIN = { - 52, - 45, - 20, - 13, - 11, - 1, - 5, - 346, - 0 - #ifdef HAS_TM_TM_GMTOFF - ,0 - #endif - #ifdef HAS_TM_TM_ZONE - ,"UTC" - #endif -}; -#endif /* HAS_TIMEGM */ - -#endif /* TIME64_LIMITS_H */ diff --git a/venv/Lib/site-packages/bson/timestamp.py b/venv/Lib/site-packages/bson/timestamp.py deleted file mode 100644 index 949bd7b..0000000 --- a/venv/Lib/site-packages/bson/timestamp.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright 2010-2015 MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tools for representing MongoDB internal Timestamps.""" -from __future__ import annotations - -import calendar -import datetime -from typing import Any, Union - -from bson._helpers import _getstate_slots, _setstate_slots -from bson.tz_util import utc - -UPPERBOUND = 4294967296 - - -class Timestamp: - """MongoDB internal timestamps used in the opLog.""" - - __slots__ = ("__time", "__inc") - - __getstate__ = _getstate_slots - __setstate__ = _setstate_slots - - _type_marker = 17 - - def __init__(self, time: Union[datetime.datetime, int], inc: int) -> None: - """Create a new :class:`Timestamp`. - - This class is only for use with the MongoDB opLog. If you need - to store a regular timestamp, please use a - :class:`~datetime.datetime`. - - Raises :class:`TypeError` if `time` is not an instance of - :class: `int` or :class:`~datetime.datetime`, or `inc` is not - an instance of :class:`int`. Raises :class:`ValueError` if - `time` or `inc` is not in [0, 2**32). - - :param time: time in seconds since epoch UTC, or a naive UTC - :class:`~datetime.datetime`, or an aware - :class:`~datetime.datetime` - :param inc: the incrementing counter - """ - if isinstance(time, datetime.datetime): - offset = time.utcoffset() - if offset is not None: - time = time - offset - time = int(calendar.timegm(time.timetuple())) - if not isinstance(time, int): - raise TypeError(f"time must be an instance of int, not {type(time)}") - if not isinstance(inc, int): - raise TypeError(f"inc must be an instance of int, not {type(inc)}") - if not 0 <= time < UPPERBOUND: - raise ValueError("time must be contained in [0, 2**32)") - if not 0 <= inc < UPPERBOUND: - raise ValueError("inc must be contained in [0, 2**32)") - - self.__time = time - self.__inc = inc - - @property - def time(self) -> int: - """Get the time portion of this :class:`Timestamp`.""" - return self.__time - - @property - def inc(self) -> int: - """Get the inc portion of this :class:`Timestamp`.""" - return self.__inc - - def __eq__(self, other: Any) -> bool: - if isinstance(other, Timestamp): - return self.__time == other.time and self.__inc == other.inc - else: - return NotImplemented - - def __hash__(self) -> int: - return hash(self.time) ^ hash(self.inc) - - def __ne__(self, other: Any) -> bool: - return not self == other - - def __lt__(self, other: Any) -> bool: - if isinstance(other, Timestamp): - return (self.time, self.inc) < (other.time, other.inc) - return NotImplemented - - def __le__(self, other: Any) -> bool: - if isinstance(other, Timestamp): - return (self.time, self.inc) <= (other.time, other.inc) - return NotImplemented - - def __gt__(self, other: Any) -> bool: - if isinstance(other, Timestamp): - return (self.time, self.inc) > (other.time, other.inc) - return NotImplemented - - def __ge__(self, other: Any) -> bool: - if isinstance(other, Timestamp): - return (self.time, self.inc) >= (other.time, other.inc) - return NotImplemented - - def __repr__(self) -> str: - return f"Timestamp({self.__time}, {self.__inc})" - - def as_datetime(self) -> datetime.datetime: - """Return a :class:`~datetime.datetime` instance corresponding - to the time portion of this :class:`Timestamp`. - - The returned datetime's timezone is UTC. - """ - return datetime.datetime.fromtimestamp(self.__time, utc) diff --git a/venv/Lib/site-packages/bson/typings.py b/venv/Lib/site-packages/bson/typings.py deleted file mode 100644 index b80c661..0000000 --- a/venv/Lib/site-packages/bson/typings.py +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright 2023-Present MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Type aliases used by bson""" -from __future__ import annotations - -from typing import TYPE_CHECKING, Any, Mapping, MutableMapping, TypeVar, Union - -if TYPE_CHECKING: - from array import array - from mmap import mmap - - from bson.raw_bson import RawBSONDocument - - -# Common Shared Types. -_DocumentOut = Union[MutableMapping[str, Any], "RawBSONDocument"] -_DocumentType = TypeVar("_DocumentType", bound=Mapping[str, Any]) -_DocumentTypeArg = TypeVar("_DocumentTypeArg", bound=Mapping[str, Any]) -_ReadableBuffer = Union[bytes, memoryview, "mmap", "array"] diff --git a/venv/Lib/site-packages/bson/tz_util.py b/venv/Lib/site-packages/bson/tz_util.py deleted file mode 100644 index 4d31c04..0000000 --- a/venv/Lib/site-packages/bson/tz_util.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2010-2015 MongoDB, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Timezone related utilities for BSON.""" -from __future__ import annotations - -from datetime import datetime, timedelta, tzinfo -from typing import Optional, Tuple, Union - -ZERO: timedelta = timedelta(0) - - -class FixedOffset(tzinfo): - """Fixed offset timezone, in minutes east from UTC. - - Implementation based from the Python `standard library documentation - `_. - Defining __getinitargs__ enables pickling / copying. - """ - - def __init__(self, offset: Union[float, timedelta], name: str) -> None: - if isinstance(offset, timedelta): - self.__offset = offset - else: - self.__offset = timedelta(minutes=offset) - self.__name = name - - def __getinitargs__(self) -> Tuple[timedelta, str]: - return self.__offset, self.__name - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.__offset!r}, {self.__name!r})" - - def utcoffset(self, dt: Optional[datetime]) -> timedelta: - return self.__offset - - def tzname(self, dt: Optional[datetime]) -> str: - return self.__name - - def dst(self, dt: Optional[datetime]) -> timedelta: - return ZERO - - -utc: FixedOffset = FixedOffset(0, "UTC") -"""Fixed offset timezone representing UTC.""" diff --git a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/INSTALLER b/venv/Lib/site-packages/certifi-2025.4.26.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/METADATA b/venv/Lib/site-packages/certifi-2025.4.26.dist-info/METADATA deleted file mode 100644 index bba2b69..0000000 --- a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/METADATA +++ /dev/null @@ -1,78 +0,0 @@ -Metadata-Version: 2.4 -Name: certifi -Version: 2025.4.26 -Summary: Python package for providing Mozilla's CA Bundle. -Home-page: https://github.com/certifi/python-certifi -Author: Kenneth Reitz -Author-email: me@kennethreitz.com -License: MPL-2.0 -Project-URL: Source, https://github.com/certifi/python-certifi -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0) -Classifier: Natural Language :: English -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: 3.7 -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 -Requires-Python: >=3.6 -License-File: LICENSE -Dynamic: author -Dynamic: author-email -Dynamic: classifier -Dynamic: description -Dynamic: home-page -Dynamic: license -Dynamic: license-file -Dynamic: project-url -Dynamic: requires-python -Dynamic: summary - -Certifi: Python SSL Certificates -================================ - -Certifi provides Mozilla's carefully curated collection of Root Certificates for -validating the trustworthiness of SSL certificates while verifying the identity -of TLS hosts. It has been extracted from the `Requests`_ project. - -Installation ------------- - -``certifi`` is available on PyPI. Simply install it with ``pip``:: - - $ pip install certifi - -Usage ------ - -To reference the installed certificate authority (CA) bundle, you can use the -built-in function:: - - >>> import certifi - - >>> certifi.where() - '/usr/local/lib/python3.7/site-packages/certifi/cacert.pem' - -Or from the command line:: - - $ python -m certifi - /usr/local/lib/python3.7/site-packages/certifi/cacert.pem - -Enjoy! - -.. _`Requests`: https://requests.readthedocs.io/en/master/ - -Addition/Removal of Certificates --------------------------------- - -Certifi does not support any addition/removal or other modification of the -CA trust store content. This project is intended to provide a reliable and -highly portable root of trust to python deployments. Look to upstream projects -for methods to use alternate trust. diff --git a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/RECORD b/venv/Lib/site-packages/certifi-2025.4.26.dist-info/RECORD deleted file mode 100644 index 764cca2..0000000 --- a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/RECORD +++ /dev/null @@ -1,14 +0,0 @@ -certifi-2025.4.26.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -certifi-2025.4.26.dist-info/METADATA,sha256=Q1SDFkY5LOQAJmDltZz2wU3VTv1Kh5X-rjGI4KiPHNM,2473 -certifi-2025.4.26.dist-info/RECORD,, -certifi-2025.4.26.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91 -certifi-2025.4.26.dist-info/licenses/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989 -certifi-2025.4.26.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8 -certifi/__init__.py,sha256=9pyWUGr6sbAlksfOHo0BTV0Gxljjh4IK1kXAjHgjL4I,94 -certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243 -certifi/__pycache__/__init__.cpython-310.pyc,, -certifi/__pycache__/__main__.cpython-310.pyc,, -certifi/__pycache__/core.cpython-310.pyc,, -certifi/cacert.pem,sha256=K3sQJvGKKX4hSBicoMvn0-f578NvcjHMwoIKQE_rVZY,283771 -certifi/core.py,sha256=qRDDFyXVJwTB_EmoGppaXU_R9qCZvhl-EzxPMuV3nTA,4426 -certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 diff --git a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/WHEEL b/venv/Lib/site-packages/certifi-2025.4.26.dist-info/WHEEL deleted file mode 100644 index 8acb955..0000000 --- a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (79.0.1) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/licenses/LICENSE b/venv/Lib/site-packages/certifi-2025.4.26.dist-info/licenses/LICENSE deleted file mode 100644 index 62b076c..0000000 --- a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/licenses/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -This package contains a modified version of ca-bundle.crt: - -ca-bundle.crt -- Bundle of CA Root Certificates - -This is a bundle of X.509 certificates of public Certificate Authorities -(CA). These were automatically extracted from Mozilla's root certificates -file (certdata.txt). This file can be found in the mozilla source tree: -https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt -It contains the certificates in PEM format and therefore -can be directly used with curl / libcurl / php_curl, or with -an Apache+mod_ssl webserver for SSL client authentication. -Just configure this file as the SSLCACertificateFile.# - -***** BEGIN LICENSE BLOCK ***** -This Source Code Form is subject to the terms of the Mozilla Public License, -v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain -one at http://mozilla.org/MPL/2.0/. - -***** END LICENSE BLOCK ***** -@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $ diff --git a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/top_level.txt b/venv/Lib/site-packages/certifi-2025.4.26.dist-info/top_level.txt deleted file mode 100644 index 963eac5..0000000 --- a/venv/Lib/site-packages/certifi-2025.4.26.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -certifi diff --git a/venv/Lib/site-packages/certifi/__init__.py b/venv/Lib/site-packages/certifi/__init__.py deleted file mode 100644 index bf83fa9..0000000 --- a/venv/Lib/site-packages/certifi/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .core import contents, where - -__all__ = ["contents", "where"] -__version__ = "2025.04.26" diff --git a/venv/Lib/site-packages/certifi/__main__.py b/venv/Lib/site-packages/certifi/__main__.py deleted file mode 100644 index 8945b5d..0000000 --- a/venv/Lib/site-packages/certifi/__main__.py +++ /dev/null @@ -1,12 +0,0 @@ -import argparse - -from certifi import contents, where - -parser = argparse.ArgumentParser() -parser.add_argument("-c", "--contents", action="store_true") -args = parser.parse_args() - -if args.contents: - print(contents()) -else: - print(where()) diff --git a/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/certifi/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 8fe7fe72c2dfb5885648c037c277a67d2f2f6a8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 278 zcmYk0!Ait15QdYq-7PB%zJMU!day1B3?>xsLj|7n>Hnh6@4RLDHji( zd<9RN-u8$2hM#}<89krRNYL5O$@V4e-_ab31#=(9o(2das3I*bY0FARiC`jXSQ&}9 zj79Q9vdJF}XBqQptviREvp)IQqCqqEm?+?DRxFCEd~ul<*PATyajg$yKLx0i0`Nxw z0~#xJ2k=eIbSxP0|M+mjpKXYE-{=bF5XN^mm)sh>a4%qEA*6`*BBFSL#UX;&gg{ucV=j03$L`*V*Iw;AoTaa{ zjfIu9ot2Xy>cD)%_s#5&ZAK%XVC}!{%|3CycjkY&XwI;8j3SAoC5gMqN?Ng)RZi?s z0%SXQA+ZbY+>?$RNLPB#UG8p&m~-HBrVd~S*oJHF_`j!iow?b*K!wi%u9ty>fsT>p=oU43U zA@-)bP}b`&mE9FmrueYmS-(#^ukD~$w^c=LUWp1iR3~3o7stsRGIY}BO$EsW^ujc4 zGM!wmM47ChUM17wKGB7Ns1?~lPOE{&-)ngP+#*DKu K<eUa9SM{K)T=q7o&X zB?0s@cSP7?Jm6(`zcQSKyaKZ-XY0gTsDgzb!NM3=7>mX`6Vb#a3*#3oOq^M;UQI@m zcASc)V4Q5%I@8fKC1P4kZO@V>RlTGi7c*CN+yF+9fftQdb_D8`peqe#D)G|8rAKQU@zTc6CWvG4BGYkvL?nJ~#mVy0gXU8uq-u6I zi;ie63$>$*Zu80VqrIfv+!Og;^GWussWL6@b(3@_*%Ycd1mKIbkOELJ6V~z|oH*4l zkZg*9s8Lyhp}~$F7>=tP%#fiCwch4N=s7)$RHmwj*XvajL`&AY-S49Y+PqR4m2M>^`37DDP}=cXg&yPl`0LX%OtK{ z3KoyE!OnpK!D5I|e0{pjxWnBy6vFXVHy$No{p;I zEdqzw@&TsKI*|zX5tSI>m1iI(YtY{!kH=|)8t-Wi75uVNsKr$v%9CtIoOrvsb??6M zfi799O=(yn$P-oUO5or;d~SRoOd(Z@%pNs#4iUG>e*lUmnjVq^VEG&Nd-auj;PzOb z{6rX3fD6wd6!$v$im18gz;k?lfo{v4t;p+Oq2U;}=!)C|WL#uI!;>Gwj{F1#`XWCC zVO*Z* None: - _CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr] - - -if sys.version_info >= (3, 11): - - from importlib.resources import as_file, files - - _CACERT_CTX = None - _CACERT_PATH = None - - def where() -> str: - # This is slightly terrible, but we want to delay extracting the file - # in cases where we're inside of a zipimport situation until someone - # actually calls where(), but we don't want to re-extract the file - # on every call of where(), so we'll do it once then store it in a - # global variable. - global _CACERT_CTX - global _CACERT_PATH - if _CACERT_PATH is None: - # This is slightly janky, the importlib.resources API wants you to - # manage the cleanup of this file, so it doesn't actually return a - # path, it returns a context manager that will give you the path - # when you enter it and will do any cleanup when you leave it. In - # the common case of not needing a temporary file, it will just - # return the file system location and the __exit__() is a no-op. - # - # We also have to hold onto the actual context manager, because - # it will do the cleanup whenever it gets garbage collected, so - # we will also store that at the global level as well. - _CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem")) - _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) - - return _CACERT_PATH - - def contents() -> str: - return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii") - -elif sys.version_info >= (3, 7): - - from importlib.resources import path as get_path, read_text - - _CACERT_CTX = None - _CACERT_PATH = None - - def where() -> str: - # This is slightly terrible, but we want to delay extracting the - # file in cases where we're inside of a zipimport situation until - # someone actually calls where(), but we don't want to re-extract - # the file on every call of where(), so we'll do it once then store - # it in a global variable. - global _CACERT_CTX - global _CACERT_PATH - if _CACERT_PATH is None: - # This is slightly janky, the importlib.resources API wants you - # to manage the cleanup of this file, so it doesn't actually - # return a path, it returns a context manager that will give - # you the path when you enter it and will do any cleanup when - # you leave it. In the common case of not needing a temporary - # file, it will just return the file system location and the - # __exit__() is a no-op. - # - # We also have to hold onto the actual context manager, because - # it will do the cleanup whenever it gets garbage collected, so - # we will also store that at the global level as well. - _CACERT_CTX = get_path("certifi", "cacert.pem") - _CACERT_PATH = str(_CACERT_CTX.__enter__()) - atexit.register(exit_cacert_ctx) - - return _CACERT_PATH - - def contents() -> str: - return read_text("certifi", "cacert.pem", encoding="ascii") - -else: - import os - import types - from typing import Union - - Package = Union[types.ModuleType, str] - Resource = Union[str, "os.PathLike"] - - # This fallback will work for Python versions prior to 3.7 that lack the - # importlib.resources module but relies on the existing `where` function - # so won't address issues with environments like PyOxidizer that don't set - # __file__ on modules. - def read_text( - package: Package, - resource: Resource, - encoding: str = 'utf-8', - errors: str = 'strict' - ) -> str: - with open(where(), encoding=encoding) as data: - return data.read() - - # If we don't have importlib.resources, then we will just do the old logic - # of assuming we're on the filesystem and munge the path directly. - def where() -> str: - f = os.path.dirname(__file__) - - return os.path.join(f, "cacert.pem") - - def contents() -> str: - return read_text("certifi", "cacert.pem", encoding="ascii") diff --git a/venv/Lib/site-packages/certifi/py.typed b/venv/Lib/site-packages/certifi/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/INSTALLER b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/METADATA b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/METADATA deleted file mode 100644 index 573d88b..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/METADATA +++ /dev/null @@ -1,731 +0,0 @@ -Metadata-Version: 2.4 -Name: charset-normalizer -Version: 3.4.2 -Summary: The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet. -Author-email: "Ahmed R. TAHRI" -Maintainer-email: "Ahmed R. TAHRI" -License: MIT -Project-URL: Changelog, https://github.com/jawah/charset_normalizer/blob/master/CHANGELOG.md -Project-URL: Documentation, https://charset-normalizer.readthedocs.io/ -Project-URL: Code, https://github.com/jawah/charset_normalizer -Project-URL: Issue tracker, https://github.com/jawah/charset_normalizer/issues -Keywords: encoding,charset,charset-detector,detector,normalization,unicode,chardet,detect -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -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 :: 3 :: Only -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Text Processing :: Linguistic -Classifier: Topic :: Utilities -Classifier: Typing :: Typed -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -License-File: LICENSE -Provides-Extra: unicode-backport -Dynamic: license-file - -

    Charset Detection, for Everyone 👋

    - -

    - The Real First Universal Charset Detector
    -
    - - - - Download Count Total - - - - -

    -

    - Featured Packages
    - - Static Badge - - - Static Badge - -

    -

    - In other language (unofficial port - by the community)
    - - Static Badge - -

    - -> A library that helps you read text from an unknown charset encoding.
    Motivated by `chardet`, -> I'm trying to resolve the issue by taking a new approach. -> All IANA character set names for which the Python core library provides codecs are supported. - -

    - >>>>> 👉 Try Me Online Now, Then Adopt Me 👈 <<<<< -

    - -This project offers you an alternative to **Universal Charset Encoding Detector**, also known as **Chardet**. - -| Feature | [Chardet](https://github.com/chardet/chardet) | Charset Normalizer | [cChardet](https://github.com/PyYoshi/cChardet) | -|--------------------------------------------------|:---------------------------------------------:|:--------------------------------------------------------------------------------------------------:|:-----------------------------------------------:| -| `Fast` | ❌ | ✅ | ✅ | -| `Universal**` | ❌ | ✅ | ❌ | -| `Reliable` **without** distinguishable standards | ❌ | ✅ | ✅ | -| `Reliable` **with** distinguishable standards | ✅ | ✅ | ✅ | -| `License` | LGPL-2.1
    _restrictive_ | MIT | MPL-1.1
    _restrictive_ | -| `Native Python` | ✅ | ✅ | ❌ | -| `Detect spoken language` | ❌ | ✅ | N/A | -| `UnicodeDecodeError Safety` | ❌ | ✅ | ❌ | -| `Whl Size (min)` | 193.6 kB | 42 kB | ~200 kB | -| `Supported Encoding` | 33 | 🎉 [99](https://charset-normalizer.readthedocs.io/en/latest/user/support.html#supported-encodings) | 40 | - -

    -Reading Normalized TextCat Reading Text -

    - -*\*\* : They are clearly using specific code for a specific encoding even if covering most of used one*
    - -## ⚡ Performance - -This package offer better performance than its counterpart Chardet. Here are some numbers. - -| Package | Accuracy | Mean per file (ms) | File per sec (est) | -|-----------------------------------------------|:--------:|:------------------:|:------------------:| -| [chardet](https://github.com/chardet/chardet) | 86 % | 63 ms | 16 file/sec | -| charset-normalizer | **98 %** | **10 ms** | 100 file/sec | - -| Package | 99th percentile | 95th percentile | 50th percentile | -|-----------------------------------------------|:---------------:|:---------------:|:---------------:| -| [chardet](https://github.com/chardet/chardet) | 265 ms | 71 ms | 7 ms | -| charset-normalizer | 100 ms | 50 ms | 5 ms | - -_updated as of december 2024 using CPython 3.12_ - -Chardet's performance on larger file (1MB+) are very poor. Expect huge difference on large payload. - -> Stats are generated using 400+ files using default parameters. More details on used files, see GHA workflows. -> And yes, these results might change at any time. The dataset can be updated to include more files. -> The actual delays heavily depends on your CPU capabilities. The factors should remain the same. -> Keep in mind that the stats are generous and that Chardet accuracy vs our is measured using Chardet initial capability -> (e.g. Supported Encoding) Challenge-them if you want. - -## ✨ Installation - -Using pip: - -```sh -pip install charset-normalizer -U -``` - -## 🚀 Basic Usage - -### CLI -This package comes with a CLI. - -``` -usage: normalizer [-h] [-v] [-a] [-n] [-m] [-r] [-f] [-t THRESHOLD] - file [file ...] - -The Real First Universal Charset Detector. Discover originating encoding used -on text file. Normalize text to unicode. - -positional arguments: - files File(s) to be analysed - -optional arguments: - -h, --help show this help message and exit - -v, --verbose Display complementary information about file if any. - Stdout will contain logs about the detection process. - -a, --with-alternative - Output complementary possibilities if any. Top-level - JSON WILL be a list. - -n, --normalize Permit to normalize input file. If not set, program - does not write anything. - -m, --minimal Only output the charset detected to STDOUT. Disabling - JSON output. - -r, --replace Replace file when trying to normalize it instead of - creating a new one. - -f, --force Replace file without asking if you are sure, use this - flag with caution. - -t THRESHOLD, --threshold THRESHOLD - Define a custom maximum amount of chaos allowed in - decoded content. 0. <= chaos <= 1. - --version Show version information and exit. -``` - -```bash -normalizer ./data/sample.1.fr.srt -``` - -or - -```bash -python -m charset_normalizer ./data/sample.1.fr.srt -``` - -🎉 Since version 1.4.0 the CLI produce easily usable stdout result in JSON format. - -```json -{ - "path": "/home/default/projects/charset_normalizer/data/sample.1.fr.srt", - "encoding": "cp1252", - "encoding_aliases": [ - "1252", - "windows_1252" - ], - "alternative_encodings": [ - "cp1254", - "cp1256", - "cp1258", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - "mbcs" - ], - "language": "French", - "alphabets": [ - "Basic Latin", - "Latin-1 Supplement" - ], - "has_sig_or_bom": false, - "chaos": 0.149, - "coherence": 97.152, - "unicode_path": null, - "is_preferred": true -} -``` - -### Python -*Just print out normalized text* -```python -from charset_normalizer import from_path - -results = from_path('./my_subtitle.srt') - -print(str(results.best())) -``` - -*Upgrade your code without effort* -```python -from charset_normalizer import detect -``` - -The above code will behave the same as **chardet**. We ensure that we offer the best (reasonable) BC result possible. - -See the docs for advanced usage : [readthedocs.io](https://charset-normalizer.readthedocs.io/en/latest/) - -## 😇 Why - -When I started using Chardet, I noticed that it was not suited to my expectations, and I wanted to propose a -reliable alternative using a completely different method. Also! I never back down on a good challenge! - -I **don't care** about the **originating charset** encoding, because **two different tables** can -produce **two identical rendered string.** -What I want is to get readable text, the best I can. - -In a way, **I'm brute forcing text decoding.** How cool is that ? 😎 - -Don't confuse package **ftfy** with charset-normalizer or chardet. ftfy goal is to repair Unicode string whereas charset-normalizer to convert raw file in unknown encoding to unicode. - -## 🍰 How - - - Discard all charset encoding table that could not fit the binary content. - - Measure noise, or the mess once opened (by chunks) with a corresponding charset encoding. - - Extract matches with the lowest mess detected. - - Additionally, we measure coherence / probe for a language. - -**Wait a minute**, what is noise/mess and coherence according to **YOU ?** - -*Noise :* I opened hundred of text files, **written by humans**, with the wrong encoding table. **I observed**, then -**I established** some ground rules about **what is obvious** when **it seems like** a mess (aka. defining noise in rendered text). - I know that my interpretation of what is noise is probably incomplete, feel free to contribute in order to - improve or rewrite it. - -*Coherence :* For each language there is on earth, we have computed ranked letter appearance occurrences (the best we can). So I thought -that intel is worth something here. So I use those records against decoded text to check if I can detect intelligent design. - -## ⚡ Known limitations - - - Language detection is unreliable when text contains two or more languages sharing identical letters. (eg. HTML (english tags) + Turkish content (Sharing Latin characters)) - - Every charset detector heavily depends on sufficient content. In common cases, do not bother run detection on very tiny content. - -## ⚠️ About Python EOLs - -**If you are running:** - -- Python >=2.7,<3.5: Unsupported -- Python 3.5: charset-normalizer < 2.1 -- Python 3.6: charset-normalizer < 3.1 -- Python 3.7: charset-normalizer < 4.0 - -Upgrade your Python interpreter as soon as possible. - -## 👤 Contributing - -Contributions, issues and feature requests are very much welcome.
    -Feel free to check [issues page](https://github.com/ousret/charset_normalizer/issues) if you want to contribute. - -## 📝 License - -Copyright © [Ahmed TAHRI @Ousret](https://github.com/Ousret).
    -This project is [MIT](https://github.com/Ousret/charset_normalizer/blob/master/LICENSE) licensed. - -Characters frequencies used in this project © 2012 [Denny Vrandečić](http://simia.net/letters/) - -## 💼 For Enterprise - -Professional support for charset-normalizer is available as part of the [Tidelift -Subscription][1]. Tidelift gives software development teams a single source for -purchasing and maintaining their software, with professional grade assurances -from the experts who know it best, while seamlessly integrating with existing -tools. - -[1]: https://tidelift.com/subscription/pkg/pypi-charset-normalizer?utm_source=pypi-charset-normalizer&utm_medium=readme - -[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/7297/badge)](https://www.bestpractices.dev/projects/7297) - -# Changelog -All notable changes to charset-normalizer will be documented in this file. This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - -## [3.4.2](https://github.com/Ousret/charset_normalizer/compare/3.4.1...3.4.2) (2025-05-02) - -### Fixed -- Addressed the DeprecationWarning in our CLI regarding `argparse.FileType` by backporting the target class into the package. (#591) -- Improved the overall reliability of the detector with CJK Ideographs. (#605) (#587) - -### Changed -- Optional mypyc compilation upgraded to version 1.15 for Python >= 3.8 - -## [3.4.1](https://github.com/Ousret/charset_normalizer/compare/3.4.0...3.4.1) (2024-12-24) - -### Changed -- Project metadata are now stored using `pyproject.toml` instead of `setup.cfg` using setuptools as the build backend. -- Enforce annotation delayed loading for a simpler and consistent types in the project. -- Optional mypyc compilation upgraded to version 1.14 for Python >= 3.8 - -### Added -- pre-commit configuration. -- noxfile. - -### Removed -- `build-requirements.txt` as per using `pyproject.toml` native build configuration. -- `bin/integration.py` and `bin/serve.py` in favor of downstream integration test (see noxfile). -- `setup.cfg` in favor of `pyproject.toml` metadata configuration. -- Unused `utils.range_scan` function. - -### Fixed -- Converting content to Unicode bytes may insert `utf_8` instead of preferred `utf-8`. (#572) -- Deprecation warning "'count' is passed as positional argument" when converting to Unicode bytes on Python 3.13+ - -## [3.4.0](https://github.com/Ousret/charset_normalizer/compare/3.3.2...3.4.0) (2024-10-08) - -### Added -- Argument `--no-preemptive` in the CLI to prevent the detector to search for hints. -- Support for Python 3.13 (#512) - -### Fixed -- Relax the TypeError exception thrown when trying to compare a CharsetMatch with anything else than a CharsetMatch. -- Improved the general reliability of the detector based on user feedbacks. (#520) (#509) (#498) (#407) (#537) -- Declared charset in content (preemptive detection) not changed when converting to utf-8 bytes. (#381) - -## [3.3.2](https://github.com/Ousret/charset_normalizer/compare/3.3.1...3.3.2) (2023-10-31) - -### Fixed -- Unintentional memory usage regression when using large payload that match several encoding (#376) -- Regression on some detection case showcased in the documentation (#371) - -### Added -- Noise (md) probe that identify malformed arabic representation due to the presence of letters in isolated form (credit to my wife) - -## [3.3.1](https://github.com/Ousret/charset_normalizer/compare/3.3.0...3.3.1) (2023-10-22) - -### Changed -- Optional mypyc compilation upgraded to version 1.6.1 for Python >= 3.8 -- Improved the general detection reliability based on reports from the community - -## [3.3.0](https://github.com/Ousret/charset_normalizer/compare/3.2.0...3.3.0) (2023-09-30) - -### Added -- Allow to execute the CLI (e.g. normalizer) through `python -m charset_normalizer.cli` or `python -m charset_normalizer` -- Support for 9 forgotten encoding that are supported by Python but unlisted in `encoding.aliases` as they have no alias (#323) - -### Removed -- (internal) Redundant utils.is_ascii function and unused function is_private_use_only -- (internal) charset_normalizer.assets is moved inside charset_normalizer.constant - -### Changed -- (internal) Unicode code blocks in constants are updated using the latest v15.0.0 definition to improve detection -- Optional mypyc compilation upgraded to version 1.5.1 for Python >= 3.8 - -### Fixed -- Unable to properly sort CharsetMatch when both chaos/noise and coherence were close due to an unreachable condition in \_\_lt\_\_ (#350) - -## [3.2.0](https://github.com/Ousret/charset_normalizer/compare/3.1.0...3.2.0) (2023-06-07) - -### Changed -- Typehint for function `from_path` no longer enforce `PathLike` as its first argument -- Minor improvement over the global detection reliability - -### Added -- Introduce function `is_binary` that relies on main capabilities, and optimized to detect binaries -- Propagate `enable_fallback` argument throughout `from_bytes`, `from_path`, and `from_fp` that allow a deeper control over the detection (default True) -- Explicit support for Python 3.12 - -### Fixed -- Edge case detection failure where a file would contain 'very-long' camel cased word (Issue #289) - -## [3.1.0](https://github.com/Ousret/charset_normalizer/compare/3.0.1...3.1.0) (2023-03-06) - -### Added -- Argument `should_rename_legacy` for legacy function `detect` and disregard any new arguments without errors (PR #262) - -### Removed -- Support for Python 3.6 (PR #260) - -### Changed -- Optional speedup provided by mypy/c 1.0.1 - -## [3.0.1](https://github.com/Ousret/charset_normalizer/compare/3.0.0...3.0.1) (2022-11-18) - -### Fixed -- Multi-bytes cutter/chunk generator did not always cut correctly (PR #233) - -### Changed -- Speedup provided by mypy/c 0.990 on Python >= 3.7 - -## [3.0.0](https://github.com/Ousret/charset_normalizer/compare/2.1.1...3.0.0) (2022-10-20) - -### Added -- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results -- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES -- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio -- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) - -### Changed -- Build with static metadata using 'build' frontend -- Make the language detection stricter -- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 - -### Fixed -- CLI with opt --normalize fail when using full path for files -- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it -- Sphinx warnings when generating the documentation - -### Removed -- Coherence detector no longer return 'Simple English' instead return 'English' -- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' -- Breaking: Method `first()` and `best()` from CharsetMatch -- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) -- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches -- Breaking: Top-level function `normalize` -- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch -- Support for the backport `unicodedata2` - -## [3.0.0rc1](https://github.com/Ousret/charset_normalizer/compare/3.0.0b2...3.0.0rc1) (2022-10-18) - -### Added -- Extend the capability of explain=True when cp_isolation contains at most two entries (min one), will log in details of the Mess-detector results -- Support for alternative language frequency set in charset_normalizer.assets.FREQUENCIES -- Add parameter `language_threshold` in `from_bytes`, `from_path` and `from_fp` to adjust the minimum expected coherence ratio - -### Changed -- Build with static metadata using 'build' frontend -- Make the language detection stricter - -### Fixed -- CLI with opt --normalize fail when using full path for files -- TooManyAccentuatedPlugin induce false positive on the mess detection when too few alpha character have been fed to it - -### Removed -- Coherence detector no longer return 'Simple English' instead return 'English' -- Coherence detector no longer return 'Classical Chinese' instead return 'Chinese' - -## [3.0.0b2](https://github.com/Ousret/charset_normalizer/compare/3.0.0b1...3.0.0b2) (2022-08-21) - -### Added -- `normalizer --version` now specify if current version provide extra speedup (meaning mypyc compilation whl) - -### Removed -- Breaking: Method `first()` and `best()` from CharsetMatch -- UTF-7 will no longer appear as "detected" without a recognized SIG/mark (is unreliable/conflict with ASCII) - -### Fixed -- Sphinx warnings when generating the documentation - -## [3.0.0b1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...3.0.0b1) (2022-08-15) - -### Changed -- Optional: Module `md.py` can be compiled using Mypyc to provide an extra speedup up to 4x faster than v2.1 - -### Removed -- Breaking: Class aliases CharsetDetector, CharsetDoctor, CharsetNormalizerMatch and CharsetNormalizerMatches -- Breaking: Top-level function `normalize` -- Breaking: Properties `chaos_secondary_pass`, `coherence_non_latin` and `w_counter` from CharsetMatch -- Support for the backport `unicodedata2` - -## [2.1.1](https://github.com/Ousret/charset_normalizer/compare/2.1.0...2.1.1) (2022-08-19) - -### Deprecated -- Function `normalize` scheduled for removal in 3.0 - -### Changed -- Removed useless call to decode in fn is_unprintable (#206) - -### Fixed -- Third-party library (i18n xgettext) crashing not recognizing utf_8 (PEP 263) with underscore from [@aleksandernovikov](https://github.com/aleksandernovikov) (#204) - -## [2.1.0](https://github.com/Ousret/charset_normalizer/compare/2.0.12...2.1.0) (2022-06-19) - -### Added -- Output the Unicode table version when running the CLI with `--version` (PR #194) - -### Changed -- Re-use decoded buffer for single byte character sets from [@nijel](https://github.com/nijel) (PR #175) -- Fixing some performance bottlenecks from [@deedy5](https://github.com/deedy5) (PR #183) - -### Fixed -- Workaround potential bug in cpython with Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space (PR #175) -- CLI default threshold aligned with the API threshold from [@oleksandr-kuzmenko](https://github.com/oleksandr-kuzmenko) (PR #181) - -### Removed -- Support for Python 3.5 (PR #192) - -### Deprecated -- Use of backport unicodedata from `unicodedata2` as Python is quickly catching up, scheduled for removal in 3.0 (PR #194) - -## [2.0.12](https://github.com/Ousret/charset_normalizer/compare/2.0.11...2.0.12) (2022-02-12) - -### Fixed -- ASCII miss-detection on rare cases (PR #170) - -## [2.0.11](https://github.com/Ousret/charset_normalizer/compare/2.0.10...2.0.11) (2022-01-30) - -### Added -- Explicit support for Python 3.11 (PR #164) - -### Changed -- The logging behavior have been completely reviewed, now using only TRACE and DEBUG levels (PR #163 #165) - -## [2.0.10](https://github.com/Ousret/charset_normalizer/compare/2.0.9...2.0.10) (2022-01-04) - -### Fixed -- Fallback match entries might lead to UnicodeDecodeError for large bytes sequence (PR #154) - -### Changed -- Skipping the language-detection (CD) on ASCII (PR #155) - -## [2.0.9](https://github.com/Ousret/charset_normalizer/compare/2.0.8...2.0.9) (2021-12-03) - -### Changed -- Moderating the logging impact (since 2.0.8) for specific environments (PR #147) - -### Fixed -- Wrong logging level applied when setting kwarg `explain` to True (PR #146) - -## [2.0.8](https://github.com/Ousret/charset_normalizer/compare/2.0.7...2.0.8) (2021-11-24) -### Changed -- Improvement over Vietnamese detection (PR #126) -- MD improvement on trailing data and long foreign (non-pure latin) data (PR #124) -- Efficiency improvements in cd/alphabet_languages from [@adbar](https://github.com/adbar) (PR #122) -- call sum() without an intermediary list following PEP 289 recommendations from [@adbar](https://github.com/adbar) (PR #129) -- Code style as refactored by Sourcery-AI (PR #131) -- Minor adjustment on the MD around european words (PR #133) -- Remove and replace SRTs from assets / tests (PR #139) -- Initialize the library logger with a `NullHandler` by default from [@nmaynes](https://github.com/nmaynes) (PR #135) -- Setting kwarg `explain` to True will add provisionally (bounded to function lifespan) a specific stream handler (PR #135) - -### Fixed -- Fix large (misleading) sequence giving UnicodeDecodeError (PR #137) -- Avoid using too insignificant chunk (PR #137) - -### Added -- Add and expose function `set_logging_handler` to configure a specific StreamHandler from [@nmaynes](https://github.com/nmaynes) (PR #135) -- Add `CHANGELOG.md` entries, format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) (PR #141) - -## [2.0.7](https://github.com/Ousret/charset_normalizer/compare/2.0.6...2.0.7) (2021-10-11) -### Added -- Add support for Kazakh (Cyrillic) language detection (PR #109) - -### Changed -- Further, improve inferring the language from a given single-byte code page (PR #112) -- Vainly trying to leverage PEP263 when PEP3120 is not supported (PR #116) -- Refactoring for potential performance improvements in loops from [@adbar](https://github.com/adbar) (PR #113) -- Various detection improvement (MD+CD) (PR #117) - -### Removed -- Remove redundant logging entry about detected language(s) (PR #115) - -### Fixed -- Fix a minor inconsistency between Python 3.5 and other versions regarding language detection (PR #117 #102) - -## [2.0.6](https://github.com/Ousret/charset_normalizer/compare/2.0.5...2.0.6) (2021-09-18) -### Fixed -- Unforeseen regression with the loss of the backward-compatibility with some older minor of Python 3.5.x (PR #100) -- Fix CLI crash when using --minimal output in certain cases (PR #103) - -### Changed -- Minor improvement to the detection efficiency (less than 1%) (PR #106 #101) - -## [2.0.5](https://github.com/Ousret/charset_normalizer/compare/2.0.4...2.0.5) (2021-09-14) -### Changed -- The project now comply with: flake8, mypy, isort and black to ensure a better overall quality (PR #81) -- The BC-support with v1.x was improved, the old staticmethods are restored (PR #82) -- The Unicode detection is slightly improved (PR #93) -- Add syntax sugar \_\_bool\_\_ for results CharsetMatches list-container (PR #91) - -### Removed -- The project no longer raise warning on tiny content given for detection, will be simply logged as warning instead (PR #92) - -### Fixed -- In some rare case, the chunks extractor could cut in the middle of a multi-byte character and could mislead the mess detection (PR #95) -- Some rare 'space' characters could trip up the UnprintablePlugin/Mess detection (PR #96) -- The MANIFEST.in was not exhaustive (PR #78) - -## [2.0.4](https://github.com/Ousret/charset_normalizer/compare/2.0.3...2.0.4) (2021-07-30) -### Fixed -- The CLI no longer raise an unexpected exception when no encoding has been found (PR #70) -- Fix accessing the 'alphabets' property when the payload contains surrogate characters (PR #68) -- The logger could mislead (explain=True) on detected languages and the impact of one MBCS match (PR #72) -- Submatch factoring could be wrong in rare edge cases (PR #72) -- Multiple files given to the CLI were ignored when publishing results to STDOUT. (After the first path) (PR #72) -- Fix line endings from CRLF to LF for certain project files (PR #67) - -### Changed -- Adjust the MD to lower the sensitivity, thus improving the global detection reliability (PR #69 #76) -- Allow fallback on specified encoding if any (PR #71) - -## [2.0.3](https://github.com/Ousret/charset_normalizer/compare/2.0.2...2.0.3) (2021-07-16) -### Changed -- Part of the detection mechanism has been improved to be less sensitive, resulting in more accurate detection results. Especially ASCII. (PR #63) -- According to the community wishes, the detection will fall back on ASCII or UTF-8 in a last-resort case. (PR #64) - -## [2.0.2](https://github.com/Ousret/charset_normalizer/compare/2.0.1...2.0.2) (2021-07-15) -### Fixed -- Empty/Too small JSON payload miss-detection fixed. Report from [@tseaver](https://github.com/tseaver) (PR #59) - -### Changed -- Don't inject unicodedata2 into sys.modules from [@akx](https://github.com/akx) (PR #57) - -## [2.0.1](https://github.com/Ousret/charset_normalizer/compare/2.0.0...2.0.1) (2021-07-13) -### Fixed -- Make it work where there isn't a filesystem available, dropping assets frequencies.json. Report from [@sethmlarson](https://github.com/sethmlarson). (PR #55) -- Using explain=False permanently disable the verbose output in the current runtime (PR #47) -- One log entry (language target preemptive) was not show in logs when using explain=True (PR #47) -- Fix undesired exception (ValueError) on getitem of instance CharsetMatches (PR #52) - -### Changed -- Public function normalize default args values were not aligned with from_bytes (PR #53) - -### Added -- You may now use charset aliases in cp_isolation and cp_exclusion arguments (PR #47) - -## [2.0.0](https://github.com/Ousret/charset_normalizer/compare/1.4.1...2.0.0) (2021-07-02) -### Changed -- 4x to 5 times faster than the previous 1.4.0 release. At least 2x faster than Chardet. -- Accent has been made on UTF-8 detection, should perform rather instantaneous. -- The backward compatibility with Chardet has been greatly improved. The legacy detect function returns an identical charset name whenever possible. -- The detection mechanism has been slightly improved, now Turkish content is detected correctly (most of the time) -- The program has been rewritten to ease the readability and maintainability. (+Using static typing)+ -- utf_7 detection has been reinstated. - -### Removed -- This package no longer require anything when used with Python 3.5 (Dropped cached_property) -- Removed support for these languages: Catalan, Esperanto, Kazakh, Baque, Volapük, Azeri, Galician, Nynorsk, Macedonian, and Serbocroatian. -- The exception hook on UnicodeDecodeError has been removed. - -### Deprecated -- Methods coherence_non_latin, w_counter, chaos_secondary_pass of the class CharsetMatch are now deprecated and scheduled for removal in v3.0 - -### Fixed -- The CLI output used the relative path of the file(s). Should be absolute. - -## [1.4.1](https://github.com/Ousret/charset_normalizer/compare/1.4.0...1.4.1) (2021-05-28) -### Fixed -- Logger configuration/usage no longer conflict with others (PR #44) - -## [1.4.0](https://github.com/Ousret/charset_normalizer/compare/1.3.9...1.4.0) (2021-05-21) -### Removed -- Using standard logging instead of using the package loguru. -- Dropping nose test framework in favor of the maintained pytest. -- Choose to not use dragonmapper package to help with gibberish Chinese/CJK text. -- Require cached_property only for Python 3.5 due to constraint. Dropping for every other interpreter version. -- Stop support for UTF-7 that does not contain a SIG. -- Dropping PrettyTable, replaced with pure JSON output in CLI. - -### Fixed -- BOM marker in a CharsetNormalizerMatch instance could be False in rare cases even if obviously present. Due to the sub-match factoring process. -- Not searching properly for the BOM when trying utf32/16 parent codec. - -### Changed -- Improving the package final size by compressing frequencies.json. -- Huge improvement over the larges payload. - -### Added -- CLI now produces JSON consumable output. -- Return ASCII if given sequences fit. Given reasonable confidence. - -## [1.3.9](https://github.com/Ousret/charset_normalizer/compare/1.3.8...1.3.9) (2021-05-13) - -### Fixed -- In some very rare cases, you may end up getting encode/decode errors due to a bad bytes payload (PR #40) - -## [1.3.8](https://github.com/Ousret/charset_normalizer/compare/1.3.7...1.3.8) (2021-05-12) - -### Fixed -- Empty given payload for detection may cause an exception if trying to access the `alphabets` property. (PR #39) - -## [1.3.7](https://github.com/Ousret/charset_normalizer/compare/1.3.6...1.3.7) (2021-05-12) - -### Fixed -- The legacy detect function should return UTF-8-SIG if sig is present in the payload. (PR #38) - -## [1.3.6](https://github.com/Ousret/charset_normalizer/compare/1.3.5...1.3.6) (2021-02-09) - -### Changed -- Amend the previous release to allow prettytable 2.0 (PR #35) - -## [1.3.5](https://github.com/Ousret/charset_normalizer/compare/1.3.4...1.3.5) (2021-02-08) - -### Fixed -- Fix error while using the package with a python pre-release interpreter (PR #33) - -### Changed -- Dependencies refactoring, constraints revised. - -### Added -- Add python 3.9 and 3.10 to the supported interpreters - -MIT License - -Copyright (c) 2025 TAHRI Ahmed R. - -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. diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/RECORD b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/RECORD deleted file mode 100644 index 8b64ff5..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/RECORD +++ /dev/null @@ -1,35 +0,0 @@ -../../Scripts/normalizer.exe,sha256=b6A9TmeBmJl13JbrRLSvC67XCABYexMxT4L8hQB9ww0,107905 -charset_normalizer-3.4.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -charset_normalizer-3.4.2.dist-info/METADATA,sha256=WneNNyl9QvsRZYzK1FeEC6Wwag4iIFoTAoevPgpZFTY,36474 -charset_normalizer-3.4.2.dist-info/RECORD,, -charset_normalizer-3.4.2.dist-info/WHEEL,sha256=AVu1DavlWPCypqX8sBQ58NLvImUaO9Rw16t7hIak0pw,101 -charset_normalizer-3.4.2.dist-info/entry_points.txt,sha256=8C-Y3iXIfyXQ83Tpir2B8t-XLJYpxF5xbb38d_js-h4,65 -charset_normalizer-3.4.2.dist-info/licenses/LICENSE,sha256=GFd0hdNwTxpHne2OVzwJds_tMV_S_ReYP6mI2kwvcNE,1092 -charset_normalizer-3.4.2.dist-info/top_level.txt,sha256=7ASyzePr8_xuZWJsnqJjIBtyV8vhEo0wBCv1MPRRi3Q,19 -charset_normalizer/__init__.py,sha256=0NT8MHi7SKq3juMqYfOdrkzjisK0L73lneNHH4qaUAs,1638 -charset_normalizer/__main__.py,sha256=2sj_BS6H0sU25C1bMqz9DVwa6kOK9lchSEbSU-_iu7M,115 -charset_normalizer/__pycache__/__init__.cpython-310.pyc,, -charset_normalizer/__pycache__/__main__.cpython-310.pyc,, -charset_normalizer/__pycache__/api.cpython-310.pyc,, -charset_normalizer/__pycache__/cd.cpython-310.pyc,, -charset_normalizer/__pycache__/constant.cpython-310.pyc,, -charset_normalizer/__pycache__/legacy.cpython-310.pyc,, -charset_normalizer/__pycache__/md.cpython-310.pyc,, -charset_normalizer/__pycache__/models.cpython-310.pyc,, -charset_normalizer/__pycache__/utils.cpython-310.pyc,, -charset_normalizer/__pycache__/version.cpython-310.pyc,, -charset_normalizer/api.py,sha256=2a0p2Gnhbdo9O6C04CNxTSN23fIbgOF20nxb0pWPNFM,23285 -charset_normalizer/cd.py,sha256=uq8nVxRpR6Guc16ACvOWtL8KO3w7vYaCh8hHisuOyTg,12917 -charset_normalizer/cli/__init__.py,sha256=d9MUx-1V_qD3x9igIy4JT4oC5CU0yjulk7QyZWeRFhg,144 -charset_normalizer/cli/__main__.py,sha256=-pdJCyPywouPyFsC8_eTSgTmvh1YEvgjsvy1WZ0XjaA,13027 -charset_normalizer/cli/__pycache__/__init__.cpython-310.pyc,, -charset_normalizer/cli/__pycache__/__main__.cpython-310.pyc,, -charset_normalizer/constant.py,sha256=mCJmYzpBU27Ut9kiNWWoBbhhxQ-aRVw3K7LSwoFwBGI,44728 -charset_normalizer/legacy.py,sha256=NgK-8ZQa_M9FHgQjdNSiYzMaB332QGuElZSfCf2y2sQ,2351 -charset_normalizer/md.cp310-win_amd64.pyd,sha256=nVB8MQoL3zbH_TwpkkT5LVviMxP7-ZVdJ6vO-D0q06Q,10752 -charset_normalizer/md.py,sha256=LSuW2hNgXSgF7JGdRapLAHLuj6pABHiP85LTNAYmu7c,20780 -charset_normalizer/md__mypyc.cp310-win_amd64.pyd,sha256=n9N3u1ftw-olnp75d80uuG-H-s0Sjrk0Nawm6KukcAc,122880 -charset_normalizer/models.py,sha256=ZR2PE-fqf6dASZfqdE5Uhkmr0o1MciSdXOjuNqwkmvg,12754 -charset_normalizer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -charset_normalizer/utils.py,sha256=XtWIQeOuz7cnGebMzyi4Vvi1JtA84QBSIeR9PDzF7pw,12584 -charset_normalizer/version.py,sha256=wtpyUZ7M57rCLclP3QjzRD0Nj2hvnMOzLZI-vwfTdWs,123 diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/WHEEL b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/WHEEL deleted file mode 100644 index cd0a146..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (80.1.0) -Root-Is-Purelib: false -Tag: cp310-cp310-win_amd64 - diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/entry_points.txt b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/entry_points.txt deleted file mode 100644 index ec92012..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[console_scripts] -normalizer = charset_normalizer:cli.cli_detect diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/licenses/LICENSE b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/licenses/LICENSE deleted file mode 100644 index 9725772..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2025 TAHRI Ahmed R. - -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. diff --git a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/top_level.txt b/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/top_level.txt deleted file mode 100644 index 66958f0..0000000 --- a/venv/Lib/site-packages/charset_normalizer-3.4.2.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -charset_normalizer diff --git a/venv/Lib/site-packages/charset_normalizer/__init__.py b/venv/Lib/site-packages/charset_normalizer/__init__.py deleted file mode 100644 index 0d3a379..0000000 --- a/venv/Lib/site-packages/charset_normalizer/__init__.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Charset-Normalizer -~~~~~~~~~~~~~~ -The Real First Universal Charset Detector. -A library that helps you read text from an unknown charset encoding. -Motivated by chardet, This package is trying to resolve the issue by taking a new approach. -All IANA character set names for which the Python core library provides codecs are supported. - -Basic usage: - >>> from charset_normalizer import from_bytes - >>> results = from_bytes('Bсеки човек има право на образование. Oбразованието!'.encode('utf_8')) - >>> best_guess = results.best() - >>> str(best_guess) - 'Bсеки човек има право на образование. Oбразованието!' - -Others methods and usages are available - see the full documentation -at . -:copyright: (c) 2021 by Ahmed TAHRI -:license: MIT, see LICENSE for more details. -""" - -from __future__ import annotations - -import logging - -from .api import from_bytes, from_fp, from_path, is_binary -from .legacy import detect -from .models import CharsetMatch, CharsetMatches -from .utils import set_logging_handler -from .version import VERSION, __version__ - -__all__ = ( - "from_fp", - "from_path", - "from_bytes", - "is_binary", - "detect", - "CharsetMatch", - "CharsetMatches", - "__version__", - "VERSION", - "set_logging_handler", -) - -# Attach a NullHandler to the top level logger by default -# https://docs.python.org/3.3/howto/logging.html#configuring-logging-for-a-library - -logging.getLogger("charset_normalizer").addHandler(logging.NullHandler()) diff --git a/venv/Lib/site-packages/charset_normalizer/__main__.py b/venv/Lib/site-packages/charset_normalizer/__main__.py deleted file mode 100644 index e0e76f7..0000000 --- a/venv/Lib/site-packages/charset_normalizer/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -from __future__ import annotations - -from .cli import cli_detect - -if __name__ == "__main__": - cli_detect() diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 0e65d5878694f601b5f976e1a6facc3d68a911c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1620 zcmcIk%WoVt7@vJ)AKp!yrY%%RNQO(YQnP`c(5ghFNl+u@fs&NNXeG-#=Ug~@d;960q~;Kb+IZ4wl&j5MFVm;L>|m(~0{^5FaM&-bHY z&GY_p!p*M=!e^dWGT#FedcGHy!m=pIvR^Jaz9K4qC9H;XqAKV7Ia%{-vhLSq!*77S z8rDQpA|DleU9@D|Z_9aqzK|Q@j=byNE%>HbkoWw1a?xJ|8Tt2F<<*0*by|A$5V&_v zz0(rtD~DdEoxZGi9@>bgHq5TF|F+0ID zNwlIt1OSD=+v|Jl#l1AJOk+qM$5b+dhf3pRDZr;RyUGf#8S@Za0V@j( zreHH^k|+&uy9hm_h6gw`fU$=##%pV9(}ZVPlK861m`iu8Fq6T=GV}HTw7@`vmq``HONJI{X0&T#g}<+s@x=q_;fyOS@np9;+{h36S4&$HKE zy#HV7%a_^32TR?e{%mA~?$f5wG39~|1j8%P;OT4(Q)qsuf>g5DQp;70U`C%t)+VO6x;o-E zN(bFQ$<_VTXl7S$H*KwpdVxwNnvWve!^=SjKl$j%$8O-(BMB3GwEp~H8}$SaSZr7i z?`|JGE&%LoZ*1)yZWS{o-AKVu14PqBZ`?D{DdjC1$7+hp?7b;DWi>}`U8dua*9(4_ z_38vv# z{mZR`!|naOyhVuHaVQZX9i-;~jD}au)9xA5bw?VGG#zmdpPqN5?MMrVzj(WLopxMD(UZRZjGtvk6AqK@9;t2aLZO^&y(rj&VH2;9&<}bH<{#(r+_~dY|VAqJOEPl T+7BD$N9A^Dq2&H*`O(5Z9|}CQ diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/__main__.cpython-310.pyc deleted file mode 100644 index 0e9fb5dbc5b62ecb0d0a3c121a60c0e0a23246fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 309 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 diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/cd.cpython-310.pyc deleted file mode 100644 index 9fd1d4f1d8b3c3d88ce914e24a96e8bf01d33c52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9736 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 diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/constant.cpython-310.pyc deleted file mode 100644 index 5bbba9a565715c19b413653fcc07de2104a4c1da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32527 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 diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/legacy.cpython-310.pyc deleted file mode 100644 index 6bdeadbbe67c20be0f09728bf5d6b260fadfead3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2141 zcmZ`*&2QT_6c;7gmK7&WztVPC0b&Ez8cWmdv@Iys7K!_@7H*fMhZzP0S)^?>66rot zNgX(srT;}&pgrzi(q)I8y3@`DhVGGanjAI(CLiA;`QH1z4_YoRh7NvT{Bd=Bv*|d0 zn#JkQ$Hg7TAqtRS4kMY9lO7?4b~88kdS34Le7p9tT3+wfk@i_FYve&Muyj3Z=3y@+ z4)@?2JlDt;@>Z`!ocj(7So4*`n!I)7^%k2UyU149Id=Y4t+&K3Y&-2s?~OHWQZB?o zNFD1`3e|SY#hqWCcA||3osCBiyZ1})u9)H`e?JECo>V8oA;>%$Of^?1TG@DTcWbk= z6Ky=%+UjgSebU|RbT>LEY3@uXoNcCwPK>V8pNES(#`~|3;7*S)r{_LH6u8ISTMqMZ z_HnM^T*tYA76)ax#Z{4MbK^m%G|(CCO2Ny3i$tURKz2G&>Chk*2mkz zM2ca`a5L|={W6Fm5$8OL$}oy@$%@R-ttfg?#MxYOCW=nM6Ggu}a2_qT!-tgNa{y@sCtnXsP zMhZ-tm382{0Fk)3IQ|+)nBOB4g};!{&dfa`a9$HenETe%-pqaLzjKbrJMtPM^2R&D z?9{cHqwBgcbdOy1r4E>{n={<=+IfSgex1YjfEa3sAar*|8_;b8a&8S##Hg1Z8J%^jY|wgZB}( zP&goGzFywLSufB0D~9jSYO^|P{pMjNEyh0~6d}dWM1yfnEAVK}^;j}1+2oohn(8s9 z$LU4o(5^=*#+I5OPz(p=-5PzUX%!7R;53&?XHz=BkYg0sjYQ@XEU-bw*X-4udAd>) zH@cr@8O>vzjOoVQ8o4j%KBOA2ru$^+50#bhEubB4Cj zRJX0NopGw@un>u1|C4BbKGD~$Pz!W6BsjlYcZRLpUlAN#K|z$>UG*J8_&e9z@#aiQB~i6 z-!5x~9!B4nex%aTy|xDnC;`)3U&L> zm(5T5V8!gVZM_2^q4bSmVA=?_9gdOvq@-6vNTe#gfy}`)vvvb6;slq>aK)S;aI)Rn zbkbVkg4s~7Ffk2Rt>O?Yx#TkOKQ8$$c18bV=wo+u&$*wI6|#c#vKtWBbBRmp|G?LH zpxY+*+Cin)m|iKrY$#)aZI1Anp-kUxpD_=?u)tP{4*{5FS=P}(EJ85vRnQQ{!(+H%;O69H=xpFjXUM7eNwE;!L8~c`q4bK%CK6_ SvfDy8(P6KJF1n57kN*PF`c~xt diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/md.cpython-310.pyc deleted file mode 100644 index 0c126281c587493be1d7292c4de33c1289e2344d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16099 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 XlKDvHYUWVpbYlOIl{jVFqxb$Fkx|i~ diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/models.cpython-310.pyc deleted file mode 100644 index 369862a3754729bfbcda3d51910d1abe80c324a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12192 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 diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index 485ffe3881271d0988e6c0c15ed205784554ec26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8987 zcma)BTWs7`dgg6z)aYVamTc$7B)&~zD{=0-$a*uDM)t(g$kE8ohLOvq=1>wX&TxFl zkt2mFypgxrF4o)a<*992sofSZQ1rP#Q55KNUy1^KAW#%VpZwH^0BxZrcEA5{G@6m) zCKBf7;eXEg&*i`W^!xjD34bsA+cPU?&P&pN&`bB9hL`swNe+IlND`Bn>`8Umlx1ow zo?ZR&wGcCqwUZ$Qkv!b2ya&_I*MLX^F)$?Xvv@>3ReZU+L?W{Lg zA2Nr~&N1CPR3A2n>xa$5^$~NVe#AUdA2mnoW9C@>sCiVD9NigXefMPMvLSZpuC^tc z$2z#1Y?vJuxZ@q%Dm%hP1@5U1&ShilsK7nlg*(QM3*0kZxTo0D0{3he?iu#1z&+Q6 zdyW|bXLRA7XD|g)6X^1ny)P?qzmX;7)bn z&arWUJKcqQg}o|pXS#6b*=qt<0PZE{$d)Yb)njk4HwFIXuCZ^iw*~GjtFs3C0lRQF zWu9|%_CqnpXGL~V^pCS9n`EWCn)wR5#V)bSXuZlf3)nQ9!JP9fWFN3OU|(Y`R%P>O zz0R&V>diOU^(B?9F_V3aac|}ncAI^|me~s4-eO8sDy%;sDJ{rxpWSHqp&hz@BdFkg zxZJ35r|vXD+naQ1K65y*8QXL1zzNXIdAw!S?AnS$_$9Z&Y|kV7C8yzVJM?M%Q!_0u zbQjk{=W%imWLh~B50oksvyg?QnY0|2eXUfyXx%j!c zl67^qS}k9kE?J#9<;rAvqBvikt;A#3DrHbAS#!n8rBcA-dSlfd0@;#_UT=5{S~c&r8?kJH=xFl(ywa z+L1Tq52c2#NujcSNS5gTBbbP)bQ{JYlGmi>d8W3XTKk!5Khy1Jrv1#epE-Jh!FpwC zL;tWmf7!S+SG-89xODM{kpR-=>)5x-(0||Yqqzr<}}t8 zrrpJbzzv;qO}n;gFFU~kaUpO*tKsuHWOT#fue3tf3&xx4@qimxcC7|cZrP#3p28}@ z8308Ykn?g{Rvu+lf@wv0m{ygq)0*;CI;H$?I<4%cGs^$)XEC^kl`0Tq(FH5V(b#8X zBnP<&7az&n3X{QFB~(K#QkZfK7JWiksPceT~1k#dk4s);OSYtWTtpRbFn09GjM@cw=8^~ZzzxNp2} zQorW@0<(0!0RUaeLLRei$lnC&$tS${4JQox6YIza=~M?!dW>l}X^Kwj8xXV62L*$B+Ot8Ojym$}_sfvXi9C?qD6zX6g5 zx7mknLgB^aI{E{0Gs(qbi{Hb`V_WQq4q2~A+Lm@OD}vL3;OIhdpz4WhYP+6M96)P} z%>}X$yYht=k@?TR`{P~t-Cg{i(@)+#>Ea4}N6Y(l zhxV24Mq8V|Tr5ACG9nb0&k*EAxAr$3+Liy0c0lU= z-Qz<4Shoe?Gc>usT%ColDNPzvvvV^~-rHDbZV&QaM@e z9w{WX>)1I`fe4mv4YrNHhZh(vQbj&N;DCk=Vqr+T1()F0>we=OF-9m@R^eA^JbBm0 z)*_1oHJ1bOprQ1+v?Mc`DR;A>Jc-yugjH usfECZ~J92`aCC)nhT%qHC9&!jc! zIzpCPaEt9Ni*3SCDC4ijnN?@~HsS}^2--|?0ufo|-d#p|^GTCm_-Awkv@7M#sI+ko zhw2F{V8dX_na$V7-}U^O?FARcJ9Dv&YB$z7xj|m-tRPxqnd46;_fNDg9c@(M*YW5% zat~L|pf@pwOm0d3;lw2FwVAT25{{|DGisHoUHN!o(Es-DVW2Nyb_|oz0oiYD{Ny1I$Ree9A{)&GD`~%4V#cbf*YB`OX6Q?LG4C21Pv3YI9+CUV_Pheb) z4!8H0L4$q}BsthdgWPE-Zz(}0R6dhKH3@G*EliR33eyo1rY+^Ch_-KLn8H-1-BY#@ zs$!&yY&^B9@Dt>MBNbun=}j%twzE6Zc8;Z4W=Gl7LVdeWgt$i$;-)s!Q7Y0f=VFwm z5H|^PqqM+HcjIooaqE-_ezO}NimcIh0F0pN z)Z8W4VFs?mXEf4nh;VtyizS25#wGIwTv?o(UvDOfSFCzYgQtPyZn%MA@3E`a#VtbDsmNgvrwj8`J6O+&(}X?$R)RYJ76x{j zd%dr}mQZ_VSKqtfV7!nb5eQm~HO~%$IOigzjS4QbMRLABvP^q|lLq{z2rM(l*q1N9NB{=D8%Y&UWTG3{#%up5GH! zU1rGliE(xV%GK7zYWdPD7iVWk$Ch1G5{x}#lqgt1seFmuAV23i9-I*n8iY*Q=3#K# z4Oh@f%7D9sAb0M>Ox10^8pIks4&LKox4jwSFcMX3(XWrvC60hl7E-J$X-Kp#<1!y1 z{nYqpwDKK*o_oWTgFY7lyEt{_0$EMIMj#+SP8V#wv)4}cB%I4wu;RBoW`Rp?vujId zXiG#UEAuTp=HpDQDU#_pO=D|ek7*_@(rXQ0|n1bNPIK3;MMm5Hz(KiXu0fi0Z z$It@r?-Jst1Uv$iZXINIPDloA>MY$T1wup0P>M_y)fR?iP2ryd3GYfGL<23m`(-gs zEqT7(d);I@I!f~kyd;TbkR_$rl9R;ppe-X+64p)Lvu;qL#4F11eX8(}@@9&`(}4-; zEd*0Hj%;S&O*6}&x|xN4Oh?%rIZ7o@_`+fYU-`DQnZ9)vt?X08tXyRoTM~c#6Fj&@ z;Ku|=Y9BnJ79HWiLjX7wG8cSR{#n*{xfR-Hh`IH`%TN)1-rPF+8th zxJyQO+czj6Fq$Z28aBr-G(5+K_kZWrlcW!vD%ybqg2wAZ=k$1VpxV1MQZbU740WYdW69`awIX^NsyZ}D}b zaPkadmC&s_g#abSlV?2C0X-7+_Iuq40vxyyAnc&7xSx^_I}}!_u^elnDoJ;`_ea9t zQGoB`rBm^OPe8E(#a5YcusI^E)6ho!XGh>M0zn&%=mh-u^pNrVuS;h6jPOjPvNAnvoq+u|K!p)NRJvgJ3&^BmG@$kN+M(oTeqH?10>r z$Q-=i!*p@&ZBTwoV;1O^$ph&rT|_zqGXH{z<@WqlAPi5OftkbnfZwBDy|&V7tU{FW zSz-h(hCB^99DB`%Y{TZoLkCShqHhdn+UqbkEI!if@7oF&54QDYZ`|(j&Lg5t@&wt%};yRgsDx|>ZU01U&vBJzU8)0YS2mPo6Q3X%Mv3hoXwBv6*nkx z1KY76i5r_|aeutVU_2>dyLUlaHX0>1>nrvwro z6Cbolikt>B^R*WAv7N7(qe%xUb0G@%Ld>k%%4#g%d`zah=V1)!1un_-6xLDhF+ouoa&A5rcj($i$2_GF>#2PP-+p@5Ui#%BohgTeqozMKRLoK5ww(Vb&ioV;fe3;Y4K#J8|C`NUcv0t55Vesa_P04)NuI47JNKC}irg_*I!9g*C| z>2SRXyUsJfnuAFaLph8fDpDRZOOUMC!tM@06Tghijx>lT5} z2~e~lJZ-F%D^s(=6$tt7(z~Z=jEL^D?P!=id8)XP){=JN2xQm-P{SIIro4^bsWwJ(crcE2BgI{eOQ~ B9a{hZ diff --git a/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/__pycache__/version.cpython-310.pyc deleted file mode 100644 index 9b45ebf8ab4c8f8fa3bdea159f119039bd9ccb59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 311 zcmYjKyH3L}6t(kcOG*(xfP}hbAV|Q35JI9Ekg6iJf+4bGnfTI1O=8P-q7r@vMt;c) z0~5c%go`?GhI8+^k8{Lm6d{N4=h5ob)vvAi58sI!gs>jFhNBE|%)JsXuB4C!z}jCz9oBwggS`6;m1vt%a&sS#+RIcX5e)v4g8h@TP=o>|*r5 LQGoV?z&pUdyU$ld diff --git a/venv/Lib/site-packages/charset_normalizer/api.py b/venv/Lib/site-packages/charset_normalizer/api.py deleted file mode 100644 index 2c8c061..0000000 --- a/venv/Lib/site-packages/charset_normalizer/api.py +++ /dev/null @@ -1,668 +0,0 @@ -from __future__ import annotations - -import logging -from os import PathLike -from typing import BinaryIO - -from .cd import ( - coherence_ratio, - encoding_languages, - mb_encoding_languages, - merge_coherence_ratios, -) -from .constant import IANA_SUPPORTED, TOO_BIG_SEQUENCE, TOO_SMALL_SEQUENCE, TRACE -from .md import mess_ratio -from .models import CharsetMatch, CharsetMatches -from .utils import ( - any_specified_encoding, - cut_sequence_chunks, - iana_name, - identify_sig_or_bom, - is_cp_similar, - is_multi_byte_encoding, - should_strip_sig_or_bom, -) - -logger = logging.getLogger("charset_normalizer") -explain_handler = logging.StreamHandler() -explain_handler.setFormatter( - logging.Formatter("%(asctime)s | %(levelname)s | %(message)s") -) - - -def from_bytes( - sequences: bytes | bytearray, - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.2, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Given a raw bytes sequence, return the best possibles charset usable to render str objects. - If there is no results, it is a strong indicator that the source is binary/not text. - By default, the process will extract 5 blocks of 512o each to assess the mess and coherence of a given sequence. - And will give up a particular code page after 20% of measured mess. Those criteria are customizable at will. - - The preemptive behavior DOES NOT replace the traditional detection workflow, it prioritize a particular code page - but never take it for granted. Can improve the performance. - - You may want to focus your attention to some code page or/and not others, use cp_isolation and cp_exclusion for that - purpose. - - This function will strip the SIG in the payload/sequence every time except on UTF-16, UTF-32. - By default the library does not setup any handler other than the NullHandler, if you choose to set the 'explain' - toggle to True it will alter the logger configuration to add a StreamHandler that is suitable for debugging. - Custom logging format and handler can be set manually. - """ - - if not isinstance(sequences, (bytearray, bytes)): - raise TypeError( - "Expected object of type bytes or bytearray, got: {}".format( - type(sequences) - ) - ) - - if explain: - previous_logger_level: int = logger.level - logger.addHandler(explain_handler) - logger.setLevel(TRACE) - - length: int = len(sequences) - - if length == 0: - logger.debug("Encoding detection on empty bytes, assuming utf_8 intention.") - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level or logging.WARNING) - return CharsetMatches([CharsetMatch(sequences, "utf_8", 0.0, False, [], "")]) - - if cp_isolation is not None: - logger.log( - TRACE, - "cp_isolation is set. use this flag for debugging purpose. " - "limited list of encoding allowed : %s.", - ", ".join(cp_isolation), - ) - cp_isolation = [iana_name(cp, False) for cp in cp_isolation] - else: - cp_isolation = [] - - if cp_exclusion is not None: - logger.log( - TRACE, - "cp_exclusion is set. use this flag for debugging purpose. " - "limited list of encoding excluded : %s.", - ", ".join(cp_exclusion), - ) - cp_exclusion = [iana_name(cp, False) for cp in cp_exclusion] - else: - cp_exclusion = [] - - if length <= (chunk_size * steps): - logger.log( - TRACE, - "override steps (%i) and chunk_size (%i) as content does not fit (%i byte(s) given) parameters.", - steps, - chunk_size, - length, - ) - steps = 1 - chunk_size = length - - if steps > 1 and length / steps < chunk_size: - chunk_size = int(length / steps) - - is_too_small_sequence: bool = len(sequences) < TOO_SMALL_SEQUENCE - is_too_large_sequence: bool = len(sequences) >= TOO_BIG_SEQUENCE - - if is_too_small_sequence: - logger.log( - TRACE, - "Trying to detect encoding from a tiny portion of ({}) byte(s).".format( - length - ), - ) - elif is_too_large_sequence: - logger.log( - TRACE, - "Using lazy str decoding because the payload is quite large, ({}) byte(s).".format( - length - ), - ) - - prioritized_encodings: list[str] = [] - - specified_encoding: str | None = ( - any_specified_encoding(sequences) if preemptive_behaviour else None - ) - - if specified_encoding is not None: - prioritized_encodings.append(specified_encoding) - logger.log( - TRACE, - "Detected declarative mark in sequence. Priority +1 given for %s.", - specified_encoding, - ) - - tested: set[str] = set() - tested_but_hard_failure: list[str] = [] - tested_but_soft_failure: list[str] = [] - - fallback_ascii: CharsetMatch | None = None - fallback_u8: CharsetMatch | None = None - fallback_specified: CharsetMatch | None = None - - results: CharsetMatches = CharsetMatches() - - early_stop_results: CharsetMatches = CharsetMatches() - - sig_encoding, sig_payload = identify_sig_or_bom(sequences) - - if sig_encoding is not None: - prioritized_encodings.append(sig_encoding) - logger.log( - TRACE, - "Detected a SIG or BOM mark on first %i byte(s). Priority +1 given for %s.", - len(sig_payload), - sig_encoding, - ) - - prioritized_encodings.append("ascii") - - if "utf_8" not in prioritized_encodings: - prioritized_encodings.append("utf_8") - - for encoding_iana in prioritized_encodings + IANA_SUPPORTED: - if cp_isolation and encoding_iana not in cp_isolation: - continue - - if cp_exclusion and encoding_iana in cp_exclusion: - continue - - if encoding_iana in tested: - continue - - tested.add(encoding_iana) - - decoded_payload: str | None = None - bom_or_sig_available: bool = sig_encoding == encoding_iana - strip_sig_or_bom: bool = bom_or_sig_available and should_strip_sig_or_bom( - encoding_iana - ) - - if encoding_iana in {"utf_16", "utf_32"} and not bom_or_sig_available: - logger.log( - TRACE, - "Encoding %s won't be tested as-is because it require a BOM. Will try some sub-encoder LE/BE.", - encoding_iana, - ) - continue - if encoding_iana in {"utf_7"} and not bom_or_sig_available: - logger.log( - TRACE, - "Encoding %s won't be tested as-is because detection is unreliable without BOM/SIG.", - encoding_iana, - ) - continue - - try: - is_multi_byte_decoder: bool = is_multi_byte_encoding(encoding_iana) - except (ModuleNotFoundError, ImportError): - logger.log( - TRACE, - "Encoding %s does not provide an IncrementalDecoder", - encoding_iana, - ) - continue - - try: - if is_too_large_sequence and is_multi_byte_decoder is False: - str( - ( - sequences[: int(50e4)] - if strip_sig_or_bom is False - else sequences[len(sig_payload) : int(50e4)] - ), - encoding=encoding_iana, - ) - else: - decoded_payload = str( - ( - sequences - if strip_sig_or_bom is False - else sequences[len(sig_payload) :] - ), - encoding=encoding_iana, - ) - except (UnicodeDecodeError, LookupError) as e: - if not isinstance(e, LookupError): - logger.log( - TRACE, - "Code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - tested_but_hard_failure.append(encoding_iana) - continue - - similar_soft_failure_test: bool = False - - for encoding_soft_failed in tested_but_soft_failure: - if is_cp_similar(encoding_iana, encoding_soft_failed): - similar_soft_failure_test = True - break - - if similar_soft_failure_test: - logger.log( - TRACE, - "%s is deemed too similar to code page %s and was consider unsuited already. Continuing!", - encoding_iana, - encoding_soft_failed, - ) - continue - - r_ = range( - 0 if not bom_or_sig_available else len(sig_payload), - length, - int(length / steps), - ) - - multi_byte_bonus: bool = ( - is_multi_byte_decoder - and decoded_payload is not None - and len(decoded_payload) < length - ) - - if multi_byte_bonus: - logger.log( - TRACE, - "Code page %s is a multi byte encoding table and it appear that at least one character " - "was encoded using n-bytes.", - encoding_iana, - ) - - max_chunk_gave_up: int = int(len(r_) / 4) - - max_chunk_gave_up = max(max_chunk_gave_up, 2) - early_stop_count: int = 0 - lazy_str_hard_failure = False - - md_chunks: list[str] = [] - md_ratios = [] - - try: - for chunk in cut_sequence_chunks( - sequences, - encoding_iana, - r_, - chunk_size, - bom_or_sig_available, - strip_sig_or_bom, - sig_payload, - is_multi_byte_decoder, - decoded_payload, - ): - md_chunks.append(chunk) - - md_ratios.append( - mess_ratio( - chunk, - threshold, - explain is True and 1 <= len(cp_isolation) <= 2, - ) - ) - - if md_ratios[-1] >= threshold: - early_stop_count += 1 - - if (early_stop_count >= max_chunk_gave_up) or ( - bom_or_sig_available and strip_sig_or_bom is False - ): - break - except ( - UnicodeDecodeError - ) as e: # Lazy str loading may have missed something there - logger.log( - TRACE, - "LazyStr Loading: After MD chunk decode, code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - early_stop_count = max_chunk_gave_up - lazy_str_hard_failure = True - - # We might want to check the sequence again with the whole content - # Only if initial MD tests passes - if ( - not lazy_str_hard_failure - and is_too_large_sequence - and not is_multi_byte_decoder - ): - try: - sequences[int(50e3) :].decode(encoding_iana, errors="strict") - except UnicodeDecodeError as e: - logger.log( - TRACE, - "LazyStr Loading: After final lookup, code page %s does not fit given bytes sequence at ALL. %s", - encoding_iana, - str(e), - ) - tested_but_hard_failure.append(encoding_iana) - continue - - mean_mess_ratio: float = sum(md_ratios) / len(md_ratios) if md_ratios else 0.0 - if mean_mess_ratio >= threshold or early_stop_count >= max_chunk_gave_up: - tested_but_soft_failure.append(encoding_iana) - logger.log( - TRACE, - "%s was excluded because of initial chaos probing. Gave up %i time(s). " - "Computed mean chaos is %f %%.", - encoding_iana, - early_stop_count, - round(mean_mess_ratio * 100, ndigits=3), - ) - # Preparing those fallbacks in case we got nothing. - if ( - enable_fallback - and encoding_iana in ["ascii", "utf_8", specified_encoding] - and not lazy_str_hard_failure - ): - fallback_entry = CharsetMatch( - sequences, - encoding_iana, - threshold, - False, - [], - decoded_payload, - preemptive_declaration=specified_encoding, - ) - if encoding_iana == specified_encoding: - fallback_specified = fallback_entry - elif encoding_iana == "ascii": - fallback_ascii = fallback_entry - else: - fallback_u8 = fallback_entry - continue - - logger.log( - TRACE, - "%s passed initial chaos probing. Mean measured chaos is %f %%", - encoding_iana, - round(mean_mess_ratio * 100, ndigits=3), - ) - - if not is_multi_byte_decoder: - target_languages: list[str] = encoding_languages(encoding_iana) - else: - target_languages = mb_encoding_languages(encoding_iana) - - if target_languages: - logger.log( - TRACE, - "{} should target any language(s) of {}".format( - encoding_iana, str(target_languages) - ), - ) - - cd_ratios = [] - - # We shall skip the CD when its about ASCII - # Most of the time its not relevant to run "language-detection" on it. - if encoding_iana != "ascii": - for chunk in md_chunks: - chunk_languages = coherence_ratio( - chunk, - language_threshold, - ",".join(target_languages) if target_languages else None, - ) - - cd_ratios.append(chunk_languages) - - cd_ratios_merged = merge_coherence_ratios(cd_ratios) - - if cd_ratios_merged: - logger.log( - TRACE, - "We detected language {} using {}".format( - cd_ratios_merged, encoding_iana - ), - ) - - current_match = CharsetMatch( - sequences, - encoding_iana, - mean_mess_ratio, - bom_or_sig_available, - cd_ratios_merged, - ( - decoded_payload - if ( - is_too_large_sequence is False - or encoding_iana in [specified_encoding, "ascii", "utf_8"] - ) - else None - ), - preemptive_declaration=specified_encoding, - ) - - results.append(current_match) - - if ( - encoding_iana in [specified_encoding, "ascii", "utf_8"] - and mean_mess_ratio < 0.1 - ): - # If md says nothing to worry about, then... stop immediately! - if mean_mess_ratio == 0.0: - logger.debug( - "Encoding detection: %s is most likely the one.", - current_match.encoding, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([current_match]) - - early_stop_results.append(current_match) - - if ( - len(early_stop_results) - and (specified_encoding is None or specified_encoding in tested) - and "ascii" in tested - and "utf_8" in tested - ): - probable_result: CharsetMatch = early_stop_results.best() # type: ignore[assignment] - logger.debug( - "Encoding detection: %s is most likely the one.", - probable_result.encoding, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - - return CharsetMatches([probable_result]) - - if encoding_iana == sig_encoding: - logger.debug( - "Encoding detection: %s is most likely the one as we detected a BOM or SIG within " - "the beginning of the sequence.", - encoding_iana, - ) - if explain: # Defensive: ensure exit path clean handler - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - return CharsetMatches([results[encoding_iana]]) - - if len(results) == 0: - if fallback_u8 or fallback_ascii or fallback_specified: - logger.log( - TRACE, - "Nothing got out of the detection process. Using ASCII/UTF-8/Specified fallback.", - ) - - if fallback_specified: - logger.debug( - "Encoding detection: %s will be used as a fallback match", - fallback_specified.encoding, - ) - results.append(fallback_specified) - elif ( - (fallback_u8 and fallback_ascii is None) - or ( - fallback_u8 - and fallback_ascii - and fallback_u8.fingerprint != fallback_ascii.fingerprint - ) - or (fallback_u8 is not None) - ): - logger.debug("Encoding detection: utf_8 will be used as a fallback match") - results.append(fallback_u8) - elif fallback_ascii: - logger.debug("Encoding detection: ascii will be used as a fallback match") - results.append(fallback_ascii) - - if results: - logger.debug( - "Encoding detection: Found %s as plausible (best-candidate) for content. With %i alternatives.", - results.best().encoding, # type: ignore - len(results) - 1, - ) - else: - logger.debug("Encoding detection: Unable to determine any suitable charset.") - - if explain: - logger.removeHandler(explain_handler) - logger.setLevel(previous_logger_level) - - return results - - -def from_fp( - fp: BinaryIO, - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Same thing than the function from_bytes but using a file pointer that is already ready. - Will not close the file pointer. - """ - return from_bytes( - fp.read(), - steps, - chunk_size, - threshold, - cp_isolation, - cp_exclusion, - preemptive_behaviour, - explain, - language_threshold, - enable_fallback, - ) - - -def from_path( - path: str | bytes | PathLike, # type: ignore[type-arg] - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = True, -) -> CharsetMatches: - """ - Same thing than the function from_bytes but with one extra step. Opening and reading given file path in binary mode. - Can raise IOError. - """ - with open(path, "rb") as fp: - return from_fp( - fp, - steps, - chunk_size, - threshold, - cp_isolation, - cp_exclusion, - preemptive_behaviour, - explain, - language_threshold, - enable_fallback, - ) - - -def is_binary( - fp_or_path_or_payload: PathLike | str | BinaryIO | bytes, # type: ignore[type-arg] - steps: int = 5, - chunk_size: int = 512, - threshold: float = 0.20, - cp_isolation: list[str] | None = None, - cp_exclusion: list[str] | None = None, - preemptive_behaviour: bool = True, - explain: bool = False, - language_threshold: float = 0.1, - enable_fallback: bool = False, -) -> bool: - """ - Detect if the given input (file, bytes, or path) points to a binary file. aka. not a string. - Based on the same main heuristic algorithms and default kwargs at the sole exception that fallbacks match - are disabled to be stricter around ASCII-compatible but unlikely to be a string. - """ - if isinstance(fp_or_path_or_payload, (str, PathLike)): - guesses = from_path( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - elif isinstance( - fp_or_path_or_payload, - ( - bytes, - bytearray, - ), - ): - guesses = from_bytes( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - else: - guesses = from_fp( - fp_or_path_or_payload, - steps=steps, - chunk_size=chunk_size, - threshold=threshold, - cp_isolation=cp_isolation, - cp_exclusion=cp_exclusion, - preemptive_behaviour=preemptive_behaviour, - explain=explain, - language_threshold=language_threshold, - enable_fallback=enable_fallback, - ) - - return not guesses diff --git a/venv/Lib/site-packages/charset_normalizer/cd.py b/venv/Lib/site-packages/charset_normalizer/cd.py deleted file mode 100644 index 71a3ed5..0000000 --- a/venv/Lib/site-packages/charset_normalizer/cd.py +++ /dev/null @@ -1,395 +0,0 @@ -from __future__ import annotations - -import importlib -from codecs import IncrementalDecoder -from collections import Counter -from functools import lru_cache -from typing import Counter as TypeCounter - -from .constant import ( - FREQUENCIES, - KO_NAMES, - LANGUAGE_SUPPORTED_COUNT, - TOO_SMALL_SEQUENCE, - ZH_NAMES, -) -from .md import is_suspiciously_successive_range -from .models import CoherenceMatches -from .utils import ( - is_accentuated, - is_latin, - is_multi_byte_encoding, - is_unicode_range_secondary, - unicode_range, -) - - -def encoding_unicode_range(iana_name: str) -> list[str]: - """ - Return associated unicode ranges in a single byte code page. - """ - if is_multi_byte_encoding(iana_name): - raise OSError("Function not supported on multi-byte code page") - - decoder = importlib.import_module(f"encodings.{iana_name}").IncrementalDecoder - - p: IncrementalDecoder = decoder(errors="ignore") - seen_ranges: dict[str, int] = {} - character_count: int = 0 - - for i in range(0x40, 0xFF): - chunk: str = p.decode(bytes([i])) - - if chunk: - character_range: str | None = unicode_range(chunk) - - if character_range is None: - continue - - if is_unicode_range_secondary(character_range) is False: - if character_range not in seen_ranges: - seen_ranges[character_range] = 0 - seen_ranges[character_range] += 1 - character_count += 1 - - return sorted( - [ - character_range - for character_range in seen_ranges - if seen_ranges[character_range] / character_count >= 0.15 - ] - ) - - -def unicode_range_languages(primary_range: str) -> list[str]: - """ - Return inferred languages used with a unicode range. - """ - languages: list[str] = [] - - for language, characters in FREQUENCIES.items(): - for character in characters: - if unicode_range(character) == primary_range: - languages.append(language) - break - - return languages - - -@lru_cache() -def encoding_languages(iana_name: str) -> list[str]: - """ - Single-byte encoding language association. Some code page are heavily linked to particular language(s). - This function does the correspondence. - """ - unicode_ranges: list[str] = encoding_unicode_range(iana_name) - primary_range: str | None = None - - for specified_range in unicode_ranges: - if "Latin" not in specified_range: - primary_range = specified_range - break - - if primary_range is None: - return ["Latin Based"] - - return unicode_range_languages(primary_range) - - -@lru_cache() -def mb_encoding_languages(iana_name: str) -> list[str]: - """ - Multi-byte encoding language association. Some code page are heavily linked to particular language(s). - This function does the correspondence. - """ - if ( - iana_name.startswith("shift_") - or iana_name.startswith("iso2022_jp") - or iana_name.startswith("euc_j") - or iana_name == "cp932" - ): - return ["Japanese"] - if iana_name.startswith("gb") or iana_name in ZH_NAMES: - return ["Chinese"] - if iana_name.startswith("iso2022_kr") or iana_name in KO_NAMES: - return ["Korean"] - - return [] - - -@lru_cache(maxsize=LANGUAGE_SUPPORTED_COUNT) -def get_target_features(language: str) -> tuple[bool, bool]: - """ - Determine main aspects from a supported language if it contains accents and if is pure Latin. - """ - target_have_accents: bool = False - target_pure_latin: bool = True - - for character in FREQUENCIES[language]: - if not target_have_accents and is_accentuated(character): - target_have_accents = True - if target_pure_latin and is_latin(character) is False: - target_pure_latin = False - - return target_have_accents, target_pure_latin - - -def alphabet_languages( - characters: list[str], ignore_non_latin: bool = False -) -> list[str]: - """ - Return associated languages associated to given characters. - """ - languages: list[tuple[str, float]] = [] - - source_have_accents = any(is_accentuated(character) for character in characters) - - for language, language_characters in FREQUENCIES.items(): - target_have_accents, target_pure_latin = get_target_features(language) - - if ignore_non_latin and target_pure_latin is False: - continue - - if target_have_accents is False and source_have_accents: - continue - - character_count: int = len(language_characters) - - character_match_count: int = len( - [c for c in language_characters if c in characters] - ) - - ratio: float = character_match_count / character_count - - if ratio >= 0.2: - languages.append((language, ratio)) - - languages = sorted(languages, key=lambda x: x[1], reverse=True) - - return [compatible_language[0] for compatible_language in languages] - - -def characters_popularity_compare( - language: str, ordered_characters: list[str] -) -> float: - """ - Determine if a ordered characters list (by occurrence from most appearance to rarest) match a particular language. - The result is a ratio between 0. (absolutely no correspondence) and 1. (near perfect fit). - Beware that is function is not strict on the match in order to ease the detection. (Meaning close match is 1.) - """ - if language not in FREQUENCIES: - raise ValueError(f"{language} not available") - - character_approved_count: int = 0 - FREQUENCIES_language_set = set(FREQUENCIES[language]) - - ordered_characters_count: int = len(ordered_characters) - target_language_characters_count: int = len(FREQUENCIES[language]) - - large_alphabet: bool = target_language_characters_count > 26 - - for character, character_rank in zip( - ordered_characters, range(0, ordered_characters_count) - ): - if character not in FREQUENCIES_language_set: - continue - - character_rank_in_language: int = FREQUENCIES[language].index(character) - expected_projection_ratio: float = ( - target_language_characters_count / ordered_characters_count - ) - character_rank_projection: int = int(character_rank * expected_projection_ratio) - - if ( - large_alphabet is False - and abs(character_rank_projection - character_rank_in_language) > 4 - ): - continue - - if ( - large_alphabet is True - and abs(character_rank_projection - character_rank_in_language) - < target_language_characters_count / 3 - ): - character_approved_count += 1 - continue - - characters_before_source: list[str] = FREQUENCIES[language][ - 0:character_rank_in_language - ] - characters_after_source: list[str] = FREQUENCIES[language][ - character_rank_in_language: - ] - characters_before: list[str] = ordered_characters[0:character_rank] - characters_after: list[str] = ordered_characters[character_rank:] - - before_match_count: int = len( - set(characters_before) & set(characters_before_source) - ) - - after_match_count: int = len( - set(characters_after) & set(characters_after_source) - ) - - if len(characters_before_source) == 0 and before_match_count <= 4: - character_approved_count += 1 - continue - - if len(characters_after_source) == 0 and after_match_count <= 4: - character_approved_count += 1 - continue - - if ( - before_match_count / len(characters_before_source) >= 0.4 - or after_match_count / len(characters_after_source) >= 0.4 - ): - character_approved_count += 1 - continue - - return character_approved_count / len(ordered_characters) - - -def alpha_unicode_split(decoded_sequence: str) -> list[str]: - """ - Given a decoded text sequence, return a list of str. Unicode range / alphabet separation. - Ex. a text containing English/Latin with a bit a Hebrew will return two items in the resulting list; - One containing the latin letters and the other hebrew. - """ - layers: dict[str, str] = {} - - for character in decoded_sequence: - if character.isalpha() is False: - continue - - character_range: str | None = unicode_range(character) - - if character_range is None: - continue - - layer_target_range: str | None = None - - for discovered_range in layers: - if ( - is_suspiciously_successive_range(discovered_range, character_range) - is False - ): - layer_target_range = discovered_range - break - - if layer_target_range is None: - layer_target_range = character_range - - if layer_target_range not in layers: - layers[layer_target_range] = character.lower() - continue - - layers[layer_target_range] += character.lower() - - return list(layers.values()) - - -def merge_coherence_ratios(results: list[CoherenceMatches]) -> CoherenceMatches: - """ - This function merge results previously given by the function coherence_ratio. - The return type is the same as coherence_ratio. - """ - per_language_ratios: dict[str, list[float]] = {} - for result in results: - for sub_result in result: - language, ratio = sub_result - if language not in per_language_ratios: - per_language_ratios[language] = [ratio] - continue - per_language_ratios[language].append(ratio) - - merge = [ - ( - language, - round( - sum(per_language_ratios[language]) / len(per_language_ratios[language]), - 4, - ), - ) - for language in per_language_ratios - ] - - return sorted(merge, key=lambda x: x[1], reverse=True) - - -def filter_alt_coherence_matches(results: CoherenceMatches) -> CoherenceMatches: - """ - We shall NOT return "English—" in CoherenceMatches because it is an alternative - of "English". This function only keeps the best match and remove the em-dash in it. - """ - index_results: dict[str, list[float]] = dict() - - for result in results: - language, ratio = result - no_em_name: str = language.replace("—", "") - - if no_em_name not in index_results: - index_results[no_em_name] = [] - - index_results[no_em_name].append(ratio) - - if any(len(index_results[e]) > 1 for e in index_results): - filtered_results: CoherenceMatches = [] - - for language in index_results: - filtered_results.append((language, max(index_results[language]))) - - return filtered_results - - return results - - -@lru_cache(maxsize=2048) -def coherence_ratio( - decoded_sequence: str, threshold: float = 0.1, lg_inclusion: str | None = None -) -> CoherenceMatches: - """ - Detect ANY language that can be identified in given sequence. The sequence will be analysed by layers. - A layer = Character extraction by alphabets/ranges. - """ - - results: list[tuple[str, float]] = [] - ignore_non_latin: bool = False - - sufficient_match_count: int = 0 - - lg_inclusion_list = lg_inclusion.split(",") if lg_inclusion is not None else [] - if "Latin Based" in lg_inclusion_list: - ignore_non_latin = True - lg_inclusion_list.remove("Latin Based") - - for layer in alpha_unicode_split(decoded_sequence): - sequence_frequencies: TypeCounter[str] = Counter(layer) - most_common = sequence_frequencies.most_common() - - character_count: int = sum(o for c, o in most_common) - - if character_count <= TOO_SMALL_SEQUENCE: - continue - - popular_character_ordered: list[str] = [c for c, o in most_common] - - for language in lg_inclusion_list or alphabet_languages( - popular_character_ordered, ignore_non_latin - ): - ratio: float = characters_popularity_compare( - language, popular_character_ordered - ) - - if ratio < threshold: - continue - elif ratio >= 0.8: - sufficient_match_count += 1 - - results.append((language, round(ratio, 4))) - - if sufficient_match_count >= 3: - break - - return sorted( - filter_alt_coherence_matches(results), key=lambda x: x[1], reverse=True - ) diff --git a/venv/Lib/site-packages/charset_normalizer/cli/__init__.py b/venv/Lib/site-packages/charset_normalizer/cli/__init__.py deleted file mode 100644 index 543a5a4..0000000 --- a/venv/Lib/site-packages/charset_normalizer/cli/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import annotations - -from .__main__ import cli_detect, query_yes_no - -__all__ = ( - "cli_detect", - "query_yes_no", -) diff --git a/venv/Lib/site-packages/charset_normalizer/cli/__main__.py b/venv/Lib/site-packages/charset_normalizer/cli/__main__.py deleted file mode 100644 index cb64156..0000000 --- a/venv/Lib/site-packages/charset_normalizer/cli/__main__.py +++ /dev/null @@ -1,381 +0,0 @@ -from __future__ import annotations - -import argparse -import sys -import typing -from json import dumps -from os.path import abspath, basename, dirname, join, realpath -from platform import python_version -from unicodedata import unidata_version - -import charset_normalizer.md as md_module -from charset_normalizer import from_fp -from charset_normalizer.models import CliDetectionResult -from charset_normalizer.version import __version__ - - -def query_yes_no(question: str, default: str = "yes") -> bool: - """Ask a yes/no question via input() and return their answer. - - "question" is a string that is presented to the user. - "default" is the presumed answer if the user just hits . - It must be "yes" (the default), "no" or None (meaning - an answer is required of the user). - - The "answer" return value is True for "yes" or False for "no". - - Credit goes to (c) https://stackoverflow.com/questions/3041986/apt-command-line-interface-like-yes-no-input - """ - valid = {"yes": True, "y": True, "ye": True, "no": False, "n": False} - if default is None: - prompt = " [y/n] " - elif default == "yes": - prompt = " [Y/n] " - elif default == "no": - prompt = " [y/N] " - else: - raise ValueError("invalid default answer: '%s'" % default) - - while True: - sys.stdout.write(question + prompt) - choice = input().lower() - if default is not None and choice == "": - return valid[default] - elif choice in valid: - return valid[choice] - else: - sys.stdout.write("Please respond with 'yes' or 'no' (or 'y' or 'n').\n") - - -class FileType: - """Factory for creating file object types - - Instances of FileType are typically passed as type= arguments to the - ArgumentParser add_argument() method. - - Keyword Arguments: - - mode -- A string indicating how the file is to be opened. Accepts the - same values as the builtin open() function. - - bufsize -- The file's desired buffer size. Accepts the same values as - the builtin open() function. - - encoding -- The file's encoding. Accepts the same values as the - builtin open() function. - - errors -- A string indicating how encoding and decoding errors are to - be handled. Accepts the same value as the builtin open() function. - - Backported from CPython 3.12 - """ - - def __init__( - self, - mode: str = "r", - bufsize: int = -1, - encoding: str | None = None, - errors: str | None = None, - ): - self._mode = mode - self._bufsize = bufsize - self._encoding = encoding - self._errors = errors - - def __call__(self, string: str) -> typing.IO: # type: ignore[type-arg] - # the special argument "-" means sys.std{in,out} - if string == "-": - if "r" in self._mode: - return sys.stdin.buffer if "b" in self._mode else sys.stdin - elif any(c in self._mode for c in "wax"): - return sys.stdout.buffer if "b" in self._mode else sys.stdout - else: - msg = f'argument "-" with mode {self._mode}' - raise ValueError(msg) - - # all other arguments are used as file names - try: - return open(string, self._mode, self._bufsize, self._encoding, self._errors) - except OSError as e: - message = f"can't open '{string}': {e}" - raise argparse.ArgumentTypeError(message) - - def __repr__(self) -> str: - args = self._mode, self._bufsize - kwargs = [("encoding", self._encoding), ("errors", self._errors)] - args_str = ", ".join( - [repr(arg) for arg in args if arg != -1] - + [f"{kw}={arg!r}" for kw, arg in kwargs if arg is not None] - ) - return f"{type(self).__name__}({args_str})" - - -def cli_detect(argv: list[str] | None = None) -> int: - """ - CLI assistant using ARGV and ArgumentParser - :param argv: - :return: 0 if everything is fine, anything else equal trouble - """ - parser = argparse.ArgumentParser( - description="The Real First Universal Charset Detector. " - "Discover originating encoding used on text file. " - "Normalize text to unicode." - ) - - parser.add_argument( - "files", type=FileType("rb"), nargs="+", help="File(s) to be analysed" - ) - parser.add_argument( - "-v", - "--verbose", - action="store_true", - default=False, - dest="verbose", - help="Display complementary information about file if any. " - "Stdout will contain logs about the detection process.", - ) - parser.add_argument( - "-a", - "--with-alternative", - action="store_true", - default=False, - dest="alternatives", - help="Output complementary possibilities if any. Top-level JSON WILL be a list.", - ) - parser.add_argument( - "-n", - "--normalize", - action="store_true", - default=False, - dest="normalize", - help="Permit to normalize input file. If not set, program does not write anything.", - ) - parser.add_argument( - "-m", - "--minimal", - action="store_true", - default=False, - dest="minimal", - help="Only output the charset detected to STDOUT. Disabling JSON output.", - ) - parser.add_argument( - "-r", - "--replace", - action="store_true", - default=False, - dest="replace", - help="Replace file when trying to normalize it instead of creating a new one.", - ) - parser.add_argument( - "-f", - "--force", - action="store_true", - default=False, - dest="force", - help="Replace file without asking if you are sure, use this flag with caution.", - ) - parser.add_argument( - "-i", - "--no-preemptive", - action="store_true", - default=False, - dest="no_preemptive", - help="Disable looking at a charset declaration to hint the detector.", - ) - parser.add_argument( - "-t", - "--threshold", - action="store", - default=0.2, - type=float, - dest="threshold", - help="Define a custom maximum amount of noise allowed in decoded content. 0. <= noise <= 1.", - ) - parser.add_argument( - "--version", - action="version", - version="Charset-Normalizer {} - Python {} - Unicode {} - SpeedUp {}".format( - __version__, - python_version(), - unidata_version, - "OFF" if md_module.__file__.lower().endswith(".py") else "ON", - ), - help="Show version information and exit.", - ) - - args = parser.parse_args(argv) - - if args.replace is True and args.normalize is False: - if args.files: - for my_file in args.files: - my_file.close() - print("Use --replace in addition of --normalize only.", file=sys.stderr) - return 1 - - if args.force is True and args.replace is False: - if args.files: - for my_file in args.files: - my_file.close() - print("Use --force in addition of --replace only.", file=sys.stderr) - return 1 - - if args.threshold < 0.0 or args.threshold > 1.0: - if args.files: - for my_file in args.files: - my_file.close() - print("--threshold VALUE should be between 0. AND 1.", file=sys.stderr) - return 1 - - x_ = [] - - for my_file in args.files: - matches = from_fp( - my_file, - threshold=args.threshold, - explain=args.verbose, - preemptive_behaviour=args.no_preemptive is False, - ) - - best_guess = matches.best() - - if best_guess is None: - print( - 'Unable to identify originating encoding for "{}". {}'.format( - my_file.name, - ( - "Maybe try increasing maximum amount of chaos." - if args.threshold < 1.0 - else "" - ), - ), - file=sys.stderr, - ) - x_.append( - CliDetectionResult( - abspath(my_file.name), - None, - [], - [], - "Unknown", - [], - False, - 1.0, - 0.0, - None, - True, - ) - ) - else: - x_.append( - CliDetectionResult( - abspath(my_file.name), - best_guess.encoding, - best_guess.encoding_aliases, - [ - cp - for cp in best_guess.could_be_from_charset - if cp != best_guess.encoding - ], - best_guess.language, - best_guess.alphabets, - best_guess.bom, - best_guess.percent_chaos, - best_guess.percent_coherence, - None, - True, - ) - ) - - if len(matches) > 1 and args.alternatives: - for el in matches: - if el != best_guess: - x_.append( - CliDetectionResult( - abspath(my_file.name), - el.encoding, - el.encoding_aliases, - [ - cp - for cp in el.could_be_from_charset - if cp != el.encoding - ], - el.language, - el.alphabets, - el.bom, - el.percent_chaos, - el.percent_coherence, - None, - False, - ) - ) - - if args.normalize is True: - if best_guess.encoding.startswith("utf") is True: - print( - '"{}" file does not need to be normalized, as it already came from unicode.'.format( - my_file.name - ), - file=sys.stderr, - ) - if my_file.closed is False: - my_file.close() - continue - - dir_path = dirname(realpath(my_file.name)) - file_name = basename(realpath(my_file.name)) - - o_: list[str] = file_name.split(".") - - if args.replace is False: - o_.insert(-1, best_guess.encoding) - if my_file.closed is False: - my_file.close() - elif ( - args.force is False - and query_yes_no( - 'Are you sure to normalize "{}" by replacing it ?'.format( - my_file.name - ), - "no", - ) - is False - ): - if my_file.closed is False: - my_file.close() - continue - - try: - x_[0].unicode_path = join(dir_path, ".".join(o_)) - - with open(x_[0].unicode_path, "wb") as fp: - fp.write(best_guess.output()) - except OSError as e: - print(str(e), file=sys.stderr) - if my_file.closed is False: - my_file.close() - return 2 - - if my_file.closed is False: - my_file.close() - - if args.minimal is False: - print( - dumps( - [el.__dict__ for el in x_] if len(x_) > 1 else x_[0].__dict__, - ensure_ascii=True, - indent=4, - ) - ) - else: - for my_file in args.files: - print( - ", ".join( - [ - el.encoding or "undefined" - for el in x_ - if el.path == abspath(my_file.name) - ] - ) - ) - - return 0 - - -if __name__ == "__main__": - cli_detect() diff --git a/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 2985da8d4a0ecc33bbdcc9f92b247003126b697d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 312 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 O)_$!0IJ*;uwDCV(=h9;U diff --git a/venv/Lib/site-packages/charset_normalizer/constant.py b/venv/Lib/site-packages/charset_normalizer/constant.py deleted file mode 100644 index cc71a01..0000000 --- a/venv/Lib/site-packages/charset_normalizer/constant.py +++ /dev/null @@ -1,2015 +0,0 @@ -from __future__ import annotations - -from codecs import BOM_UTF8, BOM_UTF16_BE, BOM_UTF16_LE, BOM_UTF32_BE, BOM_UTF32_LE -from encodings.aliases import aliases -from re import IGNORECASE -from re import compile as re_compile - -# Contain for each eligible encoding a list of/item bytes SIG/BOM -ENCODING_MARKS: dict[str, bytes | list[bytes]] = { - "utf_8": BOM_UTF8, - "utf_7": [ - b"\x2b\x2f\x76\x38", - b"\x2b\x2f\x76\x39", - b"\x2b\x2f\x76\x2b", - b"\x2b\x2f\x76\x2f", - b"\x2b\x2f\x76\x38\x2d", - ], - "gb18030": b"\x84\x31\x95\x33", - "utf_32": [BOM_UTF32_BE, BOM_UTF32_LE], - "utf_16": [BOM_UTF16_BE, BOM_UTF16_LE], -} - -TOO_SMALL_SEQUENCE: int = 32 -TOO_BIG_SEQUENCE: int = int(10e6) - -UTF8_MAXIMAL_ALLOCATION: int = 1_112_064 - -# Up-to-date Unicode ucd/15.0.0 -UNICODE_RANGES_COMBINED: dict[str, range] = { - "Control character": range(32), - "Basic Latin": range(32, 128), - "Latin-1 Supplement": range(128, 256), - "Latin Extended-A": range(256, 384), - "Latin Extended-B": range(384, 592), - "IPA Extensions": range(592, 688), - "Spacing Modifier Letters": range(688, 768), - "Combining Diacritical Marks": range(768, 880), - "Greek and Coptic": range(880, 1024), - "Cyrillic": range(1024, 1280), - "Cyrillic Supplement": range(1280, 1328), - "Armenian": range(1328, 1424), - "Hebrew": range(1424, 1536), - "Arabic": range(1536, 1792), - "Syriac": range(1792, 1872), - "Arabic Supplement": range(1872, 1920), - "Thaana": range(1920, 1984), - "NKo": range(1984, 2048), - "Samaritan": range(2048, 2112), - "Mandaic": range(2112, 2144), - "Syriac Supplement": range(2144, 2160), - "Arabic Extended-B": range(2160, 2208), - "Arabic Extended-A": range(2208, 2304), - "Devanagari": range(2304, 2432), - "Bengali": range(2432, 2560), - "Gurmukhi": range(2560, 2688), - "Gujarati": range(2688, 2816), - "Oriya": range(2816, 2944), - "Tamil": range(2944, 3072), - "Telugu": range(3072, 3200), - "Kannada": range(3200, 3328), - "Malayalam": range(3328, 3456), - "Sinhala": range(3456, 3584), - "Thai": range(3584, 3712), - "Lao": range(3712, 3840), - "Tibetan": range(3840, 4096), - "Myanmar": range(4096, 4256), - "Georgian": range(4256, 4352), - "Hangul Jamo": range(4352, 4608), - "Ethiopic": range(4608, 4992), - "Ethiopic Supplement": range(4992, 5024), - "Cherokee": range(5024, 5120), - "Unified Canadian Aboriginal Syllabics": range(5120, 5760), - "Ogham": range(5760, 5792), - "Runic": range(5792, 5888), - "Tagalog": range(5888, 5920), - "Hanunoo": range(5920, 5952), - "Buhid": range(5952, 5984), - "Tagbanwa": range(5984, 6016), - "Khmer": range(6016, 6144), - "Mongolian": range(6144, 6320), - "Unified Canadian Aboriginal Syllabics Extended": range(6320, 6400), - "Limbu": range(6400, 6480), - "Tai Le": range(6480, 6528), - "New Tai Lue": range(6528, 6624), - "Khmer Symbols": range(6624, 6656), - "Buginese": range(6656, 6688), - "Tai Tham": range(6688, 6832), - "Combining Diacritical Marks Extended": range(6832, 6912), - "Balinese": range(6912, 7040), - "Sundanese": range(7040, 7104), - "Batak": range(7104, 7168), - "Lepcha": range(7168, 7248), - "Ol Chiki": range(7248, 7296), - "Cyrillic Extended-C": range(7296, 7312), - "Georgian Extended": range(7312, 7360), - "Sundanese Supplement": range(7360, 7376), - "Vedic Extensions": range(7376, 7424), - "Phonetic Extensions": range(7424, 7552), - "Phonetic Extensions Supplement": range(7552, 7616), - "Combining Diacritical Marks Supplement": range(7616, 7680), - "Latin Extended Additional": range(7680, 7936), - "Greek Extended": range(7936, 8192), - "General Punctuation": range(8192, 8304), - "Superscripts and Subscripts": range(8304, 8352), - "Currency Symbols": range(8352, 8400), - "Combining Diacritical Marks for Symbols": range(8400, 8448), - "Letterlike Symbols": range(8448, 8528), - "Number Forms": range(8528, 8592), - "Arrows": range(8592, 8704), - "Mathematical Operators": range(8704, 8960), - "Miscellaneous Technical": range(8960, 9216), - "Control Pictures": range(9216, 9280), - "Optical Character Recognition": range(9280, 9312), - "Enclosed Alphanumerics": range(9312, 9472), - "Box Drawing": range(9472, 9600), - "Block Elements": range(9600, 9632), - "Geometric Shapes": range(9632, 9728), - "Miscellaneous Symbols": range(9728, 9984), - "Dingbats": range(9984, 10176), - "Miscellaneous Mathematical Symbols-A": range(10176, 10224), - "Supplemental Arrows-A": range(10224, 10240), - "Braille Patterns": range(10240, 10496), - "Supplemental Arrows-B": range(10496, 10624), - "Miscellaneous Mathematical Symbols-B": range(10624, 10752), - "Supplemental Mathematical Operators": range(10752, 11008), - "Miscellaneous Symbols and Arrows": range(11008, 11264), - "Glagolitic": range(11264, 11360), - "Latin Extended-C": range(11360, 11392), - "Coptic": range(11392, 11520), - "Georgian Supplement": range(11520, 11568), - "Tifinagh": range(11568, 11648), - "Ethiopic Extended": range(11648, 11744), - "Cyrillic Extended-A": range(11744, 11776), - "Supplemental Punctuation": range(11776, 11904), - "CJK Radicals Supplement": range(11904, 12032), - "Kangxi Radicals": range(12032, 12256), - "Ideographic Description Characters": range(12272, 12288), - "CJK Symbols and Punctuation": range(12288, 12352), - "Hiragana": range(12352, 12448), - "Katakana": range(12448, 12544), - "Bopomofo": range(12544, 12592), - "Hangul Compatibility Jamo": range(12592, 12688), - "Kanbun": range(12688, 12704), - "Bopomofo Extended": range(12704, 12736), - "CJK Strokes": range(12736, 12784), - "Katakana Phonetic Extensions": range(12784, 12800), - "Enclosed CJK Letters and Months": range(12800, 13056), - "CJK Compatibility": range(13056, 13312), - "CJK Unified Ideographs Extension A": range(13312, 19904), - "Yijing Hexagram Symbols": range(19904, 19968), - "CJK Unified Ideographs": range(19968, 40960), - "Yi Syllables": range(40960, 42128), - "Yi Radicals": range(42128, 42192), - "Lisu": range(42192, 42240), - "Vai": range(42240, 42560), - "Cyrillic Extended-B": range(42560, 42656), - "Bamum": range(42656, 42752), - "Modifier Tone Letters": range(42752, 42784), - "Latin Extended-D": range(42784, 43008), - "Syloti Nagri": range(43008, 43056), - "Common Indic Number Forms": range(43056, 43072), - "Phags-pa": range(43072, 43136), - "Saurashtra": range(43136, 43232), - "Devanagari Extended": range(43232, 43264), - "Kayah Li": range(43264, 43312), - "Rejang": range(43312, 43360), - "Hangul Jamo Extended-A": range(43360, 43392), - "Javanese": range(43392, 43488), - "Myanmar Extended-B": range(43488, 43520), - "Cham": range(43520, 43616), - "Myanmar Extended-A": range(43616, 43648), - "Tai Viet": range(43648, 43744), - "Meetei Mayek Extensions": range(43744, 43776), - "Ethiopic Extended-A": range(43776, 43824), - "Latin Extended-E": range(43824, 43888), - "Cherokee Supplement": range(43888, 43968), - "Meetei Mayek": range(43968, 44032), - "Hangul Syllables": range(44032, 55216), - "Hangul Jamo Extended-B": range(55216, 55296), - "High Surrogates": range(55296, 56192), - "High Private Use Surrogates": range(56192, 56320), - "Low Surrogates": range(56320, 57344), - "Private Use Area": range(57344, 63744), - "CJK Compatibility Ideographs": range(63744, 64256), - "Alphabetic Presentation Forms": range(64256, 64336), - "Arabic Presentation Forms-A": range(64336, 65024), - "Variation Selectors": range(65024, 65040), - "Vertical Forms": range(65040, 65056), - "Combining Half Marks": range(65056, 65072), - "CJK Compatibility Forms": range(65072, 65104), - "Small Form Variants": range(65104, 65136), - "Arabic Presentation Forms-B": range(65136, 65280), - "Halfwidth and Fullwidth Forms": range(65280, 65520), - "Specials": range(65520, 65536), - "Linear B Syllabary": range(65536, 65664), - "Linear B Ideograms": range(65664, 65792), - "Aegean Numbers": range(65792, 65856), - "Ancient Greek Numbers": range(65856, 65936), - "Ancient Symbols": range(65936, 66000), - "Phaistos Disc": range(66000, 66048), - "Lycian": range(66176, 66208), - "Carian": range(66208, 66272), - "Coptic Epact Numbers": range(66272, 66304), - "Old Italic": range(66304, 66352), - "Gothic": range(66352, 66384), - "Old Permic": range(66384, 66432), - "Ugaritic": range(66432, 66464), - "Old Persian": range(66464, 66528), - "Deseret": range(66560, 66640), - "Shavian": range(66640, 66688), - "Osmanya": range(66688, 66736), - "Osage": range(66736, 66816), - "Elbasan": range(66816, 66864), - "Caucasian Albanian": range(66864, 66928), - "Vithkuqi": range(66928, 67008), - "Linear A": range(67072, 67456), - "Latin Extended-F": range(67456, 67520), - "Cypriot Syllabary": range(67584, 67648), - "Imperial Aramaic": range(67648, 67680), - "Palmyrene": range(67680, 67712), - "Nabataean": range(67712, 67760), - "Hatran": range(67808, 67840), - "Phoenician": range(67840, 67872), - "Lydian": range(67872, 67904), - "Meroitic Hieroglyphs": range(67968, 68000), - "Meroitic Cursive": range(68000, 68096), - "Kharoshthi": range(68096, 68192), - "Old South Arabian": range(68192, 68224), - "Old North Arabian": range(68224, 68256), - "Manichaean": range(68288, 68352), - "Avestan": range(68352, 68416), - "Inscriptional Parthian": range(68416, 68448), - "Inscriptional Pahlavi": range(68448, 68480), - "Psalter Pahlavi": range(68480, 68528), - "Old Turkic": range(68608, 68688), - "Old Hungarian": range(68736, 68864), - "Hanifi Rohingya": range(68864, 68928), - "Rumi Numeral Symbols": range(69216, 69248), - "Yezidi": range(69248, 69312), - "Arabic Extended-C": range(69312, 69376), - "Old Sogdian": range(69376, 69424), - "Sogdian": range(69424, 69488), - "Old Uyghur": range(69488, 69552), - "Chorasmian": range(69552, 69600), - "Elymaic": range(69600, 69632), - "Brahmi": range(69632, 69760), - "Kaithi": range(69760, 69840), - "Sora Sompeng": range(69840, 69888), - "Chakma": range(69888, 69968), - "Mahajani": range(69968, 70016), - "Sharada": range(70016, 70112), - "Sinhala Archaic Numbers": range(70112, 70144), - "Khojki": range(70144, 70224), - "Multani": range(70272, 70320), - "Khudawadi": range(70320, 70400), - "Grantha": range(70400, 70528), - "Newa": range(70656, 70784), - "Tirhuta": range(70784, 70880), - "Siddham": range(71040, 71168), - "Modi": range(71168, 71264), - "Mongolian Supplement": range(71264, 71296), - "Takri": range(71296, 71376), - "Ahom": range(71424, 71504), - "Dogra": range(71680, 71760), - "Warang Citi": range(71840, 71936), - "Dives Akuru": range(71936, 72032), - "Nandinagari": range(72096, 72192), - "Zanabazar Square": range(72192, 72272), - "Soyombo": range(72272, 72368), - "Unified Canadian Aboriginal Syllabics Extended-A": range(72368, 72384), - "Pau Cin Hau": range(72384, 72448), - "Devanagari Extended-A": range(72448, 72544), - "Bhaiksuki": range(72704, 72816), - "Marchen": range(72816, 72896), - "Masaram Gondi": range(72960, 73056), - "Gunjala Gondi": range(73056, 73136), - "Makasar": range(73440, 73472), - "Kawi": range(73472, 73568), - "Lisu Supplement": range(73648, 73664), - "Tamil Supplement": range(73664, 73728), - "Cuneiform": range(73728, 74752), - "Cuneiform Numbers and Punctuation": range(74752, 74880), - "Early Dynastic Cuneiform": range(74880, 75088), - "Cypro-Minoan": range(77712, 77824), - "Egyptian Hieroglyphs": range(77824, 78896), - "Egyptian Hieroglyph Format Controls": range(78896, 78944), - "Anatolian Hieroglyphs": range(82944, 83584), - "Bamum Supplement": range(92160, 92736), - "Mro": range(92736, 92784), - "Tangsa": range(92784, 92880), - "Bassa Vah": range(92880, 92928), - "Pahawh Hmong": range(92928, 93072), - "Medefaidrin": range(93760, 93856), - "Miao": range(93952, 94112), - "Ideographic Symbols and Punctuation": range(94176, 94208), - "Tangut": range(94208, 100352), - "Tangut Components": range(100352, 101120), - "Khitan Small Script": range(101120, 101632), - "Tangut Supplement": range(101632, 101760), - "Kana Extended-B": range(110576, 110592), - "Kana Supplement": range(110592, 110848), - "Kana Extended-A": range(110848, 110896), - "Small Kana Extension": range(110896, 110960), - "Nushu": range(110960, 111360), - "Duployan": range(113664, 113824), - "Shorthand Format Controls": range(113824, 113840), - "Znamenny Musical Notation": range(118528, 118736), - "Byzantine Musical Symbols": range(118784, 119040), - "Musical Symbols": range(119040, 119296), - "Ancient Greek Musical Notation": range(119296, 119376), - "Kaktovik Numerals": range(119488, 119520), - "Mayan Numerals": range(119520, 119552), - "Tai Xuan Jing Symbols": range(119552, 119648), - "Counting Rod Numerals": range(119648, 119680), - "Mathematical Alphanumeric Symbols": range(119808, 120832), - "Sutton SignWriting": range(120832, 121520), - "Latin Extended-G": range(122624, 122880), - "Glagolitic Supplement": range(122880, 122928), - "Cyrillic Extended-D": range(122928, 123024), - "Nyiakeng Puachue Hmong": range(123136, 123216), - "Toto": range(123536, 123584), - "Wancho": range(123584, 123648), - "Nag Mundari": range(124112, 124160), - "Ethiopic Extended-B": range(124896, 124928), - "Mende Kikakui": range(124928, 125152), - "Adlam": range(125184, 125280), - "Indic Siyaq Numbers": range(126064, 126144), - "Ottoman Siyaq Numbers": range(126208, 126288), - "Arabic Mathematical Alphabetic Symbols": range(126464, 126720), - "Mahjong Tiles": range(126976, 127024), - "Domino Tiles": range(127024, 127136), - "Playing Cards": range(127136, 127232), - "Enclosed Alphanumeric Supplement": range(127232, 127488), - "Enclosed Ideographic Supplement": range(127488, 127744), - "Miscellaneous Symbols and Pictographs": range(127744, 128512), - "Emoticons range(Emoji)": range(128512, 128592), - "Ornamental Dingbats": range(128592, 128640), - "Transport and Map Symbols": range(128640, 128768), - "Alchemical Symbols": range(128768, 128896), - "Geometric Shapes Extended": range(128896, 129024), - "Supplemental Arrows-C": range(129024, 129280), - "Supplemental Symbols and Pictographs": range(129280, 129536), - "Chess Symbols": range(129536, 129648), - "Symbols and Pictographs Extended-A": range(129648, 129792), - "Symbols for Legacy Computing": range(129792, 130048), - "CJK Unified Ideographs Extension B": range(131072, 173792), - "CJK Unified Ideographs Extension C": range(173824, 177984), - "CJK Unified Ideographs Extension D": range(177984, 178208), - "CJK Unified Ideographs Extension E": range(178208, 183984), - "CJK Unified Ideographs Extension F": range(183984, 191472), - "CJK Compatibility Ideographs Supplement": range(194560, 195104), - "CJK Unified Ideographs Extension G": range(196608, 201552), - "CJK Unified Ideographs Extension H": range(201552, 205744), - "Tags": range(917504, 917632), - "Variation Selectors Supplement": range(917760, 918000), - "Supplementary Private Use Area-A": range(983040, 1048576), - "Supplementary Private Use Area-B": range(1048576, 1114112), -} - - -UNICODE_SECONDARY_RANGE_KEYWORD: list[str] = [ - "Supplement", - "Extended", - "Extensions", - "Modifier", - "Marks", - "Punctuation", - "Symbols", - "Forms", - "Operators", - "Miscellaneous", - "Drawing", - "Block", - "Shapes", - "Supplemental", - "Tags", -] - -RE_POSSIBLE_ENCODING_INDICATION = re_compile( - r"(?:(?:encoding)|(?:charset)|(?:coding))(?:[\:= ]{1,10})(?:[\"\']?)([a-zA-Z0-9\-_]+)(?:[\"\']?)", - IGNORECASE, -) - -IANA_NO_ALIASES = [ - "cp720", - "cp737", - "cp856", - "cp874", - "cp875", - "cp1006", - "koi8_r", - "koi8_t", - "koi8_u", -] - -IANA_SUPPORTED: list[str] = sorted( - filter( - lambda x: x.endswith("_codec") is False - and x not in {"rot_13", "tactis", "mbcs"}, - list(set(aliases.values())) + IANA_NO_ALIASES, - ) -) - -IANA_SUPPORTED_COUNT: int = len(IANA_SUPPORTED) - -# pre-computed code page that are similar using the function cp_similarity. -IANA_SUPPORTED_SIMILAR: dict[str, list[str]] = { - "cp037": ["cp1026", "cp1140", "cp273", "cp500"], - "cp1026": ["cp037", "cp1140", "cp273", "cp500"], - "cp1125": ["cp866"], - "cp1140": ["cp037", "cp1026", "cp273", "cp500"], - "cp1250": ["iso8859_2"], - "cp1251": ["kz1048", "ptcp154"], - "cp1252": ["iso8859_15", "iso8859_9", "latin_1"], - "cp1253": ["iso8859_7"], - "cp1254": ["iso8859_15", "iso8859_9", "latin_1"], - "cp1257": ["iso8859_13"], - "cp273": ["cp037", "cp1026", "cp1140", "cp500"], - "cp437": ["cp850", "cp858", "cp860", "cp861", "cp862", "cp863", "cp865"], - "cp500": ["cp037", "cp1026", "cp1140", "cp273"], - "cp850": ["cp437", "cp857", "cp858", "cp865"], - "cp857": ["cp850", "cp858", "cp865"], - "cp858": ["cp437", "cp850", "cp857", "cp865"], - "cp860": ["cp437", "cp861", "cp862", "cp863", "cp865"], - "cp861": ["cp437", "cp860", "cp862", "cp863", "cp865"], - "cp862": ["cp437", "cp860", "cp861", "cp863", "cp865"], - "cp863": ["cp437", "cp860", "cp861", "cp862", "cp865"], - "cp865": ["cp437", "cp850", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863"], - "cp866": ["cp1125"], - "iso8859_10": ["iso8859_14", "iso8859_15", "iso8859_4", "iso8859_9", "latin_1"], - "iso8859_11": ["tis_620"], - "iso8859_13": ["cp1257"], - "iso8859_14": [ - "iso8859_10", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_15": [ - "cp1252", - "cp1254", - "iso8859_10", - "iso8859_14", - "iso8859_16", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_16": [ - "iso8859_14", - "iso8859_15", - "iso8859_2", - "iso8859_3", - "iso8859_9", - "latin_1", - ], - "iso8859_2": ["cp1250", "iso8859_16", "iso8859_4"], - "iso8859_3": ["iso8859_14", "iso8859_15", "iso8859_16", "iso8859_9", "latin_1"], - "iso8859_4": ["iso8859_10", "iso8859_2", "iso8859_9", "latin_1"], - "iso8859_7": ["cp1253"], - "iso8859_9": [ - "cp1252", - "cp1254", - "cp1258", - "iso8859_10", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_4", - "latin_1", - ], - "kz1048": ["cp1251", "ptcp154"], - "latin_1": [ - "cp1252", - "cp1254", - "cp1258", - "iso8859_10", - "iso8859_14", - "iso8859_15", - "iso8859_16", - "iso8859_3", - "iso8859_4", - "iso8859_9", - ], - "mac_iceland": ["mac_roman", "mac_turkish"], - "mac_roman": ["mac_iceland", "mac_turkish"], - "mac_turkish": ["mac_iceland", "mac_roman"], - "ptcp154": ["cp1251", "kz1048"], - "tis_620": ["iso8859_11"], -} - - -CHARDET_CORRESPONDENCE: dict[str, str] = { - "iso2022_kr": "ISO-2022-KR", - "iso2022_jp": "ISO-2022-JP", - "euc_kr": "EUC-KR", - "tis_620": "TIS-620", - "utf_32": "UTF-32", - "euc_jp": "EUC-JP", - "koi8_r": "KOI8-R", - "iso8859_1": "ISO-8859-1", - "iso8859_2": "ISO-8859-2", - "iso8859_5": "ISO-8859-5", - "iso8859_6": "ISO-8859-6", - "iso8859_7": "ISO-8859-7", - "iso8859_8": "ISO-8859-8", - "utf_16": "UTF-16", - "cp855": "IBM855", - "mac_cyrillic": "MacCyrillic", - "gb2312": "GB2312", - "gb18030": "GB18030", - "cp932": "CP932", - "cp866": "IBM866", - "utf_8": "utf-8", - "utf_8_sig": "UTF-8-SIG", - "shift_jis": "SHIFT_JIS", - "big5": "Big5", - "cp1250": "windows-1250", - "cp1251": "windows-1251", - "cp1252": "Windows-1252", - "cp1253": "windows-1253", - "cp1255": "windows-1255", - "cp1256": "windows-1256", - "cp1254": "Windows-1254", - "cp949": "CP949", -} - - -COMMON_SAFE_ASCII_CHARACTERS: set[str] = { - "<", - ">", - "=", - ":", - "/", - "&", - ";", - "{", - "}", - "[", - "]", - ",", - "|", - '"', - "-", - "(", - ")", -} - -# Sample character sets — replace with full lists if needed -COMMON_CHINESE_CHARACTERS = "的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞" - -COMMON_JAPANESE_CHARACTERS = "日一国年大十二本中長出三時行見月分後前生五間上東四今金九入学高円子外八六下来気小七山話女北午百書先名川千水半男西電校語土木聞食車何南万毎白天母火右読友左休父雨" - -COMMON_KOREAN_CHARACTERS = "一二三四五六七八九十百千萬上下左右中人女子大小山川日月火水木金土父母天地國名年時文校學生" - -# Combine all into a set -COMMON_CJK_CHARACTERS = set( - "".join( - [ - COMMON_CHINESE_CHARACTERS, - COMMON_JAPANESE_CHARACTERS, - COMMON_KOREAN_CHARACTERS, - ] - ) -) - -KO_NAMES: set[str] = {"johab", "cp949", "euc_kr"} -ZH_NAMES: set[str] = {"big5", "cp950", "big5hkscs", "hz"} - -# Logging LEVEL below DEBUG -TRACE: int = 5 - - -# Language label that contain the em dash "—" -# character are to be considered alternative seq to origin -FREQUENCIES: dict[str, list[str]] = { - "English": [ - "e", - "a", - "t", - "i", - "o", - "n", - "s", - "r", - "h", - "l", - "d", - "c", - "u", - "m", - "f", - "p", - "g", - "w", - "y", - "b", - "v", - "k", - "x", - "j", - "z", - "q", - ], - "English—": [ - "e", - "a", - "t", - "i", - "o", - "n", - "s", - "r", - "h", - "l", - "d", - "c", - "m", - "u", - "f", - "p", - "g", - "w", - "b", - "y", - "v", - "k", - "j", - "x", - "z", - "q", - ], - "German": [ - "e", - "n", - "i", - "r", - "s", - "t", - "a", - "d", - "h", - "u", - "l", - "g", - "o", - "c", - "m", - "b", - "f", - "k", - "w", - "z", - "p", - "v", - "ü", - "ä", - "ö", - "j", - ], - "French": [ - "e", - "a", - "s", - "n", - "i", - "t", - "r", - "l", - "u", - "o", - "d", - "c", - "p", - "m", - "é", - "v", - "g", - "f", - "b", - "h", - "q", - "à", - "x", - "è", - "y", - "j", - ], - "Dutch": [ - "e", - "n", - "a", - "i", - "r", - "t", - "o", - "d", - "s", - "l", - "g", - "h", - "v", - "m", - "u", - "k", - "c", - "p", - "b", - "w", - "j", - "z", - "f", - "y", - "x", - "ë", - ], - "Italian": [ - "e", - "i", - "a", - "o", - "n", - "l", - "t", - "r", - "s", - "c", - "d", - "u", - "p", - "m", - "g", - "v", - "f", - "b", - "z", - "h", - "q", - "è", - "à", - "k", - "y", - "ò", - ], - "Polish": [ - "a", - "i", - "o", - "e", - "n", - "r", - "z", - "w", - "s", - "c", - "t", - "k", - "y", - "d", - "p", - "m", - "u", - "l", - "j", - "ł", - "g", - "b", - "h", - "ą", - "ę", - "ó", - ], - "Spanish": [ - "e", - "a", - "o", - "n", - "s", - "r", - "i", - "l", - "d", - "t", - "c", - "u", - "m", - "p", - "b", - "g", - "v", - "f", - "y", - "ó", - "h", - "q", - "í", - "j", - "z", - "á", - ], - "Russian": [ - "о", - "а", - "е", - "и", - "н", - "с", - "т", - "р", - "в", - "л", - "к", - "м", - "д", - "п", - "у", - "г", - "я", - "ы", - "з", - "б", - "й", - "ь", - "ч", - "х", - "ж", - "ц", - ], - # Jap-Kanji - "Japanese": [ - "人", - "一", - "大", - "亅", - "丁", - "丨", - "竹", - "笑", - "口", - "日", - "今", - "二", - "彳", - "行", - "十", - "土", - "丶", - "寸", - "寺", - "時", - "乙", - "丿", - "乂", - "气", - "気", - "冂", - "巾", - "亠", - "市", - "目", - "儿", - "見", - "八", - "小", - "凵", - "県", - "月", - "彐", - "門", - "間", - "木", - "東", - "山", - "出", - "本", - "中", - "刀", - "分", - "耳", - "又", - "取", - "最", - "言", - "田", - "心", - "思", - "刂", - "前", - "京", - "尹", - "事", - "生", - "厶", - "云", - "会", - "未", - "来", - "白", - "冫", - "楽", - "灬", - "馬", - "尸", - "尺", - "駅", - "明", - "耂", - "者", - "了", - "阝", - "都", - "高", - "卜", - "占", - "厂", - "广", - "店", - "子", - "申", - "奄", - "亻", - "俺", - "上", - "方", - "冖", - "学", - "衣", - "艮", - "食", - "自", - ], - # Jap-Katakana - "Japanese—": [ - "ー", - "ン", - "ス", - "・", - "ル", - "ト", - "リ", - "イ", - "ア", - "ラ", - "ッ", - "ク", - "ド", - "シ", - "レ", - "ジ", - "タ", - "フ", - "ロ", - "カ", - "テ", - "マ", - "ィ", - "グ", - "バ", - "ム", - "プ", - "オ", - "コ", - "デ", - "ニ", - "ウ", - "メ", - "サ", - "ビ", - "ナ", - "ブ", - "ャ", - "エ", - "ュ", - "チ", - "キ", - "ズ", - "ダ", - "パ", - "ミ", - "ェ", - "ョ", - "ハ", - "セ", - "ベ", - "ガ", - "モ", - "ツ", - "ネ", - "ボ", - "ソ", - "ノ", - "ァ", - "ヴ", - "ワ", - "ポ", - "ペ", - "ピ", - "ケ", - "ゴ", - "ギ", - "ザ", - "ホ", - "ゲ", - "ォ", - "ヤ", - "ヒ", - "ユ", - "ヨ", - "ヘ", - "ゼ", - "ヌ", - "ゥ", - "ゾ", - "ヶ", - "ヂ", - "ヲ", - "ヅ", - "ヵ", - "ヱ", - "ヰ", - "ヮ", - "ヽ", - "゠", - "ヾ", - "ヷ", - "ヿ", - "ヸ", - "ヹ", - "ヺ", - ], - # Jap-Hiragana - "Japanese——": [ - "の", - "に", - "る", - "た", - "と", - "は", - "し", - "い", - "を", - "で", - "て", - "が", - "な", - "れ", - "か", - "ら", - "さ", - "っ", - "り", - "す", - "あ", - "も", - "こ", - "ま", - "う", - "く", - "よ", - "き", - "ん", - "め", - "お", - "け", - "そ", - "つ", - "だ", - "や", - "え", - "ど", - "わ", - "ち", - "み", - "せ", - "じ", - "ば", - "へ", - "び", - "ず", - "ろ", - "ほ", - "げ", - "む", - "べ", - "ひ", - "ょ", - "ゆ", - "ぶ", - "ご", - "ゃ", - "ね", - "ふ", - "ぐ", - "ぎ", - "ぼ", - "ゅ", - "づ", - "ざ", - "ぞ", - "ぬ", - "ぜ", - "ぱ", - "ぽ", - "ぷ", - "ぴ", - "ぃ", - "ぁ", - "ぇ", - "ぺ", - "ゞ", - "ぢ", - "ぉ", - "ぅ", - "ゐ", - "ゝ", - "ゑ", - "゛", - "゜", - "ゎ", - "ゔ", - "゚", - "ゟ", - "゙", - "ゕ", - "ゖ", - ], - "Portuguese": [ - "a", - "e", - "o", - "s", - "i", - "r", - "d", - "n", - "t", - "m", - "u", - "c", - "l", - "p", - "g", - "v", - "b", - "f", - "h", - "ã", - "q", - "é", - "ç", - "á", - "z", - "í", - ], - "Swedish": [ - "e", - "a", - "n", - "r", - "t", - "s", - "i", - "l", - "d", - "o", - "m", - "k", - "g", - "v", - "h", - "f", - "u", - "p", - "ä", - "c", - "b", - "ö", - "å", - "y", - "j", - "x", - ], - "Chinese": [ - "的", - "一", - "是", - "不", - "了", - "在", - "人", - "有", - "我", - "他", - "这", - "个", - "们", - "中", - "来", - "上", - "大", - "为", - "和", - "国", - "地", - "到", - "以", - "说", - "时", - "要", - "就", - "出", - "会", - "可", - "也", - "你", - "对", - "生", - "能", - "而", - "子", - "那", - "得", - "于", - "着", - "下", - "自", - "之", - "年", - "过", - "发", - "后", - "作", - "里", - "用", - "道", - "行", - "所", - "然", - "家", - "种", - "事", - "成", - "方", - "多", - "经", - "么", - "去", - "法", - "学", - "如", - "都", - "同", - "现", - "当", - "没", - "动", - "面", - "起", - "看", - "定", - "天", - "分", - "还", - "进", - "好", - "小", - "部", - "其", - "些", - "主", - "样", - "理", - "心", - "她", - "本", - "前", - "开", - "但", - "因", - "只", - "从", - "想", - "实", - ], - "Ukrainian": [ - "о", - "а", - "н", - "і", - "и", - "р", - "в", - "т", - "е", - "с", - "к", - "л", - "у", - "д", - "м", - "п", - "з", - "я", - "ь", - "б", - "г", - "й", - "ч", - "х", - "ц", - "ї", - ], - "Norwegian": [ - "e", - "r", - "n", - "t", - "a", - "s", - "i", - "o", - "l", - "d", - "g", - "k", - "m", - "v", - "f", - "p", - "u", - "b", - "h", - "å", - "y", - "j", - "ø", - "c", - "æ", - "w", - ], - "Finnish": [ - "a", - "i", - "n", - "t", - "e", - "s", - "l", - "o", - "u", - "k", - "ä", - "m", - "r", - "v", - "j", - "h", - "p", - "y", - "d", - "ö", - "g", - "c", - "b", - "f", - "w", - "z", - ], - "Vietnamese": [ - "n", - "h", - "t", - "i", - "c", - "g", - "a", - "o", - "u", - "m", - "l", - "r", - "à", - "đ", - "s", - "e", - "v", - "p", - "b", - "y", - "ư", - "d", - "á", - "k", - "ộ", - "ế", - ], - "Czech": [ - "o", - "e", - "a", - "n", - "t", - "s", - "i", - "l", - "v", - "r", - "k", - "d", - "u", - "m", - "p", - "í", - "c", - "h", - "z", - "á", - "y", - "j", - "b", - "ě", - "é", - "ř", - ], - "Hungarian": [ - "e", - "a", - "t", - "l", - "s", - "n", - "k", - "r", - "i", - "o", - "z", - "á", - "é", - "g", - "m", - "b", - "y", - "v", - "d", - "h", - "u", - "p", - "j", - "ö", - "f", - "c", - ], - "Korean": [ - "이", - "다", - "에", - "의", - "는", - "로", - "하", - "을", - "가", - "고", - "지", - "서", - "한", - "은", - "기", - "으", - "년", - "대", - "사", - "시", - "를", - "리", - "도", - "인", - "스", - "일", - ], - "Indonesian": [ - "a", - "n", - "e", - "i", - "r", - "t", - "u", - "s", - "d", - "k", - "m", - "l", - "g", - "p", - "b", - "o", - "h", - "y", - "j", - "c", - "w", - "f", - "v", - "z", - "x", - "q", - ], - "Turkish": [ - "a", - "e", - "i", - "n", - "r", - "l", - "ı", - "k", - "d", - "t", - "s", - "m", - "y", - "u", - "o", - "b", - "ü", - "ş", - "v", - "g", - "z", - "h", - "c", - "p", - "ç", - "ğ", - ], - "Romanian": [ - "e", - "i", - "a", - "r", - "n", - "t", - "u", - "l", - "o", - "c", - "s", - "d", - "p", - "m", - "ă", - "f", - "v", - "î", - "g", - "b", - "ș", - "ț", - "z", - "h", - "â", - "j", - ], - "Farsi": [ - "ا", - "ی", - "ر", - "د", - "ن", - "ه", - "و", - "م", - "ت", - "ب", - "س", - "ل", - "ک", - "ش", - "ز", - "ف", - "گ", - "ع", - "خ", - "ق", - "ج", - "آ", - "پ", - "ح", - "ط", - "ص", - ], - "Arabic": [ - "ا", - "ل", - "ي", - "م", - "و", - "ن", - "ر", - "ت", - "ب", - "ة", - "ع", - "د", - "س", - "ف", - "ه", - "ك", - "ق", - "أ", - "ح", - "ج", - "ش", - "ط", - "ص", - "ى", - "خ", - "إ", - ], - "Danish": [ - "e", - "r", - "n", - "t", - "a", - "i", - "s", - "d", - "l", - "o", - "g", - "m", - "k", - "f", - "v", - "u", - "b", - "h", - "p", - "å", - "y", - "ø", - "æ", - "c", - "j", - "w", - ], - "Serbian": [ - "а", - "и", - "о", - "е", - "н", - "р", - "с", - "у", - "т", - "к", - "ј", - "в", - "д", - "м", - "п", - "л", - "г", - "з", - "б", - "a", - "i", - "e", - "o", - "n", - "ц", - "ш", - ], - "Lithuanian": [ - "i", - "a", - "s", - "o", - "r", - "e", - "t", - "n", - "u", - "k", - "m", - "l", - "p", - "v", - "d", - "j", - "g", - "ė", - "b", - "y", - "ų", - "š", - "ž", - "c", - "ą", - "į", - ], - "Slovene": [ - "e", - "a", - "i", - "o", - "n", - "r", - "s", - "l", - "t", - "j", - "v", - "k", - "d", - "p", - "m", - "u", - "z", - "b", - "g", - "h", - "č", - "c", - "š", - "ž", - "f", - "y", - ], - "Slovak": [ - "o", - "a", - "e", - "n", - "i", - "r", - "v", - "t", - "s", - "l", - "k", - "d", - "m", - "p", - "u", - "c", - "h", - "j", - "b", - "z", - "á", - "y", - "ý", - "í", - "č", - "é", - ], - "Hebrew": [ - "י", - "ו", - "ה", - "ל", - "ר", - "ב", - "ת", - "מ", - "א", - "ש", - "נ", - "ע", - "ם", - "ד", - "ק", - "ח", - "פ", - "ס", - "כ", - "ג", - "ט", - "צ", - "ן", - "ז", - "ך", - ], - "Bulgarian": [ - "а", - "и", - "о", - "е", - "н", - "т", - "р", - "с", - "в", - "л", - "к", - "д", - "п", - "м", - "з", - "г", - "я", - "ъ", - "у", - "б", - "ч", - "ц", - "й", - "ж", - "щ", - "х", - ], - "Croatian": [ - "a", - "i", - "o", - "e", - "n", - "r", - "j", - "s", - "t", - "u", - "k", - "l", - "v", - "d", - "m", - "p", - "g", - "z", - "b", - "c", - "č", - "h", - "š", - "ž", - "ć", - "f", - ], - "Hindi": [ - "क", - "र", - "स", - "न", - "त", - "म", - "ह", - "प", - "य", - "ल", - "व", - "ज", - "द", - "ग", - "ब", - "श", - "ट", - "अ", - "ए", - "थ", - "भ", - "ड", - "च", - "ध", - "ष", - "इ", - ], - "Estonian": [ - "a", - "i", - "e", - "s", - "t", - "l", - "u", - "n", - "o", - "k", - "r", - "d", - "m", - "v", - "g", - "p", - "j", - "h", - "ä", - "b", - "õ", - "ü", - "f", - "c", - "ö", - "y", - ], - "Thai": [ - "า", - "น", - "ร", - "อ", - "ก", - "เ", - "ง", - "ม", - "ย", - "ล", - "ว", - "ด", - "ท", - "ส", - "ต", - "ะ", - "ป", - "บ", - "ค", - "ห", - "แ", - "จ", - "พ", - "ช", - "ข", - "ใ", - ], - "Greek": [ - "α", - "τ", - "ο", - "ι", - "ε", - "ν", - "ρ", - "σ", - "κ", - "η", - "π", - "ς", - "υ", - "μ", - "λ", - "ί", - "ό", - "ά", - "γ", - "έ", - "δ", - "ή", - "ω", - "χ", - "θ", - "ύ", - ], - "Tamil": [ - "க", - "த", - "ப", - "ட", - "ர", - "ம", - "ல", - "ன", - "வ", - "ற", - "ய", - "ள", - "ச", - "ந", - "இ", - "ண", - "அ", - "ஆ", - "ழ", - "ங", - "எ", - "உ", - "ஒ", - "ஸ", - ], - "Kazakh": [ - "а", - "ы", - "е", - "н", - "т", - "р", - "л", - "і", - "д", - "с", - "м", - "қ", - "к", - "о", - "б", - "и", - "у", - "ғ", - "ж", - "ң", - "з", - "ш", - "й", - "п", - "г", - "ө", - ], -} - -LANGUAGE_SUPPORTED_COUNT: int = len(FREQUENCIES) diff --git a/venv/Lib/site-packages/charset_normalizer/legacy.py b/venv/Lib/site-packages/charset_normalizer/legacy.py deleted file mode 100644 index e221bec..0000000 --- a/venv/Lib/site-packages/charset_normalizer/legacy.py +++ /dev/null @@ -1,64 +0,0 @@ -from __future__ import annotations - -from typing import TYPE_CHECKING, Any -from warnings import warn - -from .api import from_bytes -from .constant import CHARDET_CORRESPONDENCE - -# TODO: remove this check when dropping Python 3.7 support -if TYPE_CHECKING: - from typing_extensions import TypedDict - - class ResultDict(TypedDict): - encoding: str | None - language: str - confidence: float | None - - -def detect( - byte_str: bytes, should_rename_legacy: bool = False, **kwargs: Any -) -> ResultDict: - """ - chardet legacy method - Detect the encoding of the given byte string. It should be mostly backward-compatible. - Encoding name will match Chardet own writing whenever possible. (Not on encoding name unsupported by it) - This function is deprecated and should be used to migrate your project easily, consult the documentation for - further information. Not planned for removal. - - :param byte_str: The byte sequence to examine. - :param should_rename_legacy: Should we rename legacy encodings - to their more modern equivalents? - """ - if len(kwargs): - warn( - f"charset-normalizer disregard arguments '{','.join(list(kwargs.keys()))}' in legacy function detect()" - ) - - if not isinstance(byte_str, (bytearray, bytes)): - raise TypeError( # pragma: nocover - f"Expected object of type bytes or bytearray, got: {type(byte_str)}" - ) - - if isinstance(byte_str, bytearray): - byte_str = bytes(byte_str) - - r = from_bytes(byte_str).best() - - encoding = r.encoding if r is not None else None - language = r.language if r is not None and r.language != "Unknown" else "" - confidence = 1.0 - r.chaos if r is not None else None - - # Note: CharsetNormalizer does not return 'UTF-8-SIG' as the sig get stripped in the detection/normalization process - # but chardet does return 'utf-8-sig' and it is a valid codec name. - if r is not None and encoding == "utf_8" and r.bom: - encoding += "_sig" - - if should_rename_legacy is False and encoding in CHARDET_CORRESPONDENCE: - encoding = CHARDET_CORRESPONDENCE[encoding] - - return { - "encoding": encoding, - "language": language, - "confidence": confidence, - } diff --git a/venv/Lib/site-packages/charset_normalizer/md.cp310-win_amd64.pyd b/venv/Lib/site-packages/charset_normalizer/md.cp310-win_amd64.pyd deleted file mode 100644 index 2e61ae43b736690a655afbb89166f3378c58668f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10752 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 BO bool: - """ - Determine if given character should be fed in. - """ - raise NotImplementedError # pragma: nocover - - def feed(self, character: str) -> None: - """ - The main routine to be executed upon character. - Insert the logic in witch the text would be considered chaotic. - """ - raise NotImplementedError # pragma: nocover - - def reset(self) -> None: # pragma: no cover - """ - Permit to reset the plugin to the initial state. - """ - raise NotImplementedError - - @property - def ratio(self) -> float: - """ - Compute the chaos ratio based on what your feed() has seen. - Must NOT be lower than 0.; No restriction gt 0. - """ - raise NotImplementedError # pragma: nocover - - -class TooManySymbolOrPunctuationPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._punctuation_count: int = 0 - self._symbol_count: int = 0 - self._character_count: int = 0 - - self._last_printable_char: str | None = None - self._frenzy_symbol_in_word: bool = False - - def eligible(self, character: str) -> bool: - return character.isprintable() - - def feed(self, character: str) -> None: - self._character_count += 1 - - if ( - character != self._last_printable_char - and character not in COMMON_SAFE_ASCII_CHARACTERS - ): - if is_punctuation(character): - self._punctuation_count += 1 - elif ( - character.isdigit() is False - and is_symbol(character) - and is_emoticon(character) is False - ): - self._symbol_count += 2 - - self._last_printable_char = character - - def reset(self) -> None: # Abstract - self._punctuation_count = 0 - self._character_count = 0 - self._symbol_count = 0 - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - ratio_of_punctuation: float = ( - self._punctuation_count + self._symbol_count - ) / self._character_count - - return ratio_of_punctuation if ratio_of_punctuation >= 0.3 else 0.0 - - -class TooManyAccentuatedPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._character_count: int = 0 - self._accentuated_count: int = 0 - - def eligible(self, character: str) -> bool: - return character.isalpha() - - def feed(self, character: str) -> None: - self._character_count += 1 - - if is_accentuated(character): - self._accentuated_count += 1 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._accentuated_count = 0 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - ratio_of_accentuation: float = self._accentuated_count / self._character_count - return ratio_of_accentuation if ratio_of_accentuation >= 0.35 else 0.0 - - -class UnprintablePlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._unprintable_count: int = 0 - self._character_count: int = 0 - - def eligible(self, character: str) -> bool: - return True - - def feed(self, character: str) -> None: - if is_unprintable(character): - self._unprintable_count += 1 - self._character_count += 1 - - def reset(self) -> None: # Abstract - self._unprintable_count = 0 - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return (self._unprintable_count * 8) / self._character_count - - -class SuspiciousDuplicateAccentPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._successive_count: int = 0 - self._character_count: int = 0 - - self._last_latin_character: str | None = None - - def eligible(self, character: str) -> bool: - return character.isalpha() and is_latin(character) - - def feed(self, character: str) -> None: - self._character_count += 1 - if ( - self._last_latin_character is not None - and is_accentuated(character) - and is_accentuated(self._last_latin_character) - ): - if character.isupper() and self._last_latin_character.isupper(): - self._successive_count += 1 - # Worse if its the same char duplicated with different accent. - if remove_accent(character) == remove_accent(self._last_latin_character): - self._successive_count += 1 - self._last_latin_character = character - - def reset(self) -> None: # Abstract - self._successive_count = 0 - self._character_count = 0 - self._last_latin_character = None - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return (self._successive_count * 2) / self._character_count - - -class SuspiciousRange(MessDetectorPlugin): - def __init__(self) -> None: - self._suspicious_successive_range_count: int = 0 - self._character_count: int = 0 - self._last_printable_seen: str | None = None - - def eligible(self, character: str) -> bool: - return character.isprintable() - - def feed(self, character: str) -> None: - self._character_count += 1 - - if ( - character.isspace() - or is_punctuation(character) - or character in COMMON_SAFE_ASCII_CHARACTERS - ): - self._last_printable_seen = None - return - - if self._last_printable_seen is None: - self._last_printable_seen = character - return - - unicode_range_a: str | None = unicode_range(self._last_printable_seen) - unicode_range_b: str | None = unicode_range(character) - - if is_suspiciously_successive_range(unicode_range_a, unicode_range_b): - self._suspicious_successive_range_count += 1 - - self._last_printable_seen = character - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._suspicious_successive_range_count = 0 - self._last_printable_seen = None - - @property - def ratio(self) -> float: - if self._character_count <= 13: - return 0.0 - - ratio_of_suspicious_range_usage: float = ( - self._suspicious_successive_range_count * 2 - ) / self._character_count - - return ratio_of_suspicious_range_usage - - -class SuperWeirdWordPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._word_count: int = 0 - self._bad_word_count: int = 0 - self._foreign_long_count: int = 0 - - self._is_current_word_bad: bool = False - self._foreign_long_watch: bool = False - - self._character_count: int = 0 - self._bad_character_count: int = 0 - - self._buffer: str = "" - self._buffer_accent_count: int = 0 - self._buffer_glyph_count: int = 0 - - def eligible(self, character: str) -> bool: - return True - - def feed(self, character: str) -> None: - if character.isalpha(): - self._buffer += character - if is_accentuated(character): - self._buffer_accent_count += 1 - if ( - self._foreign_long_watch is False - and (is_latin(character) is False or is_accentuated(character)) - and is_cjk(character) is False - and is_hangul(character) is False - and is_katakana(character) is False - and is_hiragana(character) is False - and is_thai(character) is False - ): - self._foreign_long_watch = True - if ( - is_cjk(character) - or is_hangul(character) - or is_katakana(character) - or is_hiragana(character) - or is_thai(character) - ): - self._buffer_glyph_count += 1 - return - if not self._buffer: - return - if ( - character.isspace() or is_punctuation(character) or is_separator(character) - ) and self._buffer: - self._word_count += 1 - buffer_length: int = len(self._buffer) - - self._character_count += buffer_length - - if buffer_length >= 4: - if self._buffer_accent_count / buffer_length >= 0.5: - self._is_current_word_bad = True - # Word/Buffer ending with an upper case accentuated letter are so rare, - # that we will consider them all as suspicious. Same weight as foreign_long suspicious. - elif ( - is_accentuated(self._buffer[-1]) - and self._buffer[-1].isupper() - and all(_.isupper() for _ in self._buffer) is False - ): - self._foreign_long_count += 1 - self._is_current_word_bad = True - elif self._buffer_glyph_count == 1: - self._is_current_word_bad = True - self._foreign_long_count += 1 - if buffer_length >= 24 and self._foreign_long_watch: - camel_case_dst = [ - i - for c, i in zip(self._buffer, range(0, buffer_length)) - if c.isupper() - ] - probable_camel_cased: bool = False - - if camel_case_dst and (len(camel_case_dst) / buffer_length <= 0.3): - probable_camel_cased = True - - if not probable_camel_cased: - self._foreign_long_count += 1 - self._is_current_word_bad = True - - if self._is_current_word_bad: - self._bad_word_count += 1 - self._bad_character_count += len(self._buffer) - self._is_current_word_bad = False - - self._foreign_long_watch = False - self._buffer = "" - self._buffer_accent_count = 0 - self._buffer_glyph_count = 0 - elif ( - character not in {"<", ">", "-", "=", "~", "|", "_"} - and character.isdigit() is False - and is_symbol(character) - ): - self._is_current_word_bad = True - self._buffer += character - - def reset(self) -> None: # Abstract - self._buffer = "" - self._is_current_word_bad = False - self._foreign_long_watch = False - self._bad_word_count = 0 - self._word_count = 0 - self._character_count = 0 - self._bad_character_count = 0 - self._foreign_long_count = 0 - - @property - def ratio(self) -> float: - if self._word_count <= 10 and self._foreign_long_count == 0: - return 0.0 - - return self._bad_character_count / self._character_count - - -class CjkUncommonPlugin(MessDetectorPlugin): - """ - Detect messy CJK text that probably means nothing. - """ - - def __init__(self) -> None: - self._character_count: int = 0 - self._uncommon_count: int = 0 - - def eligible(self, character: str) -> bool: - return is_cjk(character) - - def feed(self, character: str) -> None: - self._character_count += 1 - - if is_cjk_uncommon(character): - self._uncommon_count += 1 - return - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._uncommon_count = 0 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - uncommon_form_usage: float = self._uncommon_count / self._character_count - - # we can be pretty sure it's garbage when uncommon characters are widely - # used. otherwise it could just be traditional chinese for example. - return uncommon_form_usage / 10 if uncommon_form_usage > 0.5 else 0.0 - - -class ArchaicUpperLowerPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._buf: bool = False - - self._character_count_since_last_sep: int = 0 - - self._successive_upper_lower_count: int = 0 - self._successive_upper_lower_count_final: int = 0 - - self._character_count: int = 0 - - self._last_alpha_seen: str | None = None - self._current_ascii_only: bool = True - - def eligible(self, character: str) -> bool: - return True - - def feed(self, character: str) -> None: - is_concerned = character.isalpha() and is_case_variable(character) - chunk_sep = is_concerned is False - - if chunk_sep and self._character_count_since_last_sep > 0: - if ( - self._character_count_since_last_sep <= 64 - and character.isdigit() is False - and self._current_ascii_only is False - ): - self._successive_upper_lower_count_final += ( - self._successive_upper_lower_count - ) - - self._successive_upper_lower_count = 0 - self._character_count_since_last_sep = 0 - self._last_alpha_seen = None - self._buf = False - self._character_count += 1 - self._current_ascii_only = True - - return - - if self._current_ascii_only is True and character.isascii() is False: - self._current_ascii_only = False - - if self._last_alpha_seen is not None: - if (character.isupper() and self._last_alpha_seen.islower()) or ( - character.islower() and self._last_alpha_seen.isupper() - ): - if self._buf is True: - self._successive_upper_lower_count += 2 - self._buf = False - else: - self._buf = True - else: - self._buf = False - - self._character_count += 1 - self._character_count_since_last_sep += 1 - self._last_alpha_seen = character - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._character_count_since_last_sep = 0 - self._successive_upper_lower_count = 0 - self._successive_upper_lower_count_final = 0 - self._last_alpha_seen = None - self._buf = False - self._current_ascii_only = True - - @property - def ratio(self) -> float: - if self._character_count == 0: - return 0.0 - - return self._successive_upper_lower_count_final / self._character_count - - -class ArabicIsolatedFormPlugin(MessDetectorPlugin): - def __init__(self) -> None: - self._character_count: int = 0 - self._isolated_form_count: int = 0 - - def reset(self) -> None: # Abstract - self._character_count = 0 - self._isolated_form_count = 0 - - def eligible(self, character: str) -> bool: - return is_arabic(character) - - def feed(self, character: str) -> None: - self._character_count += 1 - - if is_arabic_isolated_form(character): - self._isolated_form_count += 1 - - @property - def ratio(self) -> float: - if self._character_count < 8: - return 0.0 - - isolated_form_usage: float = self._isolated_form_count / self._character_count - - return isolated_form_usage - - -@lru_cache(maxsize=1024) -def is_suspiciously_successive_range( - unicode_range_a: str | None, unicode_range_b: str | None -) -> bool: - """ - Determine if two Unicode range seen next to each other can be considered as suspicious. - """ - if unicode_range_a is None or unicode_range_b is None: - return True - - if unicode_range_a == unicode_range_b: - return False - - if "Latin" in unicode_range_a and "Latin" in unicode_range_b: - return False - - if "Emoticons" in unicode_range_a or "Emoticons" in unicode_range_b: - return False - - # Latin characters can be accompanied with a combining diacritical mark - # eg. Vietnamese. - if ("Latin" in unicode_range_a or "Latin" in unicode_range_b) and ( - "Combining" in unicode_range_a or "Combining" in unicode_range_b - ): - return False - - keywords_range_a, keywords_range_b = ( - unicode_range_a.split(" "), - unicode_range_b.split(" "), - ) - - for el in keywords_range_a: - if el in UNICODE_SECONDARY_RANGE_KEYWORD: - continue - if el in keywords_range_b: - return False - - # Japanese Exception - range_a_jp_chars, range_b_jp_chars = ( - unicode_range_a - in ( - "Hiragana", - "Katakana", - ), - unicode_range_b in ("Hiragana", "Katakana"), - ) - if (range_a_jp_chars or range_b_jp_chars) and ( - "CJK" in unicode_range_a or "CJK" in unicode_range_b - ): - return False - if range_a_jp_chars and range_b_jp_chars: - return False - - if "Hangul" in unicode_range_a or "Hangul" in unicode_range_b: - if "CJK" in unicode_range_a or "CJK" in unicode_range_b: - return False - if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": - return False - - # Chinese/Japanese use dedicated range for punctuation and/or separators. - if ("CJK" in unicode_range_a or "CJK" in unicode_range_b) or ( - unicode_range_a in ["Katakana", "Hiragana"] - and unicode_range_b in ["Katakana", "Hiragana"] - ): - if "Punctuation" in unicode_range_a or "Punctuation" in unicode_range_b: - return False - if "Forms" in unicode_range_a or "Forms" in unicode_range_b: - return False - if unicode_range_a == "Basic Latin" or unicode_range_b == "Basic Latin": - return False - - return True - - -@lru_cache(maxsize=2048) -def mess_ratio( - decoded_sequence: str, maximum_threshold: float = 0.2, debug: bool = False -) -> float: - """ - Compute a mess ratio given a decoded bytes sequence. The maximum threshold does stop the computation earlier. - """ - - detectors: list[MessDetectorPlugin] = [ - md_class() for md_class in MessDetectorPlugin.__subclasses__() - ] - - length: int = len(decoded_sequence) + 1 - - mean_mess_ratio: float = 0.0 - - if length < 512: - intermediary_mean_mess_ratio_calc: int = 32 - elif length <= 1024: - intermediary_mean_mess_ratio_calc = 64 - else: - intermediary_mean_mess_ratio_calc = 128 - - for character, index in zip(decoded_sequence + "\n", range(length)): - for detector in detectors: - if detector.eligible(character): - detector.feed(character) - - if ( - index > 0 and index % intermediary_mean_mess_ratio_calc == 0 - ) or index == length - 1: - mean_mess_ratio = sum(dt.ratio for dt in detectors) - - if mean_mess_ratio >= maximum_threshold: - break - - if debug: - logger = getLogger("charset_normalizer") - - logger.log( - TRACE, - "Mess-detector extended-analysis start. " - f"intermediary_mean_mess_ratio_calc={intermediary_mean_mess_ratio_calc} mean_mess_ratio={mean_mess_ratio} " - f"maximum_threshold={maximum_threshold}", - ) - - if len(decoded_sequence) > 16: - logger.log(TRACE, f"Starting with: {decoded_sequence[:16]}") - logger.log(TRACE, f"Ending with: {decoded_sequence[-16::]}") - - for dt in detectors: - logger.log(TRACE, f"{dt.__class__}: {dt.ratio}") - - return round(mean_mess_ratio, 3) diff --git a/venv/Lib/site-packages/charset_normalizer/md__mypyc.cp310-win_amd64.pyd b/venv/Lib/site-packages/charset_normalizer/md__mypyc.cp310-win_amd64.pyd deleted file mode 100644 index cee5fb90e045b5b13d869a471663ba0669e1a0a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122880 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

    V8R93zHEl<)@j2>BW-H$V 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 iOs$i(lwa>`ZN#tncuneodc2 bool: - if not isinstance(other, CharsetMatch): - if isinstance(other, str): - return iana_name(other) == self.encoding - return False - return self.encoding == other.encoding and self.fingerprint == other.fingerprint - - def __lt__(self, other: object) -> bool: - """ - Implemented to make sorted available upon CharsetMatches items. - """ - if not isinstance(other, CharsetMatch): - raise ValueError - - chaos_difference: float = abs(self.chaos - other.chaos) - coherence_difference: float = abs(self.coherence - other.coherence) - - # Below 1% difference --> Use Coherence - if chaos_difference < 0.01 and coherence_difference > 0.02: - return self.coherence > other.coherence - elif chaos_difference < 0.01 and coherence_difference <= 0.02: - # When having a difficult decision, use the result that decoded as many multi-byte as possible. - # preserve RAM usage! - if len(self._payload) >= TOO_BIG_SEQUENCE: - return self.chaos < other.chaos - return self.multi_byte_usage > other.multi_byte_usage - - return self.chaos < other.chaos - - @property - def multi_byte_usage(self) -> float: - return 1.0 - (len(str(self)) / len(self.raw)) - - def __str__(self) -> str: - # Lazy Str Loading - if self._string is None: - self._string = str(self._payload, self._encoding, "strict") - return self._string - - def __repr__(self) -> str: - return f"" - - def add_submatch(self, other: CharsetMatch) -> None: - if not isinstance(other, CharsetMatch) or other == self: - raise ValueError( - "Unable to add instance <{}> as a submatch of a CharsetMatch".format( - other.__class__ - ) - ) - - other._string = None # Unload RAM usage; dirty trick. - self._leaves.append(other) - - @property - def encoding(self) -> str: - return self._encoding - - @property - def encoding_aliases(self) -> list[str]: - """ - Encoding name are known by many name, using this could help when searching for IBM855 when it's listed as CP855. - """ - also_known_as: list[str] = [] - for u, p in aliases.items(): - if self.encoding == u: - also_known_as.append(p) - elif self.encoding == p: - also_known_as.append(u) - return also_known_as - - @property - def bom(self) -> bool: - return self._has_sig_or_bom - - @property - def byte_order_mark(self) -> bool: - return self._has_sig_or_bom - - @property - def languages(self) -> list[str]: - """ - Return the complete list of possible languages found in decoded sequence. - Usually not really useful. Returned list may be empty even if 'language' property return something != 'Unknown'. - """ - return [e[0] for e in self._languages] - - @property - def language(self) -> str: - """ - Most probable language found in decoded sequence. If none were detected or inferred, the property will return - "Unknown". - """ - if not self._languages: - # Trying to infer the language based on the given encoding - # Its either English or we should not pronounce ourselves in certain cases. - if "ascii" in self.could_be_from_charset: - return "English" - - # doing it there to avoid circular import - from charset_normalizer.cd import encoding_languages, mb_encoding_languages - - languages = ( - mb_encoding_languages(self.encoding) - if is_multi_byte_encoding(self.encoding) - else encoding_languages(self.encoding) - ) - - if len(languages) == 0 or "Latin Based" in languages: - return "Unknown" - - return languages[0] - - return self._languages[0][0] - - @property - def chaos(self) -> float: - return self._mean_mess_ratio - - @property - def coherence(self) -> float: - if not self._languages: - return 0.0 - return self._languages[0][1] - - @property - def percent_chaos(self) -> float: - return round(self.chaos * 100, ndigits=3) - - @property - def percent_coherence(self) -> float: - return round(self.coherence * 100, ndigits=3) - - @property - def raw(self) -> bytes: - """ - Original untouched bytes. - """ - return self._payload - - @property - def submatch(self) -> list[CharsetMatch]: - return self._leaves - - @property - def has_submatch(self) -> bool: - return len(self._leaves) > 0 - - @property - def alphabets(self) -> list[str]: - if self._unicode_ranges is not None: - return self._unicode_ranges - # list detected ranges - detected_ranges: list[str | None] = [unicode_range(char) for char in str(self)] - # filter and sort - self._unicode_ranges = sorted(list({r for r in detected_ranges if r})) - return self._unicode_ranges - - @property - def could_be_from_charset(self) -> list[str]: - """ - The complete list of encoding that output the exact SAME str result and therefore could be the originating - encoding. - This list does include the encoding available in property 'encoding'. - """ - return [self._encoding] + [m.encoding for m in self._leaves] - - def output(self, encoding: str = "utf_8") -> bytes: - """ - Method to get re-encoded bytes payload using given target encoding. Default to UTF-8. - Any errors will be simply ignored by the encoder NOT replaced. - """ - if self._output_encoding is None or self._output_encoding != encoding: - self._output_encoding = encoding - decoded_string = str(self) - if ( - self._preemptive_declaration is not None - and self._preemptive_declaration.lower() - not in ["utf-8", "utf8", "utf_8"] - ): - patched_header = sub( - RE_POSSIBLE_ENCODING_INDICATION, - lambda m: m.string[m.span()[0] : m.span()[1]].replace( - m.groups()[0], - iana_name(self._output_encoding).replace("_", "-"), # type: ignore[arg-type] - ), - decoded_string[:8192], - count=1, - ) - - decoded_string = patched_header + decoded_string[8192:] - - self._output_payload = decoded_string.encode(encoding, "replace") - - return self._output_payload # type: ignore - - @property - def fingerprint(self) -> str: - """ - Retrieve the unique SHA256 computed using the transformed (re-encoded) payload. Not the original one. - """ - return sha256(self.output()).hexdigest() - - -class CharsetMatches: - """ - Container with every CharsetMatch items ordered by default from most probable to the less one. - Act like a list(iterable) but does not implements all related methods. - """ - - def __init__(self, results: list[CharsetMatch] | None = None): - self._results: list[CharsetMatch] = sorted(results) if results else [] - - def __iter__(self) -> Iterator[CharsetMatch]: - yield from self._results - - def __getitem__(self, item: int | str) -> CharsetMatch: - """ - Retrieve a single item either by its position or encoding name (alias may be used here). - Raise KeyError upon invalid index or encoding not present in results. - """ - if isinstance(item, int): - return self._results[item] - if isinstance(item, str): - item = iana_name(item, False) - for result in self._results: - if item in result.could_be_from_charset: - return result - raise KeyError - - def __len__(self) -> int: - return len(self._results) - - def __bool__(self) -> bool: - return len(self._results) > 0 - - def append(self, item: CharsetMatch) -> None: - """ - Insert a single match. Will be inserted accordingly to preserve sort. - Can be inserted as a submatch. - """ - if not isinstance(item, CharsetMatch): - raise ValueError( - "Cannot append instance '{}' to CharsetMatches".format( - str(item.__class__) - ) - ) - # We should disable the submatch factoring when the input file is too heavy (conserve RAM usage) - if len(item.raw) < TOO_BIG_SEQUENCE: - for match in self._results: - if match.fingerprint == item.fingerprint and match.chaos == item.chaos: - match.add_submatch(item) - return - self._results.append(item) - self._results = sorted(self._results) - - def best(self) -> CharsetMatch | None: - """ - Simply return the first match. Strict equivalent to matches[0]. - """ - if not self._results: - return None - return self._results[0] - - def first(self) -> CharsetMatch | None: - """ - Redundant method, call the method best(). Kept for BC reasons. - """ - return self.best() - - -CoherenceMatch = Tuple[str, float] -CoherenceMatches = List[CoherenceMatch] - - -class CliDetectionResult: - def __init__( - self, - path: str, - encoding: str | None, - encoding_aliases: list[str], - alternative_encodings: list[str], - language: str, - alphabets: list[str], - has_sig_or_bom: bool, - chaos: float, - coherence: float, - unicode_path: str | None, - is_preferred: bool, - ): - self.path: str = path - self.unicode_path: str | None = unicode_path - self.encoding: str | None = encoding - self.encoding_aliases: list[str] = encoding_aliases - self.alternative_encodings: list[str] = alternative_encodings - self.language: str = language - self.alphabets: list[str] = alphabets - self.has_sig_or_bom: bool = has_sig_or_bom - self.chaos: float = chaos - self.coherence: float = coherence - self.is_preferred: bool = is_preferred - - @property - def __dict__(self) -> dict[str, Any]: # type: ignore - return { - "path": self.path, - "encoding": self.encoding, - "encoding_aliases": self.encoding_aliases, - "alternative_encodings": self.alternative_encodings, - "language": self.language, - "alphabets": self.alphabets, - "has_sig_or_bom": self.has_sig_or_bom, - "chaos": self.chaos, - "coherence": self.coherence, - "unicode_path": self.unicode_path, - "is_preferred": self.is_preferred, - } - - def to_json(self) -> str: - return dumps(self.__dict__, ensure_ascii=True, indent=4) diff --git a/venv/Lib/site-packages/charset_normalizer/py.typed b/venv/Lib/site-packages/charset_normalizer/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/charset_normalizer/utils.py b/venv/Lib/site-packages/charset_normalizer/utils.py deleted file mode 100644 index 6bf0384..0000000 --- a/venv/Lib/site-packages/charset_normalizer/utils.py +++ /dev/null @@ -1,414 +0,0 @@ -from __future__ import annotations - -import importlib -import logging -import unicodedata -from codecs import IncrementalDecoder -from encodings.aliases import aliases -from functools import lru_cache -from re import findall -from typing import Generator - -from _multibytecodec import ( # type: ignore[import-not-found,import] - MultibyteIncrementalDecoder, -) - -from .constant import ( - ENCODING_MARKS, - IANA_SUPPORTED_SIMILAR, - RE_POSSIBLE_ENCODING_INDICATION, - UNICODE_RANGES_COMBINED, - UNICODE_SECONDARY_RANGE_KEYWORD, - UTF8_MAXIMAL_ALLOCATION, - COMMON_CJK_CHARACTERS, -) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_accentuated(character: str) -> bool: - try: - description: str = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - return ( - "WITH GRAVE" in description - or "WITH ACUTE" in description - or "WITH CEDILLA" in description - or "WITH DIAERESIS" in description - or "WITH CIRCUMFLEX" in description - or "WITH TILDE" in description - or "WITH MACRON" in description - or "WITH RING ABOVE" in description - ) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def remove_accent(character: str) -> str: - decomposed: str = unicodedata.decomposition(character) - if not decomposed: - return character - - codes: list[str] = decomposed.split(" ") - - return chr(int(codes[0], 16)) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def unicode_range(character: str) -> str | None: - """ - Retrieve the Unicode range official name from a single character. - """ - character_ord: int = ord(character) - - for range_name, ord_range in UNICODE_RANGES_COMBINED.items(): - if character_ord in ord_range: - return range_name - - return None - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_latin(character: str) -> bool: - try: - description: str = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - return "LATIN" in description - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_punctuation(character: str) -> bool: - character_category: str = unicodedata.category(character) - - if "P" in character_category: - return True - - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Punctuation" in character_range - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_symbol(character: str) -> bool: - character_category: str = unicodedata.category(character) - - if "S" in character_category or "N" in character_category: - return True - - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Forms" in character_range and character_category != "Lo" - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_emoticon(character: str) -> bool: - character_range: str | None = unicode_range(character) - - if character_range is None: - return False - - return "Emoticons" in character_range or "Pictographs" in character_range - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_separator(character: str) -> bool: - if character.isspace() or character in {"|", "+", "<", ">"}: - return True - - character_category: str = unicodedata.category(character) - - return "Z" in character_category or character_category in {"Po", "Pd", "Pc"} - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_case_variable(character: str) -> bool: - return character.islower() != character.isupper() - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_cjk(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "CJK" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_hiragana(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "HIRAGANA" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_katakana(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "KATAKANA" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_hangul(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "HANGUL" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_thai(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "THAI" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_arabic(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "ARABIC" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_arabic_isolated_form(character: str) -> bool: - try: - character_name = unicodedata.name(character) - except ValueError: # Defensive: unicode database outdated? - return False - - return "ARABIC" in character_name and "ISOLATED FORM" in character_name - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_cjk_uncommon(character: str) -> bool: - return character not in COMMON_CJK_CHARACTERS - - -@lru_cache(maxsize=len(UNICODE_RANGES_COMBINED)) -def is_unicode_range_secondary(range_name: str) -> bool: - return any(keyword in range_name for keyword in UNICODE_SECONDARY_RANGE_KEYWORD) - - -@lru_cache(maxsize=UTF8_MAXIMAL_ALLOCATION) -def is_unprintable(character: str) -> bool: - return ( - character.isspace() is False # includes \n \t \r \v - and character.isprintable() is False - and character != "\x1a" # Why? Its the ASCII substitute character. - and character != "\ufeff" # bug discovered in Python, - # Zero Width No-Break Space located in Arabic Presentation Forms-B, Unicode 1.1 not acknowledged as space. - ) - - -def any_specified_encoding(sequence: bytes, search_zone: int = 8192) -> str | None: - """ - Extract using ASCII-only decoder any specified encoding in the first n-bytes. - """ - if not isinstance(sequence, bytes): - raise TypeError - - seq_len: int = len(sequence) - - results: list[str] = findall( - RE_POSSIBLE_ENCODING_INDICATION, - sequence[: min(seq_len, search_zone)].decode("ascii", errors="ignore"), - ) - - if len(results) == 0: - return None - - for specified_encoding in results: - specified_encoding = specified_encoding.lower().replace("-", "_") - - encoding_alias: str - encoding_iana: str - - for encoding_alias, encoding_iana in aliases.items(): - if encoding_alias == specified_encoding: - return encoding_iana - if encoding_iana == specified_encoding: - return encoding_iana - - return None - - -@lru_cache(maxsize=128) -def is_multi_byte_encoding(name: str) -> bool: - """ - Verify is a specific encoding is a multi byte one based on it IANA name - """ - return name in { - "utf_8", - "utf_8_sig", - "utf_16", - "utf_16_be", - "utf_16_le", - "utf_32", - "utf_32_le", - "utf_32_be", - "utf_7", - } or issubclass( - importlib.import_module(f"encodings.{name}").IncrementalDecoder, - MultibyteIncrementalDecoder, - ) - - -def identify_sig_or_bom(sequence: bytes) -> tuple[str | None, bytes]: - """ - Identify and extract SIG/BOM in given sequence. - """ - - for iana_encoding in ENCODING_MARKS: - marks: bytes | list[bytes] = ENCODING_MARKS[iana_encoding] - - if isinstance(marks, bytes): - marks = [marks] - - for mark in marks: - if sequence.startswith(mark): - return iana_encoding, mark - - return None, b"" - - -def should_strip_sig_or_bom(iana_encoding: str) -> bool: - return iana_encoding not in {"utf_16", "utf_32"} - - -def iana_name(cp_name: str, strict: bool = True) -> str: - """Returns the Python normalized encoding name (Not the IANA official name).""" - cp_name = cp_name.lower().replace("-", "_") - - encoding_alias: str - encoding_iana: str - - for encoding_alias, encoding_iana in aliases.items(): - if cp_name in [encoding_alias, encoding_iana]: - return encoding_iana - - if strict: - raise ValueError(f"Unable to retrieve IANA for '{cp_name}'") - - return cp_name - - -def cp_similarity(iana_name_a: str, iana_name_b: str) -> float: - if is_multi_byte_encoding(iana_name_a) or is_multi_byte_encoding(iana_name_b): - return 0.0 - - decoder_a = importlib.import_module(f"encodings.{iana_name_a}").IncrementalDecoder - decoder_b = importlib.import_module(f"encodings.{iana_name_b}").IncrementalDecoder - - id_a: IncrementalDecoder = decoder_a(errors="ignore") - id_b: IncrementalDecoder = decoder_b(errors="ignore") - - character_match_count: int = 0 - - for i in range(255): - to_be_decoded: bytes = bytes([i]) - if id_a.decode(to_be_decoded) == id_b.decode(to_be_decoded): - character_match_count += 1 - - return character_match_count / 254 - - -def is_cp_similar(iana_name_a: str, iana_name_b: str) -> bool: - """ - Determine if two code page are at least 80% similar. IANA_SUPPORTED_SIMILAR dict was generated using - the function cp_similarity. - """ - return ( - iana_name_a in IANA_SUPPORTED_SIMILAR - and iana_name_b in IANA_SUPPORTED_SIMILAR[iana_name_a] - ) - - -def set_logging_handler( - name: str = "charset_normalizer", - level: int = logging.INFO, - format_string: str = "%(asctime)s | %(levelname)s | %(message)s", -) -> None: - logger = logging.getLogger(name) - logger.setLevel(level) - - handler = logging.StreamHandler() - handler.setFormatter(logging.Formatter(format_string)) - logger.addHandler(handler) - - -def cut_sequence_chunks( - sequences: bytes, - encoding_iana: str, - offsets: range, - chunk_size: int, - bom_or_sig_available: bool, - strip_sig_or_bom: bool, - sig_payload: bytes, - is_multi_byte_decoder: bool, - decoded_payload: str | None = None, -) -> Generator[str, None, None]: - if decoded_payload and is_multi_byte_decoder is False: - for i in offsets: - chunk = decoded_payload[i : i + chunk_size] - if not chunk: - break - yield chunk - else: - for i in offsets: - chunk_end = i + chunk_size - if chunk_end > len(sequences) + 8: - continue - - cut_sequence = sequences[i : i + chunk_size] - - if bom_or_sig_available and strip_sig_or_bom is False: - cut_sequence = sig_payload + cut_sequence - - chunk = cut_sequence.decode( - encoding_iana, - errors="ignore" if is_multi_byte_decoder else "strict", - ) - - # multi-byte bad cutting detector and adjustment - # not the cleanest way to perform that fix but clever enough for now. - if is_multi_byte_decoder and i > 0: - chunk_partial_size_chk: int = min(chunk_size, 16) - - if ( - decoded_payload - and chunk[:chunk_partial_size_chk] not in decoded_payload - ): - for j in range(i, i - 4, -1): - cut_sequence = sequences[j:chunk_end] - - if bom_or_sig_available and strip_sig_or_bom is False: - cut_sequence = sig_payload + cut_sequence - - chunk = cut_sequence.decode(encoding_iana, errors="ignore") - - if chunk[:chunk_partial_size_chk] in decoded_payload: - break - - yield chunk diff --git a/venv/Lib/site-packages/charset_normalizer/version.py b/venv/Lib/site-packages/charset_normalizer/version.py deleted file mode 100644 index e5687e3..0000000 --- a/venv/Lib/site-packages/charset_normalizer/version.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -Expose version -""" - -from __future__ import annotations - -__version__ = "3.4.2" -VERSION = __version__.split(".") diff --git a/venv/Lib/site-packages/click-8.1.8.dist-info/INSTALLER b/venv/Lib/site-packages/click-8.1.8.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/click-8.1.8.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt b/venv/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt deleted file mode 100644 index d12a849..0000000 --- a/venv/Lib/site-packages/click-8.1.8.dist-info/LICENSE.txt +++ /dev/null @@ -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. diff --git a/venv/Lib/site-packages/click-8.1.8.dist-info/METADATA b/venv/Lib/site-packages/click-8.1.8.dist-info/METADATA deleted file mode 100644 index 366d1a7..0000000 --- a/venv/Lib/site-packages/click-8.1.8.dist-info/METADATA +++ /dev/null @@ -1,74 +0,0 @@ -Metadata-Version: 2.3 -Name: click -Version: 8.1.8 -Summary: Composable command line interface toolkit -Maintainer-email: Pallets -Requires-Python: >=3.7 -Description-Content-Type: text/markdown -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Typing :: Typed -Requires-Dist: colorama; platform_system == 'Windows' -Requires-Dist: importlib-metadata; python_version < '3.8' -Project-URL: Changes, https://click.palletsprojects.com/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 - diff --git a/venv/Lib/site-packages/click-8.1.8.dist-info/RECORD b/venv/Lib/site-packages/click-8.1.8.dist-info/RECORD deleted file mode 100644 index 312f26b..0000000 --- a/venv/Lib/site-packages/click-8.1.8.dist-info/RECORD +++ /dev/null @@ -1,38 +0,0 @@ -click-8.1.8.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -click-8.1.8.dist-info/LICENSE.txt,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475 -click-8.1.8.dist-info/METADATA,sha256=WJtQ6uGS2ybLfvUE4vC0XIhIBr4yFGwjrMBR2fiCQ-Q,2263 -click-8.1.8.dist-info/RECORD,, -click-8.1.8.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82 -click/__init__.py,sha256=j1DJeCbga4ribkv5uyvIAzI0oFN13fW9mevDKShFelo,3188 -click/__pycache__/__init__.cpython-310.pyc,, -click/__pycache__/_compat.cpython-310.pyc,, -click/__pycache__/_termui_impl.cpython-310.pyc,, -click/__pycache__/_textwrap.cpython-310.pyc,, -click/__pycache__/_winconsole.cpython-310.pyc,, -click/__pycache__/core.cpython-310.pyc,, -click/__pycache__/decorators.cpython-310.pyc,, -click/__pycache__/exceptions.cpython-310.pyc,, -click/__pycache__/formatting.cpython-310.pyc,, -click/__pycache__/globals.cpython-310.pyc,, -click/__pycache__/parser.cpython-310.pyc,, -click/__pycache__/shell_completion.cpython-310.pyc,, -click/__pycache__/termui.cpython-310.pyc,, -click/__pycache__/testing.cpython-310.pyc,, -click/__pycache__/types.cpython-310.pyc,, -click/__pycache__/utils.cpython-310.pyc,, -click/_compat.py,sha256=IGKh_J5QdfKELitnRfTGHneejWxoCw_NX9tfMbdcg3w,18730 -click/_termui_impl.py,sha256=a5z7I9gOFeMmu7Gb6_RPyQ8GPuVP1EeblixcWSPSQPk,24783 -click/_textwrap.py,sha256=10fQ64OcBUMuK7mFvh8363_uoOxPlRItZBmKzRJDgoY,1353 -click/_winconsole.py,sha256=5ju3jQkcZD0W27WEMGqmEP4y_crUVzPCqsX_FYb7BO0,7860 -click/core.py,sha256=Q1nEVdctZwvIPOlt4vfHko0TYnHCeE40UEEul8Wpyvs,114748 -click/decorators.py,sha256=7t6F-QWowtLh6F_6l-4YV4Y4yNTcqFQEu9i37zIz68s,18925 -click/exceptions.py,sha256=V7zDT6emqJ8iNl0kF1P5kpFmLMWQ1T1L7aNNKM4YR0w,9600 -click/formatting.py,sha256=Frf0-5W33-loyY_i9qrwXR8-STnW3m5gvyxLVUdyxyk,9706 -click/globals.py,sha256=cuJ6Bbo073lgEEmhjr394PeM-QFmXM-Ci-wmfsd7H5g,1954 -click/parser.py,sha256=h4sndcpF5OHrZQN8vD8IWb5OByvW7ABbhRToxovrqS8,19067 -click/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -click/shell_completion.py,sha256=TR0dXEGcvWb9Eo3aaQEXGhnvNS3FF4H4QcuLnvAvYo4,18636 -click/termui.py,sha256=dLxiS70UOvIYBda_nEEZaPAFOVDVmRs1sEPMuLDowQo,28310 -click/testing.py,sha256=3RA8anCf7TZ8-5RAF5it2Te-aWXBAL5VLasQnMiC2ZQ,16282 -click/types.py,sha256=BD5Qqq4h-8kawBmOIzJlmq4xzThAf4wCvaOLZSBDNx0,36422 -click/utils.py,sha256=ce-IrO9ilII76LGkU354pOdHbepM8UftfNH7SfMU_28,20330 diff --git a/venv/Lib/site-packages/click-8.1.8.dist-info/WHEEL b/venv/Lib/site-packages/click-8.1.8.dist-info/WHEEL deleted file mode 100644 index e3c6fee..0000000 --- a/venv/Lib/site-packages/click-8.1.8.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.10.1 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/Lib/site-packages/click/__init__.py b/venv/Lib/site-packages/click/__init__.py deleted file mode 100644 index 2610d0e..0000000 --- a/venv/Lib/site-packages/click/__init__.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -Click is a simple Python module inspired by the stdlib optparse to make -writing command line scripts fun. Unlike other modules, it's based -around a simple API that does not come with too much magic and is -composable. -""" - -from .core import Argument as Argument -from .core import BaseCommand as BaseCommand -from .core import Command as Command -from .core import CommandCollection as CommandCollection -from .core import Context as Context -from .core import Group as Group -from .core import MultiCommand as MultiCommand -from .core import Option as Option -from .core import Parameter as Parameter -from .decorators import argument as argument -from .decorators import command as command -from .decorators import confirmation_option as confirmation_option -from .decorators import group as group -from .decorators import help_option as help_option -from .decorators import HelpOption as HelpOption -from .decorators import make_pass_decorator as make_pass_decorator -from .decorators import option as option -from .decorators import pass_context as pass_context -from .decorators import pass_obj as pass_obj -from .decorators import password_option as password_option -from .decorators import version_option as version_option -from .exceptions import Abort as Abort -from .exceptions import BadArgumentUsage as BadArgumentUsage -from .exceptions import BadOptionUsage as BadOptionUsage -from .exceptions import BadParameter as BadParameter -from .exceptions import ClickException as ClickException -from .exceptions import FileError as FileError -from .exceptions import MissingParameter as MissingParameter -from .exceptions import NoSuchOption as NoSuchOption -from .exceptions import UsageError as UsageError -from .formatting import HelpFormatter as HelpFormatter -from .formatting import wrap_text as wrap_text -from .globals import get_current_context as get_current_context -from .parser import OptionParser as OptionParser -from .termui import clear as clear -from .termui import confirm as confirm -from .termui import echo_via_pager as echo_via_pager -from .termui import edit as edit -from .termui import getchar as getchar -from .termui import launch as launch -from .termui import pause as pause -from .termui import progressbar as progressbar -from .termui import prompt as prompt -from .termui import secho as secho -from .termui import style as style -from .termui import unstyle as unstyle -from .types import BOOL as BOOL -from .types import Choice as Choice -from .types import DateTime as DateTime -from .types import File as File -from .types import FLOAT as FLOAT -from .types import FloatRange as FloatRange -from .types import INT as INT -from .types import IntRange as IntRange -from .types import ParamType as ParamType -from .types import Path as Path -from .types import STRING as STRING -from .types import Tuple as Tuple -from .types import UNPROCESSED as UNPROCESSED -from .types import UUID as UUID -from .utils import echo as echo -from .utils import format_filename as format_filename -from .utils import get_app_dir as get_app_dir -from .utils import get_binary_stream as get_binary_stream -from .utils import get_text_stream as get_text_stream -from .utils import open_file as open_file - -__version__ = "8.1.8" diff --git a/venv/Lib/site-packages/click/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 69e2888929b505d07508ae5eced025e2bcebf8d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2640 zcmc)M*;3m`6b4`e-fi|RY(WIVj@iS$7=sB30V=@FDOagvsj)R^t8N)Wo?u>OUdcCe zF<0{nb2aB2vt*uNNag42R;xF)E&SHjbOe9a{v4@>*+}FsD*XD>jD~Ph_e&u1SHr=bP|&66gmYdb{d_AG&|#D z+$?0-S#&G3vRlz@(8g{<)A%bh10qUC_nuLU%(qyBpmDJ?tKIFZ8l| z(S6Xz?nC!OKfB*~=MKOC`yF}^2H6AXAsAv0qK9FaJ%k>C5%w_pJ-la+phsbp{T{7> z#vVnF!5CX}KDgsB&K^Tgzy$k)^U`C-I%(JJ^ z3$VbRM&}^Mo1HBLX>`n9m9I&_0hj7T=M&}{V z-a#M15qlS1fC76DeGJF!edok2LXmxdK7~{EA^J0XX6MmoaK=7De}OOT0{Sa_MIXbt zb#fh^flMG7wJc7hqhPIOy6}4&(a**!^WnxgHUOAH7}>#dX9ZBG#`7B&%LX8%?_uO zRyLHd(uVYFc<1Xx@>gd#q!DVCFO=r_A$2aaM?0+IusCkbtm5Dm+tg@8Tcz=O;47o- zh+O*bCj2g#X{smlvQl$}7osyqI8dQ6Lo6oV*!j$Y?>NE?ZQpBL_d@Z5?u?z{l_3pRghFDor13Ut!h9XE+w{FVTe=3_qvIwv28vald(Tvb6TH=@ zKV$KAfNt7oJusBgEn)i72z?qV{@P8Jui+5SlTLEkFaL(E+R2Z;wBCAedk|9ncOLn& zFKM|QM~3yXZ@0>*2&`+vy2e~yYO+}K>!REEFrEA`#mmA{McWZ4Qu0JQzS&CQ8Ts{= z?1g`gkMVVlY3}>wj#gTK(Wm`tY-{RK8iD@2yzYt!b+aZVK3x56)!9a8IEvy&5i=cO z&_>~N;LWGC2(#+z54M5ZS>aYuVcE3u1a@jxxqaL*YMxoe%2;636zxGKkbXr9rOJ&K zSabtEABuXUrYd}LsA;0+y)b%od3lai@j}(NO}dyoHbQY@yW}YC5&n)9&oA>gh;-5M zjqtnS@wT^|T~KB6%zLeBoV1&#fN#GtLYiaz`sVxD#VK`kQ^U_OB6E9j_5HGNa(#Vr zjK%2f?HT`mo@)CY@2q}@<9m2==?>abBM5ZMrXA~~V%hc#`J}5*3d6<9cB-UD@K%-b z1L1K$KVzG@<=p1Q%(r?%*Dc@F^?DS~s*v=0miT6l$S6gOB2JN@NK&LI=p_&7*8{F( zhHCMJACavTZ4~Vk9Tc4uT@>9EJrunZeHit$csYzp_EYUUiUEp2iXn<&iV=$U6r&iB zZtM+xrAduy$1w14IDXl1l>9)Yc)&+Yj$;AhctG8nEhnh)M~X>`DT--|8H!noIf{9T z1&SQSB1SzH;v-dZi7J*URwz~})+p8~K2dB?Y*K7dY*Xw|>{9Gu)MK^K#+mL@#R0`3 zMV{h_qJUA)==#f-fc{5Bp3?=2e~N|e(k*^|R4J(7mu~4;sQb_lO6SKX4~A2E5Z*)S z+%A`t9g2m(Fz@kWq)H~eOcr(B_UusCbHP(Rx!ZV;;A;^7GW#7P8p$TIP5<}5Wb?nq Ch_~|q diff --git a/venv/Lib/site-packages/click/__pycache__/_compat.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/_compat.cpython-310.pyc deleted file mode 100644 index 3b7d0fead759cbb840ad8e01f51db86197b45751..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15675 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 diff --git a/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/_termui_impl.cpython-310.pyc deleted file mode 100644 index 1fb5577aaac8201d3ef06c22eb174eb2ee460335..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16567 zcmc(Gd2l4xd0$`C)6*CXj>TfJCx_gF9FmKrD4r{sDWnV#${KkY>COh&LP@SlBz_pE9J74IG5w3Qb{VQR9B^vs-(hfQmIIm z6-%I~&F}a1;202$lD{%Qzxm$%`n~V|-ZY1YeFLAz{=?CwfAN}O{3m91elo~BhbL@V zhM|n2p-g4f%%UmZR?(7gyJ*X|Q*`7zRZPjZTTJ8Iu6cE@m@(PcsrmJx;*h|pTDCr1 z92VHE6pxrjknSB-R^ywzArd-(70_EkE^HEA>>a4Cl4CxFrZVx{eX@rYr$1V z)v-5I#Rqn@xF!2X0%%)9S2x5Hmj%+^-(Sb0nC?yrSc@ zpZZAuC-><8)OP>Er#ipu&n;EMe7&jKwIE+Ea>3%HpZ;2 z=G$SQ@(b-og~OL?)o3+e4gFTFTtRuYfdRJ{Rc@$!vw=>@3}{de^Nk=-ftvR3keFr) zW}IFOqA0i(0rX}gU2QC0z5+P4vQ(`s0T`as7<|55xiPoe3htQbhSG_W3Kq)kT2x}+ zQW&Xbn?tzgUwz@)WsWSBkKdIwo2tj zSVhj`c9m*D1F)S8my>!js- z$*=G&cYf|g<~cm!23{mEz%GoUl`%6`#?CmIRK^9I#*_ScnT)!md=Q?4Cl$B{4Uo@} z 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 diff --git a/venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/_winconsole.cpython-310.pyc deleted file mode 100644 index 1a626f3a78496b11b652b491c03dfc18459a6ab3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7659 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 E7l^;JjQ{`u diff --git a/venv/Lib/site-packages/click/__pycache__/decorators.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/decorators.cpython-310.pyc deleted file mode 100644 index 6cde559ae73eca5b7d07fae9129fdd049475bfc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17708 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 diff --git a/venv/Lib/site-packages/click/__pycache__/exceptions.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/exceptions.cpython-310.pyc deleted file mode 100644 index 08e275511a0af1c8cc1a0cdfd9fafc5898532c63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10348 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

    9=&8 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 OUH{3{E$dgWy!pS8L_?|o diff --git a/venv/Lib/site-packages/click/__pycache__/globals.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/globals.cpython-310.pyc deleted file mode 100644 index 3f33943437bbf38ff7c7b686f3a5e14a7030d89f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2426 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 diff --git a/venv/Lib/site-packages/click/__pycache__/termui.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/termui.cpython-310.pyc deleted file mode 100644 index b830492d19ca71766c7a3c3368e85dd9b0fffe57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26127 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 M{dk?#frG{W1AMZr3jhEB diff --git a/venv/Lib/site-packages/click/__pycache__/testing.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/testing.cpython-310.pyc deleted file mode 100644 index bb754d3e85d4abef42b8930e2268daf3020e131d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15289 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 JFtsqZ`hSsgyGH;3 diff --git a/venv/Lib/site-packages/click/__pycache__/types.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/types.cpython-310.pyc deleted file mode 100644 index a4a04ceeaf4869e71d05f0a49b186f200cdf2ec9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33728 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 diff --git a/venv/Lib/site-packages/click/__pycache__/utils.cpython-310.pyc b/venv/Lib/site-packages/click/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index 5e8296f2ae850cbc947611e1dae90c76bde38bfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18876 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 Xo@8Ie&soMxJsjW0rJize?7{y7%kkGq diff --git a/venv/Lib/site-packages/click/_compat.py b/venv/Lib/site-packages/click/_compat.py deleted file mode 100644 index 9153d15..0000000 --- a/venv/Lib/site-packages/click/_compat.py +++ /dev/null @@ -1,623 +0,0 @@ -import codecs -import io -import os -import re -import sys -import typing as t -from weakref import WeakKeyDictionary - -CYGWIN = sys.platform.startswith("cygwin") -WIN = sys.platform.startswith("win") -auto_wrap_for_ansi: t.Optional[t.Callable[[t.TextIO], t.TextIO]] = None -_ansi_re = re.compile(r"\033\[[;?0-9]*[a-zA-Z]") - - -def _make_text_stream( - stream: t.BinaryIO, - encoding: t.Optional[str], - errors: t.Optional[str], - force_readable: bool = False, - force_writable: bool = False, -) -> t.TextIO: - if encoding is None: - encoding = get_best_encoding(stream) - if errors is None: - errors = "replace" - return _NonClosingTextIOWrapper( - stream, - encoding, - errors, - line_buffering=True, - force_readable=force_readable, - force_writable=force_writable, - ) - - -def is_ascii_encoding(encoding: str) -> bool: - """Checks if a given encoding is ascii.""" - try: - return codecs.lookup(encoding).name == "ascii" - except LookupError: - return False - - -def get_best_encoding(stream: t.IO[t.Any]) -> str: - """Returns the default stream encoding if not found.""" - rv = getattr(stream, "encoding", None) or sys.getdefaultencoding() - if is_ascii_encoding(rv): - return "utf-8" - return rv - - -class _NonClosingTextIOWrapper(io.TextIOWrapper): - def __init__( - self, - stream: t.BinaryIO, - encoding: t.Optional[str], - errors: t.Optional[str], - force_readable: bool = False, - force_writable: bool = False, - **extra: t.Any, - ) -> None: - self._stream = stream = t.cast( - t.BinaryIO, _FixupStream(stream, force_readable, force_writable) - ) - super().__init__(stream, encoding, errors, **extra) - - def __del__(self) -> None: - try: - self.detach() - except Exception: - pass - - def isatty(self) -> bool: - # https://bitbucket.org/pypy/pypy/issue/1803 - return self._stream.isatty() - - -class _FixupStream: - """The new io interface needs more from streams than streams - traditionally implement. As such, this fix-up code is necessary in - some circumstances. - - The forcing of readable and writable flags are there because some tools - put badly patched objects on sys (one such offender are certain version - of jupyter notebook). - """ - - def __init__( - self, - stream: t.BinaryIO, - force_readable: bool = False, - force_writable: bool = False, - ): - self._stream = stream - self._force_readable = force_readable - self._force_writable = force_writable - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._stream, name) - - def read1(self, size: int) -> bytes: - f = getattr(self._stream, "read1", None) - - if f is not None: - return t.cast(bytes, f(size)) - - return self._stream.read(size) - - def readable(self) -> bool: - if self._force_readable: - return True - x = getattr(self._stream, "readable", None) - if x is not None: - return t.cast(bool, x()) - try: - self._stream.read(0) - except Exception: - return False - return True - - def writable(self) -> bool: - if self._force_writable: - return True - x = getattr(self._stream, "writable", None) - if x is not None: - return t.cast(bool, x()) - try: - self._stream.write("") # type: ignore - except Exception: - try: - self._stream.write(b"") - except Exception: - return False - return True - - def seekable(self) -> bool: - x = getattr(self._stream, "seekable", None) - if x is not None: - return t.cast(bool, x()) - try: - self._stream.seek(self._stream.tell()) - except Exception: - return False - return True - - -def _is_binary_reader(stream: t.IO[t.Any], default: bool = False) -> bool: - try: - return isinstance(stream.read(0), bytes) - except Exception: - return default - # This happens in some cases where the stream was already - # closed. In this case, we assume the default. - - -def _is_binary_writer(stream: t.IO[t.Any], default: bool = False) -> bool: - try: - stream.write(b"") - except Exception: - try: - stream.write("") - return False - except Exception: - pass - return default - return True - - -def _find_binary_reader(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_reader(stream, False): - return t.cast(t.BinaryIO, stream) - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_reader(buf, True): - return t.cast(t.BinaryIO, buf) - - return None - - -def _find_binary_writer(stream: t.IO[t.Any]) -> t.Optional[t.BinaryIO]: - # We need to figure out if the given stream is already binary. - # This can happen because the official docs recommend detaching - # the streams to get binary streams. Some code might do this, so - # we need to deal with this case explicitly. - if _is_binary_writer(stream, False): - return t.cast(t.BinaryIO, stream) - - buf = getattr(stream, "buffer", None) - - # Same situation here; this time we assume that the buffer is - # actually binary in case it's closed. - if buf is not None and _is_binary_writer(buf, True): - return t.cast(t.BinaryIO, buf) - - return None - - -def _stream_is_misconfigured(stream: t.TextIO) -> bool: - """A stream is misconfigured if its encoding is ASCII.""" - # If the stream does not have an encoding set, we assume it's set - # to ASCII. This appears to happen in certain unittest - # environments. It's not quite clear what the correct behavior is - # but this at least will force Click to recover somehow. - return is_ascii_encoding(getattr(stream, "encoding", None) or "ascii") - - -def _is_compat_stream_attr(stream: t.TextIO, attr: str, value: t.Optional[str]) -> bool: - """A stream attribute is compatible if it is equal to the - desired value or the desired value is unset and the attribute - has a value. - """ - stream_value = getattr(stream, attr, None) - return stream_value == value or (value is None and stream_value is not None) - - -def _is_compatible_text_stream( - stream: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] -) -> bool: - """Check if a stream's encoding and errors attributes are - compatible with the desired values. - """ - return _is_compat_stream_attr( - stream, "encoding", encoding - ) and _is_compat_stream_attr(stream, "errors", errors) - - -def _force_correct_text_stream( - text_stream: t.IO[t.Any], - encoding: t.Optional[str], - errors: t.Optional[str], - is_binary: t.Callable[[t.IO[t.Any], bool], bool], - find_binary: t.Callable[[t.IO[t.Any]], t.Optional[t.BinaryIO]], - force_readable: bool = False, - force_writable: bool = False, -) -> t.TextIO: - if is_binary(text_stream, False): - binary_reader = t.cast(t.BinaryIO, text_stream) - else: - text_stream = t.cast(t.TextIO, text_stream) - # If the stream looks compatible, and won't default to a - # misconfigured ascii encoding, return it as-is. - if _is_compatible_text_stream(text_stream, encoding, errors) and not ( - encoding is None and _stream_is_misconfigured(text_stream) - ): - return text_stream - - # Otherwise, get the underlying binary reader. - possible_binary_reader = find_binary(text_stream) - - # If that's not possible, silently use the original reader - # and get mojibake instead of exceptions. - if possible_binary_reader is None: - return text_stream - - binary_reader = possible_binary_reader - - # Default errors to replace instead of strict in order to get - # something that works. - if errors is None: - errors = "replace" - - # Wrap the binary stream in a text stream with the correct - # encoding parameters. - return _make_text_stream( - binary_reader, - encoding, - errors, - force_readable=force_readable, - force_writable=force_writable, - ) - - -def _force_correct_text_reader( - text_reader: t.IO[t.Any], - encoding: t.Optional[str], - errors: t.Optional[str], - force_readable: bool = False, -) -> t.TextIO: - return _force_correct_text_stream( - text_reader, - encoding, - errors, - _is_binary_reader, - _find_binary_reader, - force_readable=force_readable, - ) - - -def _force_correct_text_writer( - text_writer: t.IO[t.Any], - encoding: t.Optional[str], - errors: t.Optional[str], - force_writable: bool = False, -) -> t.TextIO: - return _force_correct_text_stream( - text_writer, - encoding, - errors, - _is_binary_writer, - _find_binary_writer, - force_writable=force_writable, - ) - - -def get_binary_stdin() -> t.BinaryIO: - reader = _find_binary_reader(sys.stdin) - if reader is None: - raise RuntimeError("Was not able to determine binary stream for sys.stdin.") - return reader - - -def get_binary_stdout() -> t.BinaryIO: - writer = _find_binary_writer(sys.stdout) - if writer is None: - raise RuntimeError("Was not able to determine binary stream for sys.stdout.") - return writer - - -def get_binary_stderr() -> t.BinaryIO: - writer = _find_binary_writer(sys.stderr) - if writer is None: - raise RuntimeError("Was not able to determine binary stream for sys.stderr.") - return writer - - -def get_text_stdin( - encoding: t.Optional[str] = None, errors: t.Optional[str] = None -) -> t.TextIO: - rv = _get_windows_console_stream(sys.stdin, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_reader(sys.stdin, encoding, errors, force_readable=True) - - -def get_text_stdout( - encoding: t.Optional[str] = None, errors: t.Optional[str] = None -) -> t.TextIO: - rv = _get_windows_console_stream(sys.stdout, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer(sys.stdout, encoding, errors, force_writable=True) - - -def get_text_stderr( - encoding: t.Optional[str] = None, errors: t.Optional[str] = None -) -> t.TextIO: - rv = _get_windows_console_stream(sys.stderr, encoding, errors) - if rv is not None: - return rv - return _force_correct_text_writer(sys.stderr, encoding, errors, force_writable=True) - - -def _wrap_io_open( - file: t.Union[str, "os.PathLike[str]", int], - mode: str, - encoding: t.Optional[str], - errors: t.Optional[str], -) -> t.IO[t.Any]: - """Handles not passing ``encoding`` and ``errors`` in binary mode.""" - if "b" in mode: - return open(file, mode) - - return open(file, mode, encoding=encoding, errors=errors) - - -def open_stream( - filename: "t.Union[str, os.PathLike[str]]", - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - atomic: bool = False, -) -> t.Tuple[t.IO[t.Any], bool]: - binary = "b" in mode - filename = os.fspath(filename) - - # Standard streams first. These are simple because they ignore the - # atomic flag. Use fsdecode to handle Path("-"). - if os.fsdecode(filename) == "-": - if any(m in mode for m in ["w", "a", "x"]): - if binary: - return get_binary_stdout(), False - return get_text_stdout(encoding=encoding, errors=errors), False - if binary: - return get_binary_stdin(), False - return get_text_stdin(encoding=encoding, errors=errors), False - - # Non-atomic writes directly go out through the regular open functions. - if not atomic: - return _wrap_io_open(filename, mode, encoding, errors), True - - # Some usability stuff for atomic writes - if "a" in mode: - raise ValueError( - "Appending to an existing file is not supported, because that" - " would involve an expensive `copy`-operation to a temporary" - " file. Open the file in normal `w`-mode and copy explicitly" - " if that's what you're after." - ) - if "x" in mode: - raise ValueError("Use the `overwrite`-parameter instead.") - if "w" not in mode: - raise ValueError("Atomic writes only make sense with `w`-mode.") - - # Atomic writes are more complicated. They work by opening a file - # as a proxy in the same folder and then using the fdopen - # functionality to wrap it in a Python file. Then we wrap it in an - # atomic file that moves the file over on close. - import errno - import random - - try: - perm: t.Optional[int] = os.stat(filename).st_mode - except OSError: - perm = None - - flags = os.O_RDWR | os.O_CREAT | os.O_EXCL - - if binary: - flags |= getattr(os, "O_BINARY", 0) - - while True: - tmp_filename = os.path.join( - os.path.dirname(filename), - f".__atomic-write{random.randrange(1 << 32):08x}", - ) - try: - fd = os.open(tmp_filename, flags, 0o666 if perm is None else perm) - break - except OSError as e: - if e.errno == errno.EEXIST or ( - os.name == "nt" - and e.errno == errno.EACCES - and os.path.isdir(e.filename) - and os.access(e.filename, os.W_OK) - ): - continue - raise - - if perm is not None: - os.chmod(tmp_filename, perm) # in case perm includes bits in umask - - f = _wrap_io_open(fd, mode, encoding, errors) - af = _AtomicFile(f, tmp_filename, os.path.realpath(filename)) - return t.cast(t.IO[t.Any], af), True - - -class _AtomicFile: - def __init__(self, f: t.IO[t.Any], tmp_filename: str, real_filename: str) -> None: - self._f = f - self._tmp_filename = tmp_filename - self._real_filename = real_filename - self.closed = False - - @property - def name(self) -> str: - return self._real_filename - - def close(self, delete: bool = False) -> None: - if self.closed: - return - self._f.close() - os.replace(self._tmp_filename, self._real_filename) - self.closed = True - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._f, name) - - def __enter__(self) -> "_AtomicFile": - return self - - def __exit__(self, exc_type: t.Optional[t.Type[BaseException]], *_: t.Any) -> None: - self.close(delete=exc_type is not None) - - def __repr__(self) -> str: - return repr(self._f) - - -def strip_ansi(value: str) -> str: - return _ansi_re.sub("", value) - - -def _is_jupyter_kernel_output(stream: t.IO[t.Any]) -> bool: - while isinstance(stream, (_FixupStream, _NonClosingTextIOWrapper)): - stream = stream._stream - - return stream.__class__.__module__.startswith("ipykernel.") - - -def should_strip_ansi( - stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None -) -> bool: - if color is None: - if stream is None: - stream = sys.stdin - return not isatty(stream) and not _is_jupyter_kernel_output(stream) - return not color - - -# On Windows, wrap the output streams with colorama to support ANSI -# color codes. -# NOTE: double check is needed so mypy does not analyze this on Linux -if sys.platform.startswith("win") and WIN: - from ._winconsole import _get_windows_console_stream - - def _get_argv_encoding() -> str: - import locale - - return locale.getpreferredencoding() - - _ansi_stream_wrappers: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - - def auto_wrap_for_ansi( - stream: t.TextIO, color: t.Optional[bool] = None - ) -> t.TextIO: - """Support ANSI color and style codes on Windows by wrapping a - stream with colorama. - """ - try: - cached = _ansi_stream_wrappers.get(stream) - except Exception: - cached = None - - if cached is not None: - return cached - - import colorama - - strip = should_strip_ansi(stream, color) - ansi_wrapper = colorama.AnsiToWin32(stream, strip=strip) - rv = t.cast(t.TextIO, ansi_wrapper.stream) - _write = rv.write - - def _safe_write(s): - try: - return _write(s) - except BaseException: - ansi_wrapper.reset_all() - raise - - rv.write = _safe_write - - try: - _ansi_stream_wrappers[stream] = rv - except Exception: - pass - - return rv - -else: - - def _get_argv_encoding() -> str: - return getattr(sys.stdin, "encoding", None) or sys.getfilesystemencoding() - - def _get_windows_console_stream( - f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] - ) -> t.Optional[t.TextIO]: - return None - - -def term_len(x: str) -> int: - return len(strip_ansi(x)) - - -def isatty(stream: t.IO[t.Any]) -> bool: - try: - return stream.isatty() - except Exception: - return False - - -def _make_cached_stream_func( - src_func: t.Callable[[], t.Optional[t.TextIO]], - wrapper_func: t.Callable[[], t.TextIO], -) -> t.Callable[[], t.Optional[t.TextIO]]: - cache: t.MutableMapping[t.TextIO, t.TextIO] = WeakKeyDictionary() - - def func() -> t.Optional[t.TextIO]: - stream = src_func() - - if stream is None: - return None - - try: - rv = cache.get(stream) - except Exception: - rv = None - if rv is not None: - return rv - rv = wrapper_func() - try: - cache[stream] = rv - except Exception: - pass - return rv - - return func - - -_default_text_stdin = _make_cached_stream_func(lambda: sys.stdin, get_text_stdin) -_default_text_stdout = _make_cached_stream_func(lambda: sys.stdout, get_text_stdout) -_default_text_stderr = _make_cached_stream_func(lambda: sys.stderr, get_text_stderr) - - -binary_streams: t.Mapping[str, t.Callable[[], t.BinaryIO]] = { - "stdin": get_binary_stdin, - "stdout": get_binary_stdout, - "stderr": get_binary_stderr, -} - -text_streams: t.Mapping[ - str, t.Callable[[t.Optional[str], t.Optional[str]], t.TextIO] -] = { - "stdin": get_text_stdin, - "stdout": get_text_stdout, - "stderr": get_text_stderr, -} diff --git a/venv/Lib/site-packages/click/_termui_impl.py b/venv/Lib/site-packages/click/_termui_impl.py deleted file mode 100644 index ad9f8f6..0000000 --- a/venv/Lib/site-packages/click/_termui_impl.py +++ /dev/null @@ -1,788 +0,0 @@ -""" -This module contains implementations for the termui module. To keep the -import time of Click down, some infrequently used functionality is -placed in this module and only imported as needed. -""" - -import contextlib -import math -import os -import sys -import time -import typing as t -from gettext import gettext as _ -from io import StringIO -from shutil import which -from types import TracebackType - -from ._compat import _default_text_stdout -from ._compat import CYGWIN -from ._compat import get_best_encoding -from ._compat import isatty -from ._compat import open_stream -from ._compat import strip_ansi -from ._compat import term_len -from ._compat import WIN -from .exceptions import ClickException -from .utils import echo - -V = t.TypeVar("V") - -if os.name == "nt": - BEFORE_BAR = "\r" - AFTER_BAR = "\n" -else: - BEFORE_BAR = "\r\033[?25l" - AFTER_BAR = "\033[?25h\n" - - -class ProgressBar(t.Generic[V]): - def __init__( - self, - iterable: t.Optional[t.Iterable[V]], - length: t.Optional[int] = None, - fill_char: str = "#", - empty_char: str = " ", - bar_template: str = "%(bar)s", - info_sep: str = " ", - show_eta: bool = True, - show_percent: t.Optional[bool] = None, - show_pos: bool = False, - item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, - label: t.Optional[str] = None, - file: t.Optional[t.TextIO] = None, - color: t.Optional[bool] = None, - update_min_steps: int = 1, - width: int = 30, - ) -> None: - self.fill_char = fill_char - self.empty_char = empty_char - self.bar_template = bar_template - self.info_sep = info_sep - self.show_eta = show_eta - self.show_percent = show_percent - self.show_pos = show_pos - self.item_show_func = item_show_func - self.label: str = label or "" - - if file is None: - file = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if file is None: - file = StringIO() - - self.file = file - self.color = color - self.update_min_steps = update_min_steps - self._completed_intervals = 0 - self.width: int = width - self.autowidth: bool = width == 0 - - if length is None: - from operator import length_hint - - length = length_hint(iterable, -1) - - if length == -1: - length = None - if iterable is None: - if length is None: - raise TypeError("iterable or length is required") - iterable = t.cast(t.Iterable[V], range(length)) - self.iter: t.Iterable[V] = iter(iterable) - self.length = length - self.pos = 0 - self.avg: t.List[float] = [] - self.last_eta: float - self.start: float - self.start = self.last_eta = time.time() - self.eta_known: bool = False - self.finished: bool = False - self.max_width: t.Optional[int] = None - self.entered: bool = False - self.current_item: t.Optional[V] = None - self.is_hidden: bool = not isatty(self.file) - self._last_line: t.Optional[str] = None - - def __enter__(self) -> "ProgressBar[V]": - self.entered = True - self.render_progress() - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - self.render_finish() - - def __iter__(self) -> t.Iterator[V]: - if not self.entered: - raise RuntimeError("You need to use progress bars in a with block.") - self.render_progress() - return self.generator() - - def __next__(self) -> V: - # Iteration is defined in terms of a generator function, - # returned by iter(self); use that to define next(). This works - # because `self.iter` is an iterable consumed by that generator, - # so it is re-entry safe. Calling `next(self.generator())` - # twice works and does "what you want". - return next(iter(self)) - - def render_finish(self) -> None: - if self.is_hidden: - return - self.file.write(AFTER_BAR) - self.file.flush() - - @property - def pct(self) -> float: - if self.finished: - return 1.0 - return min(self.pos / (float(self.length or 1) or 1), 1.0) - - @property - def time_per_iteration(self) -> float: - if not self.avg: - return 0.0 - return sum(self.avg) / float(len(self.avg)) - - @property - def eta(self) -> float: - if self.length is not None and not self.finished: - return self.time_per_iteration * (self.length - self.pos) - return 0.0 - - def format_eta(self) -> str: - if self.eta_known: - t = int(self.eta) - seconds = t % 60 - t //= 60 - minutes = t % 60 - t //= 60 - hours = t % 24 - t //= 24 - if t > 0: - return f"{t}d {hours:02}:{minutes:02}:{seconds:02}" - else: - return f"{hours:02}:{minutes:02}:{seconds:02}" - return "" - - def format_pos(self) -> str: - pos = str(self.pos) - if self.length is not None: - pos += f"/{self.length}" - return pos - - def format_pct(self) -> str: - return f"{int(self.pct * 100): 4}%"[1:] - - def format_bar(self) -> str: - if self.length is not None: - bar_length = int(self.pct * self.width) - bar = self.fill_char * bar_length - bar += self.empty_char * (self.width - bar_length) - elif self.finished: - bar = self.fill_char * self.width - else: - chars = list(self.empty_char * (self.width or 1)) - if self.time_per_iteration != 0: - chars[ - int( - (math.cos(self.pos * self.time_per_iteration) / 2.0 + 0.5) - * self.width - ) - ] = self.fill_char - bar = "".join(chars) - return bar - - def format_progress_line(self) -> str: - show_percent = self.show_percent - - info_bits = [] - if self.length is not None and show_percent is None: - show_percent = not self.show_pos - - if self.show_pos: - info_bits.append(self.format_pos()) - if show_percent: - info_bits.append(self.format_pct()) - if self.show_eta and self.eta_known and not self.finished: - info_bits.append(self.format_eta()) - if self.item_show_func is not None: - item_info = self.item_show_func(self.current_item) - if item_info is not None: - info_bits.append(item_info) - - return ( - self.bar_template - % { - "label": self.label, - "bar": self.format_bar(), - "info": self.info_sep.join(info_bits), - } - ).rstrip() - - def render_progress(self) -> None: - import shutil - - if self.is_hidden: - # Only output the label as it changes if the output is not a - # TTY. Use file=stderr if you expect to be piping stdout. - if self._last_line != self.label: - self._last_line = self.label - echo(self.label, file=self.file, color=self.color) - - return - - buf = [] - # Update width in case the terminal has been resized - if self.autowidth: - old_width = self.width - self.width = 0 - clutter_length = term_len(self.format_progress_line()) - new_width = max(0, shutil.get_terminal_size().columns - clutter_length) - if new_width < old_width: - buf.append(BEFORE_BAR) - buf.append(" " * self.max_width) # type: ignore - self.max_width = new_width - self.width = new_width - - clear_width = self.width - if self.max_width is not None: - clear_width = self.max_width - - buf.append(BEFORE_BAR) - line = self.format_progress_line() - line_len = term_len(line) - if self.max_width is None or self.max_width < line_len: - self.max_width = line_len - - buf.append(line) - buf.append(" " * (clear_width - line_len)) - line = "".join(buf) - # Render the line only if it changed. - - if line != self._last_line: - self._last_line = line - echo(line, file=self.file, color=self.color, nl=False) - self.file.flush() - - def make_step(self, n_steps: int) -> None: - self.pos += n_steps - if self.length is not None and self.pos >= self.length: - self.finished = True - - if (time.time() - self.last_eta) < 1.0: - return - - self.last_eta = time.time() - - # self.avg is a rolling list of length <= 7 of steps where steps are - # defined as time elapsed divided by the total progress through - # self.length. - if self.pos: - step = (time.time() - self.start) / self.pos - else: - step = time.time() - self.start - - self.avg = self.avg[-6:] + [step] - - self.eta_known = self.length is not None - - def update(self, n_steps: int, current_item: t.Optional[V] = None) -> None: - """Update the progress bar by advancing a specified number of - steps, and optionally set the ``current_item`` for this new - position. - - :param n_steps: Number of steps to advance. - :param current_item: Optional item to set as ``current_item`` - for the updated position. - - .. versionchanged:: 8.0 - Added the ``current_item`` optional parameter. - - .. versionchanged:: 8.0 - Only render when the number of steps meets the - ``update_min_steps`` threshold. - """ - if current_item is not None: - self.current_item = current_item - - self._completed_intervals += n_steps - - if self._completed_intervals >= self.update_min_steps: - self.make_step(self._completed_intervals) - self.render_progress() - self._completed_intervals = 0 - - def finish(self) -> None: - self.eta_known = False - self.current_item = None - self.finished = True - - def generator(self) -> t.Iterator[V]: - """Return a generator which yields the items added to the bar - during construction, and updates the progress bar *after* the - yielded block returns. - """ - # WARNING: the iterator interface for `ProgressBar` relies on - # this and only works because this is a simple generator which - # doesn't create or manage additional state. If this function - # changes, the impact should be evaluated both against - # `iter(bar)` and `next(bar)`. `next()` in particular may call - # `self.generator()` repeatedly, and this must remain safe in - # order for that interface to work. - if not self.entered: - raise RuntimeError("You need to use progress bars in a with block.") - - if self.is_hidden: - yield from self.iter - else: - for rv in self.iter: - self.current_item = rv - - # This allows show_item_func to be updated before the - # item is processed. Only trigger at the beginning of - # the update interval. - if self._completed_intervals == 0: - self.render_progress() - - yield rv - self.update(1) - - self.finish() - self.render_progress() - - -def pager(generator: t.Iterable[str], color: t.Optional[bool] = None) -> None: - """Decide what method to use for paging through text.""" - stdout = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if stdout is None: - stdout = StringIO() - - if not isatty(sys.stdin) or not isatty(stdout): - return _nullpager(stdout, generator, color) - pager_cmd = (os.environ.get("PAGER", None) or "").strip() - if pager_cmd: - if WIN: - if _tempfilepager(generator, pager_cmd, color): - return - elif _pipepager(generator, pager_cmd, color): - return - if os.environ.get("TERM") in ("dumb", "emacs"): - return _nullpager(stdout, generator, color) - if (WIN or sys.platform.startswith("os2")) and _tempfilepager( - generator, "more", color - ): - return - if _pipepager(generator, "less", color): - return - - import tempfile - - fd, filename = tempfile.mkstemp() - os.close(fd) - try: - if _pipepager(generator, "more", color): - return - return _nullpager(stdout, generator, color) - finally: - os.unlink(filename) - - -def _pipepager(generator: t.Iterable[str], cmd: str, color: t.Optional[bool]) -> bool: - """Page through text by feeding it to another program. Invoking a - pager through this might support colors. - - Returns True if the command was found, False otherwise and thus another - pager should be attempted. - """ - cmd_absolute = which(cmd) - if cmd_absolute is None: - return False - - import subprocess - - env = dict(os.environ) - - # If we're piping to less we might support colors under the - # condition that - cmd_detail = cmd.rsplit("/", 1)[-1].split() - if color is None and cmd_detail[0] == "less": - less_flags = f"{os.environ.get('LESS', '')}{' '.join(cmd_detail[1:])}" - if not less_flags: - env["LESS"] = "-R" - color = True - elif "r" in less_flags or "R" in less_flags: - color = True - - c = subprocess.Popen( - [cmd_absolute], - shell=True, - stdin=subprocess.PIPE, - env=env, - errors="replace", - text=True, - ) - assert c.stdin is not None - try: - for text in generator: - if not color: - text = strip_ansi(text) - - c.stdin.write(text) - except (OSError, KeyboardInterrupt): - pass - else: - c.stdin.close() - - # Less doesn't respect ^C, but catches it for its own UI purposes (aborting - # search or other commands inside less). - # - # That means when the user hits ^C, the parent process (click) terminates, - # but less is still alive, paging the output and messing up the terminal. - # - # If the user wants to make the pager exit on ^C, they should set - # `LESS='-K'`. It's not our decision to make. - while True: - try: - c.wait() - except KeyboardInterrupt: - pass - else: - break - - return True - - -def _tempfilepager( - generator: t.Iterable[str], - cmd: str, - color: t.Optional[bool], -) -> bool: - """Page through text by invoking a program on a temporary file. - - Returns True if the command was found, False otherwise and thus another - pager should be attempted. - """ - # Which is necessary for Windows, it is also recommended in the Popen docs. - cmd_absolute = which(cmd) - if cmd_absolute is None: - return False - - import subprocess - import tempfile - - fd, filename = tempfile.mkstemp() - # TODO: This never terminates if the passed generator never terminates. - text = "".join(generator) - if not color: - text = strip_ansi(text) - encoding = get_best_encoding(sys.stdout) - with open_stream(filename, "wb")[0] as f: - f.write(text.encode(encoding)) - try: - subprocess.call([cmd_absolute, filename]) - except OSError: - # Command not found - pass - finally: - os.close(fd) - os.unlink(filename) - - return True - - -def _nullpager( - stream: t.TextIO, generator: t.Iterable[str], color: t.Optional[bool] -) -> None: - """Simply print unformatted text. This is the ultimate fallback.""" - for text in generator: - if not color: - text = strip_ansi(text) - stream.write(text) - - -class Editor: - def __init__( - self, - editor: t.Optional[str] = None, - env: t.Optional[t.Mapping[str, str]] = None, - require_save: bool = True, - extension: str = ".txt", - ) -> None: - self.editor = editor - self.env = env - self.require_save = require_save - self.extension = extension - - def get_editor(self) -> str: - if self.editor is not None: - return self.editor - for key in "VISUAL", "EDITOR": - rv = os.environ.get(key) - if rv: - return rv - if WIN: - return "notepad" - for editor in "sensible-editor", "vim", "nano": - if which(editor) is not None: - return editor - return "vi" - - def edit_file(self, filename: str) -> None: - import subprocess - - editor = self.get_editor() - environ: t.Optional[t.Dict[str, str]] = None - - if self.env: - environ = os.environ.copy() - environ.update(self.env) - - try: - c = subprocess.Popen(f'{editor} "{filename}"', env=environ, shell=True) - exit_code = c.wait() - if exit_code != 0: - raise ClickException( - _("{editor}: Editing failed").format(editor=editor) - ) - except OSError as e: - raise ClickException( - _("{editor}: Editing failed: {e}").format(editor=editor, e=e) - ) from e - - def edit(self, text: t.Optional[t.AnyStr]) -> t.Optional[t.AnyStr]: - import tempfile - - if not text: - data = b"" - elif isinstance(text, (bytes, bytearray)): - data = text - else: - if text and not text.endswith("\n"): - text += "\n" - - if WIN: - data = text.replace("\n", "\r\n").encode("utf-8-sig") - else: - data = text.encode("utf-8") - - fd, name = tempfile.mkstemp(prefix="editor-", suffix=self.extension) - f: t.BinaryIO - - try: - with os.fdopen(fd, "wb") as f: - f.write(data) - - # If the filesystem resolution is 1 second, like Mac OS - # 10.12 Extended, or 2 seconds, like FAT32, and the editor - # closes very fast, require_save can fail. Set the modified - # time to be 2 seconds in the past to work around this. - os.utime(name, (os.path.getatime(name), os.path.getmtime(name) - 2)) - # Depending on the resolution, the exact value might not be - # recorded, so get the new recorded value. - timestamp = os.path.getmtime(name) - - self.edit_file(name) - - if self.require_save and os.path.getmtime(name) == timestamp: - return None - - with open(name, "rb") as f: - rv = f.read() - - if isinstance(text, (bytes, bytearray)): - return rv - - return rv.decode("utf-8-sig").replace("\r\n", "\n") # type: ignore - finally: - os.unlink(name) - - -def open_url(url: str, wait: bool = False, locate: bool = False) -> int: - import subprocess - - def _unquote_file(url: str) -> str: - from urllib.parse import unquote - - if url.startswith("file://"): - url = unquote(url[7:]) - - return url - - if sys.platform == "darwin": - args = ["open"] - if wait: - args.append("-W") - if locate: - args.append("-R") - args.append(_unquote_file(url)) - null = open("/dev/null", "w") - try: - return subprocess.Popen(args, stderr=null).wait() - finally: - null.close() - elif WIN: - if locate: - url = _unquote_file(url) - args = ["explorer", f"/select,{url}"] - else: - args = ["start"] - if wait: - args.append("/WAIT") - args.append("") - args.append(url) - try: - return subprocess.call(args) - except OSError: - # Command not found - return 127 - elif CYGWIN: - if locate: - url = _unquote_file(url) - args = ["cygstart", os.path.dirname(url)] - else: - args = ["cygstart"] - if wait: - args.append("-w") - args.append(url) - try: - return subprocess.call(args) - except OSError: - # Command not found - return 127 - - try: - if locate: - url = os.path.dirname(_unquote_file(url)) or "." - else: - url = _unquote_file(url) - c = subprocess.Popen(["xdg-open", url]) - if wait: - return c.wait() - return 0 - except OSError: - if url.startswith(("http://", "https://")) and not locate and not wait: - import webbrowser - - webbrowser.open(url) - return 0 - return 1 - - -def _translate_ch_to_exc(ch: str) -> t.Optional[BaseException]: - if ch == "\x03": - raise KeyboardInterrupt() - - if ch == "\x04" and not WIN: # Unix-like, Ctrl+D - raise EOFError() - - if ch == "\x1a" and WIN: # Windows, Ctrl+Z - raise EOFError() - - return None - - -if WIN: - import msvcrt - - @contextlib.contextmanager - def raw_terminal() -> t.Iterator[int]: - yield -1 - - def getchar(echo: bool) -> str: - # The function `getch` will return a bytes object corresponding to - # the pressed character. Since Windows 10 build 1803, it will also - # return \x00 when called a second time after pressing a regular key. - # - # `getwch` does not share this probably-bugged behavior. Moreover, it - # returns a Unicode object by default, which is what we want. - # - # Either of these functions will return \x00 or \xe0 to indicate - # a special key, and you need to call the same function again to get - # the "rest" of the code. The fun part is that \u00e0 is - # "latin small letter a with grave", so if you type that on a French - # keyboard, you _also_ get a \xe0. - # E.g., consider the Up arrow. This returns \xe0 and then \x48. The - # resulting Unicode string reads as "a with grave" + "capital H". - # This is indistinguishable from when the user actually types - # "a with grave" and then "capital H". - # - # When \xe0 is returned, we assume it's part of a special-key sequence - # and call `getwch` again, but that means that when the user types - # the \u00e0 character, `getchar` doesn't return until a second - # character is typed. - # The alternative is returning immediately, but that would mess up - # cross-platform handling of arrow keys and others that start with - # \xe0. Another option is using `getch`, but then we can't reliably - # read non-ASCII characters, because return values of `getch` are - # limited to the current 8-bit codepage. - # - # Anyway, Click doesn't claim to do this Right(tm), and using `getwch` - # is doing the right thing in more situations than with `getch`. - func: t.Callable[[], str] - - if echo: - func = msvcrt.getwche # type: ignore - else: - func = msvcrt.getwch # type: ignore - - rv = func() - - if rv in ("\x00", "\xe0"): - # \x00 and \xe0 are control characters that indicate special key, - # see above. - rv += func() - - _translate_ch_to_exc(rv) - return rv - -else: - import termios - import tty - - @contextlib.contextmanager - def raw_terminal() -> t.Iterator[int]: - f: t.Optional[t.TextIO] - fd: int - - if not isatty(sys.stdin): - f = open("/dev/tty") - fd = f.fileno() - else: - fd = sys.stdin.fileno() - f = None - - try: - old_settings = termios.tcgetattr(fd) - - try: - tty.setraw(fd) - yield fd - finally: - termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) - sys.stdout.flush() - - if f is not None: - f.close() - except termios.error: - pass - - def getchar(echo: bool) -> str: - with raw_terminal() as fd: - ch = os.read(fd, 32).decode(get_best_encoding(sys.stdin), "replace") - - if echo and isatty(sys.stdout): - sys.stdout.write(ch) - - _translate_ch_to_exc(ch) - return ch diff --git a/venv/Lib/site-packages/click/_textwrap.py b/venv/Lib/site-packages/click/_textwrap.py deleted file mode 100644 index b47dcbd..0000000 --- a/venv/Lib/site-packages/click/_textwrap.py +++ /dev/null @@ -1,49 +0,0 @@ -import textwrap -import typing as t -from contextlib import contextmanager - - -class TextWrapper(textwrap.TextWrapper): - def _handle_long_word( - self, - reversed_chunks: t.List[str], - cur_line: t.List[str], - cur_len: int, - width: int, - ) -> None: - space_left = max(width - cur_len, 1) - - if self.break_long_words: - last = reversed_chunks[-1] - cut = last[:space_left] - res = last[space_left:] - cur_line.append(cut) - reversed_chunks[-1] = res - elif not cur_line: - cur_line.append(reversed_chunks.pop()) - - @contextmanager - def extra_indent(self, indent: str) -> t.Iterator[None]: - old_initial_indent = self.initial_indent - old_subsequent_indent = self.subsequent_indent - self.initial_indent += indent - self.subsequent_indent += indent - - try: - yield - finally: - self.initial_indent = old_initial_indent - self.subsequent_indent = old_subsequent_indent - - def indent_only(self, text: str) -> str: - rv = [] - - for idx, line in enumerate(text.splitlines()): - indent = self.initial_indent - - if idx > 0: - indent = self.subsequent_indent - - rv.append(f"{indent}{line}") - - return "\n".join(rv) diff --git a/venv/Lib/site-packages/click/_winconsole.py b/venv/Lib/site-packages/click/_winconsole.py deleted file mode 100644 index 6b20df3..0000000 --- a/venv/Lib/site-packages/click/_winconsole.py +++ /dev/null @@ -1,279 +0,0 @@ -# This module is based on the excellent work by Adam Bartoš who -# provided a lot of what went into the implementation here in -# the discussion to issue1602 in the Python bug tracker. -# -# There are some general differences in regards to how this works -# compared to the original patches as we do not need to patch -# the entire interpreter but just work in our little world of -# echo and prompt. -import io -import sys -import time -import typing as t -from ctypes import byref -from ctypes import c_char -from ctypes import c_char_p -from ctypes import c_int -from ctypes import c_ssize_t -from ctypes import c_ulong -from ctypes import c_void_p -from ctypes import POINTER -from ctypes import py_object -from ctypes import Structure -from ctypes.wintypes import DWORD -from ctypes.wintypes import HANDLE -from ctypes.wintypes import LPCWSTR -from ctypes.wintypes import LPWSTR - -from ._compat import _NonClosingTextIOWrapper - -assert sys.platform == "win32" -import msvcrt # noqa: E402 -from ctypes import windll # noqa: E402 -from ctypes import WINFUNCTYPE # noqa: E402 - -c_ssize_p = POINTER(c_ssize_t) - -kernel32 = windll.kernel32 -GetStdHandle = kernel32.GetStdHandle -ReadConsoleW = kernel32.ReadConsoleW -WriteConsoleW = kernel32.WriteConsoleW -GetConsoleMode = kernel32.GetConsoleMode -GetLastError = kernel32.GetLastError -GetCommandLineW = WINFUNCTYPE(LPWSTR)(("GetCommandLineW", windll.kernel32)) -CommandLineToArgvW = WINFUNCTYPE(POINTER(LPWSTR), LPCWSTR, POINTER(c_int))( - ("CommandLineToArgvW", windll.shell32) -) -LocalFree = WINFUNCTYPE(c_void_p, c_void_p)(("LocalFree", windll.kernel32)) - -STDIN_HANDLE = GetStdHandle(-10) -STDOUT_HANDLE = GetStdHandle(-11) -STDERR_HANDLE = GetStdHandle(-12) - -PyBUF_SIMPLE = 0 -PyBUF_WRITABLE = 1 - -ERROR_SUCCESS = 0 -ERROR_NOT_ENOUGH_MEMORY = 8 -ERROR_OPERATION_ABORTED = 995 - -STDIN_FILENO = 0 -STDOUT_FILENO = 1 -STDERR_FILENO = 2 - -EOF = b"\x1a" -MAX_BYTES_WRITTEN = 32767 - -try: - from ctypes import pythonapi -except ImportError: - # On PyPy we cannot get buffers so our ability to operate here is - # severely limited. - get_buffer = None -else: - - class Py_buffer(Structure): - _fields_ = [ - ("buf", c_void_p), - ("obj", py_object), - ("len", c_ssize_t), - ("itemsize", c_ssize_t), - ("readonly", c_int), - ("ndim", c_int), - ("format", c_char_p), - ("shape", c_ssize_p), - ("strides", c_ssize_p), - ("suboffsets", c_ssize_p), - ("internal", c_void_p), - ] - - PyObject_GetBuffer = pythonapi.PyObject_GetBuffer - PyBuffer_Release = pythonapi.PyBuffer_Release - - def get_buffer(obj, writable=False): - buf = Py_buffer() - flags = PyBUF_WRITABLE if writable else PyBUF_SIMPLE - PyObject_GetBuffer(py_object(obj), byref(buf), flags) - - try: - buffer_type = c_char * buf.len - return buffer_type.from_address(buf.buf) - finally: - PyBuffer_Release(byref(buf)) - - -class _WindowsConsoleRawIOBase(io.RawIOBase): - def __init__(self, handle): - self.handle = handle - - def isatty(self): - super().isatty() - return True - - -class _WindowsConsoleReader(_WindowsConsoleRawIOBase): - def readable(self): - return True - - def readinto(self, b): - bytes_to_be_read = len(b) - if not bytes_to_be_read: - return 0 - elif bytes_to_be_read % 2: - raise ValueError( - "cannot read odd number of bytes from UTF-16-LE encoded console" - ) - - buffer = get_buffer(b, writable=True) - code_units_to_be_read = bytes_to_be_read // 2 - code_units_read = c_ulong() - - rv = ReadConsoleW( - HANDLE(self.handle), - buffer, - code_units_to_be_read, - byref(code_units_read), - None, - ) - if GetLastError() == ERROR_OPERATION_ABORTED: - # wait for KeyboardInterrupt - time.sleep(0.1) - if not rv: - raise OSError(f"Windows error: {GetLastError()}") - - if buffer[0] == EOF: - return 0 - return 2 * code_units_read.value - - -class _WindowsConsoleWriter(_WindowsConsoleRawIOBase): - def writable(self): - return True - - @staticmethod - def _get_error_message(errno): - if errno == ERROR_SUCCESS: - return "ERROR_SUCCESS" - elif errno == ERROR_NOT_ENOUGH_MEMORY: - return "ERROR_NOT_ENOUGH_MEMORY" - return f"Windows error {errno}" - - def write(self, b): - bytes_to_be_written = len(b) - buf = get_buffer(b) - code_units_to_be_written = min(bytes_to_be_written, MAX_BYTES_WRITTEN) // 2 - code_units_written = c_ulong() - - WriteConsoleW( - HANDLE(self.handle), - buf, - code_units_to_be_written, - byref(code_units_written), - None, - ) - bytes_written = 2 * code_units_written.value - - if bytes_written == 0 and bytes_to_be_written > 0: - raise OSError(self._get_error_message(GetLastError())) - return bytes_written - - -class ConsoleStream: - def __init__(self, text_stream: t.TextIO, byte_stream: t.BinaryIO) -> None: - self._text_stream = text_stream - self.buffer = byte_stream - - @property - def name(self) -> str: - return self.buffer.name - - def write(self, x: t.AnyStr) -> int: - if isinstance(x, str): - return self._text_stream.write(x) - try: - self.flush() - except Exception: - pass - return self.buffer.write(x) - - def writelines(self, lines: t.Iterable[t.AnyStr]) -> None: - for line in lines: - self.write(line) - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._text_stream, name) - - def isatty(self) -> bool: - return self.buffer.isatty() - - def __repr__(self): - return f"" - - -def _get_text_stdin(buffer_stream: t.BinaryIO) -> t.TextIO: - text_stream = _NonClosingTextIOWrapper( - io.BufferedReader(_WindowsConsoleReader(STDIN_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) - - -def _get_text_stdout(buffer_stream: t.BinaryIO) -> t.TextIO: - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDOUT_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) - - -def _get_text_stderr(buffer_stream: t.BinaryIO) -> t.TextIO: - text_stream = _NonClosingTextIOWrapper( - io.BufferedWriter(_WindowsConsoleWriter(STDERR_HANDLE)), - "utf-16-le", - "strict", - line_buffering=True, - ) - return t.cast(t.TextIO, ConsoleStream(text_stream, buffer_stream)) - - -_stream_factories: t.Mapping[int, t.Callable[[t.BinaryIO], t.TextIO]] = { - 0: _get_text_stdin, - 1: _get_text_stdout, - 2: _get_text_stderr, -} - - -def _is_console(f: t.TextIO) -> bool: - if not hasattr(f, "fileno"): - return False - - try: - fileno = f.fileno() - except (OSError, io.UnsupportedOperation): - return False - - handle = msvcrt.get_osfhandle(fileno) - return bool(GetConsoleMode(handle, byref(DWORD()))) - - -def _get_windows_console_stream( - f: t.TextIO, encoding: t.Optional[str], errors: t.Optional[str] -) -> t.Optional[t.TextIO]: - if ( - get_buffer is not None - and encoding in {"utf-16-le", None} - and errors in {"strict", None} - and _is_console(f) - ): - func = _stream_factories.get(f.fileno()) - if func is not None: - b = getattr(f, "buffer", None) - - if b is None: - return None - - return func(b) diff --git a/venv/Lib/site-packages/click/core.py b/venv/Lib/site-packages/click/core.py deleted file mode 100644 index e630501..0000000 --- a/venv/Lib/site-packages/click/core.py +++ /dev/null @@ -1,3047 +0,0 @@ -import enum -import errno -import inspect -import os -import sys -import typing as t -from collections import abc -from contextlib import contextmanager -from contextlib import ExitStack -from functools import update_wrapper -from gettext import gettext as _ -from gettext import ngettext -from itertools import repeat -from types import TracebackType - -from . import types -from .exceptions import Abort -from .exceptions import BadParameter -from .exceptions import ClickException -from .exceptions import Exit -from .exceptions import MissingParameter -from .exceptions import UsageError -from .formatting import HelpFormatter -from .formatting import join_options -from .globals import pop_context -from .globals import push_context -from .parser import _flag_needs_value -from .parser import OptionParser -from .parser import split_opt -from .termui import confirm -from .termui import prompt -from .termui import style -from .utils import _detect_program_name -from .utils import _expand_args -from .utils import echo -from .utils import make_default_short_help -from .utils import make_str -from .utils import PacifyFlushWrapper - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .decorators import HelpOption - from .shell_completion import CompletionItem - -F = t.TypeVar("F", bound=t.Callable[..., t.Any]) -V = t.TypeVar("V") - - -def _complete_visible_commands( - ctx: "Context", incomplete: str -) -> t.Iterator[t.Tuple[str, "Command"]]: - """List all the subcommands of a group that start with the - incomplete value and aren't hidden. - - :param ctx: Invocation context for the group. - :param incomplete: Value being completed. May be empty. - """ - multi = t.cast(MultiCommand, ctx.command) - - for name in multi.list_commands(ctx): - if name.startswith(incomplete): - command = multi.get_command(ctx, name) - - if command is not None and not command.hidden: - yield name, command - - -def _check_multicommand( - base_command: "MultiCommand", cmd_name: str, cmd: "Command", register: bool = False -) -> None: - if not base_command.chain or not isinstance(cmd, MultiCommand): - return - if register: - hint = ( - "It is not possible to add multi commands as children to" - " another multi command that is in chain mode." - ) - else: - hint = ( - "Found a multi command as subcommand to a multi command" - " that is in chain mode. This is not supported." - ) - raise RuntimeError( - f"{hint}. Command {base_command.name!r} is set to chain and" - f" {cmd_name!r} was added as a subcommand but it in itself is a" - f" multi command. ({cmd_name!r} is a {type(cmd).__name__}" - f" within a chained {type(base_command).__name__} named" - f" {base_command.name!r})." - ) - - -def batch(iterable: t.Iterable[V], batch_size: int) -> t.List[t.Tuple[V, ...]]: - return list(zip(*repeat(iter(iterable), batch_size))) - - -@contextmanager -def augment_usage_errors( - ctx: "Context", param: t.Optional["Parameter"] = None -) -> t.Iterator[None]: - """Context manager that attaches extra information to exceptions.""" - try: - yield - except BadParameter as e: - if e.ctx is None: - e.ctx = ctx - if param is not None and e.param is None: - e.param = param - raise - except UsageError as e: - if e.ctx is None: - e.ctx = ctx - raise - - -def iter_params_for_processing( - invocation_order: t.Sequence["Parameter"], - declaration_order: t.Sequence["Parameter"], -) -> t.List["Parameter"]: - """Returns all declared parameters in the order they should be processed. - - The declared parameters are re-shuffled depending on the order in which - they were invoked, as well as the eagerness of each parameters. - - The invocation order takes precedence over the declaration order. I.e. the - order in which the user provided them to the CLI is respected. - - This behavior and its effect on callback evaluation is detailed at: - https://click.palletsprojects.com/en/stable/advanced/#callback-evaluation-order - """ - - def sort_key(item: "Parameter") -> t.Tuple[bool, float]: - try: - idx: float = invocation_order.index(item) - except ValueError: - idx = float("inf") - - return not item.is_eager, idx - - return sorted(declaration_order, key=sort_key) - - -class ParameterSource(enum.Enum): - """This is an :class:`~enum.Enum` that indicates the source of a - parameter's value. - - Use :meth:`click.Context.get_parameter_source` to get the - source for a parameter by name. - - .. versionchanged:: 8.0 - Use :class:`~enum.Enum` and drop the ``validate`` method. - - .. versionchanged:: 8.0 - Added the ``PROMPT`` value. - """ - - COMMANDLINE = enum.auto() - """The value was provided by the command line args.""" - ENVIRONMENT = enum.auto() - """The value was provided with an environment variable.""" - DEFAULT = enum.auto() - """Used the default specified by the parameter.""" - DEFAULT_MAP = enum.auto() - """Used a default provided by :attr:`Context.default_map`.""" - PROMPT = enum.auto() - """Used a prompt to confirm a default or provide a value.""" - - -class Context: - """The context is a special internal object that holds state relevant - for the script execution at every single level. It's normally invisible - to commands unless they opt-in to getting access to it. - - The context is useful as it can pass internal objects around and can - control special execution features such as reading data from - environment variables. - - A context can be used as context manager in which case it will call - :meth:`close` on teardown. - - :param command: the command class for this context. - :param parent: the parent context. - :param info_name: the info name for this invocation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it is usually - the name of the script, for commands below it it's - the name of the script. - :param obj: an arbitrary object of user data. - :param auto_envvar_prefix: the prefix to use for automatic environment - variables. If this is `None` then reading - from environment variables is disabled. This - does not affect manually set environment - variables which are always read. - :param default_map: a dictionary (like object) with default values - for parameters. - :param terminal_width: the width of the terminal. The default is - inherit from parent context. If no context - defines the terminal width then auto - detection will be applied. - :param max_content_width: the maximum width for content rendered by - Click (this currently only affects help - pages). This defaults to 80 characters if - not overridden. In other words: even if the - terminal is larger than that, Click will not - format things wider than 80 characters by - default. In addition to that, formatters might - add some safety mapping on the right. - :param resilient_parsing: if this flag is enabled then Click will - parse without any interactivity or callback - invocation. Default values will also be - ignored. This is useful for implementing - things such as completion support. - :param allow_extra_args: if this is set to `True` then extra arguments - at the end will not raise an error and will be - kept on the context. The default is to inherit - from the command. - :param allow_interspersed_args: if this is set to `False` then options - and arguments cannot be mixed. The - default is to inherit from the command. - :param ignore_unknown_options: instructs click to ignore options it does - not know and keeps them for later - processing. - :param help_option_names: optionally a list of strings that define how - the default help parameter is named. The - default is ``['--help']``. - :param token_normalize_func: an optional function that is used to - normalize tokens (options, choices, - etc.). This for instance can be used to - implement case insensitive behavior. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are used in texts that Click prints which is by - default not the case. This for instance would affect - help output. - :param show_default: Show the default value for commands. If this - value is not set, it defaults to the value from the parent - context. ``Command.show_default`` overrides this default for the - specific command. - - .. versionchanged:: 8.1 - The ``show_default`` parameter is overridden by - ``Command.show_default``, instead of the other way around. - - .. versionchanged:: 8.0 - The ``show_default`` parameter defaults to the value from the - parent context. - - .. versionchanged:: 7.1 - Added the ``show_default`` parameter. - - .. versionchanged:: 4.0 - Added the ``color``, ``ignore_unknown_options``, and - ``max_content_width`` parameters. - - .. versionchanged:: 3.0 - Added the ``allow_extra_args`` and ``allow_interspersed_args`` - parameters. - - .. versionchanged:: 2.0 - Added the ``resilient_parsing``, ``help_option_names``, and - ``token_normalize_func`` parameters. - """ - - #: The formatter class to create with :meth:`make_formatter`. - #: - #: .. versionadded:: 8.0 - formatter_class: t.Type["HelpFormatter"] = HelpFormatter - - def __init__( - self, - command: "Command", - parent: t.Optional["Context"] = None, - info_name: t.Optional[str] = None, - obj: t.Optional[t.Any] = None, - auto_envvar_prefix: t.Optional[str] = None, - default_map: t.Optional[t.MutableMapping[str, t.Any]] = None, - terminal_width: t.Optional[int] = None, - max_content_width: t.Optional[int] = None, - resilient_parsing: bool = False, - allow_extra_args: t.Optional[bool] = None, - allow_interspersed_args: t.Optional[bool] = None, - ignore_unknown_options: t.Optional[bool] = None, - help_option_names: t.Optional[t.List[str]] = None, - token_normalize_func: t.Optional[t.Callable[[str], str]] = None, - color: t.Optional[bool] = None, - show_default: t.Optional[bool] = None, - ) -> None: - #: the parent context or `None` if none exists. - self.parent = parent - #: the :class:`Command` for this context. - self.command = command - #: the descriptive information name - self.info_name = info_name - #: Map of parameter names to their parsed values. Parameters - #: with ``expose_value=False`` are not stored. - self.params: t.Dict[str, t.Any] = {} - #: the leftover arguments. - self.args: t.List[str] = [] - #: protected arguments. These are arguments that are prepended - #: to `args` when certain parsing scenarios are encountered but - #: must be never propagated to another arguments. This is used - #: to implement nested parsing. - self.protected_args: t.List[str] = [] - #: the collected prefixes of the command's options. - self._opt_prefixes: t.Set[str] = set(parent._opt_prefixes) if parent else set() - - if obj is None and parent is not None: - obj = parent.obj - - #: the user object stored. - self.obj: t.Any = obj - self._meta: t.Dict[str, t.Any] = getattr(parent, "meta", {}) - - #: A dictionary (-like object) with defaults for parameters. - if ( - default_map is None - and info_name is not None - and parent is not None - and parent.default_map is not None - ): - default_map = parent.default_map.get(info_name) - - self.default_map: t.Optional[t.MutableMapping[str, t.Any]] = default_map - - #: This flag indicates if a subcommand is going to be executed. A - #: group callback can use this information to figure out if it's - #: being executed directly or because the execution flow passes - #: onwards to a subcommand. By default it's None, but it can be - #: the name of the subcommand to execute. - #: - #: If chaining is enabled this will be set to ``'*'`` in case - #: any commands are executed. It is however not possible to - #: figure out which ones. If you require this knowledge you - #: should use a :func:`result_callback`. - self.invoked_subcommand: t.Optional[str] = None - - if terminal_width is None and parent is not None: - terminal_width = parent.terminal_width - - #: The width of the terminal (None is autodetection). - self.terminal_width: t.Optional[int] = terminal_width - - if max_content_width is None and parent is not None: - max_content_width = parent.max_content_width - - #: The maximum width of formatted content (None implies a sensible - #: default which is 80 for most things). - self.max_content_width: t.Optional[int] = max_content_width - - if allow_extra_args is None: - allow_extra_args = command.allow_extra_args - - #: Indicates if the context allows extra args or if it should - #: fail on parsing. - #: - #: .. versionadded:: 3.0 - self.allow_extra_args = allow_extra_args - - if allow_interspersed_args is None: - allow_interspersed_args = command.allow_interspersed_args - - #: Indicates if the context allows mixing of arguments and - #: options or not. - #: - #: .. versionadded:: 3.0 - self.allow_interspersed_args: bool = allow_interspersed_args - - if ignore_unknown_options is None: - ignore_unknown_options = command.ignore_unknown_options - - #: Instructs click to ignore options that a command does not - #: understand and will store it on the context for later - #: processing. This is primarily useful for situations where you - #: want to call into external programs. Generally this pattern is - #: strongly discouraged because it's not possibly to losslessly - #: forward all arguments. - #: - #: .. versionadded:: 4.0 - self.ignore_unknown_options: bool = ignore_unknown_options - - if help_option_names is None: - if parent is not None: - help_option_names = parent.help_option_names - else: - help_option_names = ["--help"] - - #: The names for the help options. - self.help_option_names: t.List[str] = help_option_names - - if token_normalize_func is None and parent is not None: - token_normalize_func = parent.token_normalize_func - - #: An optional normalization function for tokens. This is - #: options, choices, commands etc. - self.token_normalize_func: t.Optional[t.Callable[[str], str]] = ( - token_normalize_func - ) - - #: Indicates if resilient parsing is enabled. In that case Click - #: will do its best to not cause any failures and default values - #: will be ignored. Useful for completion. - self.resilient_parsing: bool = resilient_parsing - - # If there is no envvar prefix yet, but the parent has one and - # the command on this level has a name, we can expand the envvar - # prefix automatically. - if auto_envvar_prefix is None: - if ( - parent is not None - and parent.auto_envvar_prefix is not None - and self.info_name is not None - ): - auto_envvar_prefix = ( - f"{parent.auto_envvar_prefix}_{self.info_name.upper()}" - ) - else: - auto_envvar_prefix = auto_envvar_prefix.upper() - - if auto_envvar_prefix is not None: - auto_envvar_prefix = auto_envvar_prefix.replace("-", "_") - - self.auto_envvar_prefix: t.Optional[str] = auto_envvar_prefix - - if color is None and parent is not None: - color = parent.color - - #: Controls if styling output is wanted or not. - self.color: t.Optional[bool] = color - - if show_default is None and parent is not None: - show_default = parent.show_default - - #: Show option default values when formatting help text. - self.show_default: t.Optional[bool] = show_default - - self._close_callbacks: t.List[t.Callable[[], t.Any]] = [] - self._depth = 0 - self._parameter_source: t.Dict[str, ParameterSource] = {} - self._exit_stack = ExitStack() - - def to_info_dict(self) -> t.Dict[str, t.Any]: - """Gather information that could be useful for a tool generating - user-facing documentation. This traverses the entire CLI - structure. - - .. code-block:: python - - with Context(cli) as ctx: - info = ctx.to_info_dict() - - .. versionadded:: 8.0 - """ - return { - "command": self.command.to_info_dict(self), - "info_name": self.info_name, - "allow_extra_args": self.allow_extra_args, - "allow_interspersed_args": self.allow_interspersed_args, - "ignore_unknown_options": self.ignore_unknown_options, - "auto_envvar_prefix": self.auto_envvar_prefix, - } - - def __enter__(self) -> "Context": - self._depth += 1 - push_context(self) - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - self._depth -= 1 - if self._depth == 0: - self.close() - pop_context() - - @contextmanager - def scope(self, cleanup: bool = True) -> t.Iterator["Context"]: - """This helper method can be used with the context object to promote - it to the current thread local (see :func:`get_current_context`). - The default behavior of this is to invoke the cleanup functions which - can be disabled by setting `cleanup` to `False`. The cleanup - functions are typically used for things such as closing file handles. - - If the cleanup is intended the context object can also be directly - used as a context manager. - - Example usage:: - - with ctx.scope(): - assert get_current_context() is ctx - - This is equivalent:: - - with ctx: - assert get_current_context() is ctx - - .. versionadded:: 5.0 - - :param cleanup: controls if the cleanup functions should be run or - not. The default is to run these functions. In - some situations the context only wants to be - temporarily pushed in which case this can be disabled. - Nested pushes automatically defer the cleanup. - """ - if not cleanup: - self._depth += 1 - try: - with self as rv: - yield rv - finally: - if not cleanup: - self._depth -= 1 - - @property - def meta(self) -> t.Dict[str, t.Any]: - """This is a dictionary which is shared with all the contexts - that are nested. It exists so that click utilities can store some - state here if they need to. It is however the responsibility of - that code to manage this dictionary well. - - The keys are supposed to be unique dotted strings. For instance - module paths are a good choice for it. What is stored in there is - irrelevant for the operation of click. However what is important is - that code that places data here adheres to the general semantics of - the system. - - Example usage:: - - LANG_KEY = f'{__name__}.lang' - - def set_language(value): - ctx = get_current_context() - ctx.meta[LANG_KEY] = value - - def get_language(): - return get_current_context().meta.get(LANG_KEY, 'en_US') - - .. versionadded:: 5.0 - """ - return self._meta - - def make_formatter(self) -> HelpFormatter: - """Creates the :class:`~click.HelpFormatter` for the help and - usage output. - - To quickly customize the formatter class used without overriding - this method, set the :attr:`formatter_class` attribute. - - .. versionchanged:: 8.0 - Added the :attr:`formatter_class` attribute. - """ - return self.formatter_class( - width=self.terminal_width, max_width=self.max_content_width - ) - - def with_resource(self, context_manager: t.ContextManager[V]) -> V: - """Register a resource as if it were used in a ``with`` - statement. The resource will be cleaned up when the context is - popped. - - Uses :meth:`contextlib.ExitStack.enter_context`. It calls the - resource's ``__enter__()`` method and returns the result. When - the context is popped, it closes the stack, which calls the - resource's ``__exit__()`` method. - - To register a cleanup function for something that isn't a - context manager, use :meth:`call_on_close`. Or use something - from :mod:`contextlib` to turn it into a context manager first. - - .. code-block:: python - - @click.group() - @click.option("--name") - @click.pass_context - def cli(ctx): - ctx.obj = ctx.with_resource(connect_db(name)) - - :param context_manager: The context manager to enter. - :return: Whatever ``context_manager.__enter__()`` returns. - - .. versionadded:: 8.0 - """ - return self._exit_stack.enter_context(context_manager) - - def call_on_close(self, f: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: - """Register a function to be called when the context tears down. - - This can be used to close resources opened during the script - execution. Resources that support Python's context manager - protocol which would be used in a ``with`` statement should be - registered with :meth:`with_resource` instead. - - :param f: The function to execute on teardown. - """ - return self._exit_stack.callback(f) - - def close(self) -> None: - """Invoke all close callbacks registered with - :meth:`call_on_close`, and exit all context managers entered - with :meth:`with_resource`. - """ - self._exit_stack.close() - # In case the context is reused, create a new exit stack. - self._exit_stack = ExitStack() - - @property - def command_path(self) -> str: - """The computed command path. This is used for the ``usage`` - information on the help page. It's automatically created by - combining the info names of the chain of contexts to the root. - """ - rv = "" - if self.info_name is not None: - rv = self.info_name - if self.parent is not None: - parent_command_path = [self.parent.command_path] - - if isinstance(self.parent.command, Command): - for param in self.parent.command.get_params(self): - parent_command_path.extend(param.get_usage_pieces(self)) - - rv = f"{' '.join(parent_command_path)} {rv}" - return rv.lstrip() - - def find_root(self) -> "Context": - """Finds the outermost context.""" - node = self - while node.parent is not None: - node = node.parent - return node - - def find_object(self, object_type: t.Type[V]) -> t.Optional[V]: - """Finds the closest object of a given type.""" - node: t.Optional[Context] = self - - while node is not None: - if isinstance(node.obj, object_type): - return node.obj - - node = node.parent - - return None - - def ensure_object(self, object_type: t.Type[V]) -> V: - """Like :meth:`find_object` but sets the innermost object to a - new instance of `object_type` if it does not exist. - """ - rv = self.find_object(object_type) - if rv is None: - self.obj = rv = object_type() - return rv - - @t.overload - def lookup_default( - self, name: str, call: "te.Literal[True]" = True - ) -> t.Optional[t.Any]: ... - - @t.overload - def lookup_default( - self, name: str, call: "te.Literal[False]" = ... - ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... - - def lookup_default(self, name: str, call: bool = True) -> t.Optional[t.Any]: - """Get the default for a parameter from :attr:`default_map`. - - :param name: Name of the parameter. - :param call: If the default is a callable, call it. Disable to - return the callable instead. - - .. versionchanged:: 8.0 - Added the ``call`` parameter. - """ - if self.default_map is not None: - value = self.default_map.get(name) - - if call and callable(value): - return value() - - return value - - return None - - def fail(self, message: str) -> "te.NoReturn": - """Aborts the execution of the program with a specific error - message. - - :param message: the error message to fail with. - """ - raise UsageError(message, self) - - def abort(self) -> "te.NoReturn": - """Aborts the script.""" - raise Abort() - - def exit(self, code: int = 0) -> "te.NoReturn": - """Exits the application with a given exit code.""" - raise Exit(code) - - def get_usage(self) -> str: - """Helper method to get formatted usage string for the current - context and command. - """ - return self.command.get_usage(self) - - def get_help(self) -> str: - """Helper method to get formatted help page for the current - context and command. - """ - return self.command.get_help(self) - - def _make_sub_context(self, command: "Command") -> "Context": - """Create a new context of the same type as this context, but - for a new command. - - :meta private: - """ - return type(self)(command, info_name=command.name, parent=self) - - @t.overload - def invoke( - __self, - __callback: "t.Callable[..., V]", - *args: t.Any, - **kwargs: t.Any, - ) -> V: ... - - @t.overload - def invoke( - __self, - __callback: "Command", - *args: t.Any, - **kwargs: t.Any, - ) -> t.Any: ... - - def invoke( - __self, - __callback: t.Union["Command", "t.Callable[..., V]"], - *args: t.Any, - **kwargs: t.Any, - ) -> t.Union[t.Any, V]: - """Invokes a command callback in exactly the way it expects. There - are two ways to invoke this method: - - 1. the first argument can be a callback and all other arguments and - keyword arguments are forwarded directly to the function. - 2. the first argument is a click command object. In that case all - arguments are forwarded as well but proper click parameters - (options and click arguments) must be keyword arguments and Click - will fill in defaults. - - Note that before Click 3.2 keyword arguments were not properly filled - in against the intention of this code and no context was created. For - more information about this change and why it was done in a bugfix - release see :ref:`upgrade-to-3.2`. - - .. versionchanged:: 8.0 - All ``kwargs`` are tracked in :attr:`params` so they will be - passed if :meth:`forward` is called at multiple levels. - """ - if isinstance(__callback, Command): - other_cmd = __callback - - if other_cmd.callback is None: - raise TypeError( - "The given command does not have a callback that can be invoked." - ) - else: - __callback = t.cast("t.Callable[..., V]", other_cmd.callback) - - ctx = __self._make_sub_context(other_cmd) - - for param in other_cmd.params: - if param.name not in kwargs and param.expose_value: - kwargs[param.name] = param.type_cast_value( # type: ignore - ctx, param.get_default(ctx) - ) - - # Track all kwargs as params, so that forward() will pass - # them on in subsequent calls. - ctx.params.update(kwargs) - else: - ctx = __self - - with augment_usage_errors(__self): - with ctx: - return __callback(*args, **kwargs) - - def forward(__self, __cmd: "Command", *args: t.Any, **kwargs: t.Any) -> t.Any: - """Similar to :meth:`invoke` but fills in default keyword - arguments from the current context if the other command expects - it. This cannot invoke callbacks directly, only other commands. - - .. versionchanged:: 8.0 - All ``kwargs`` are tracked in :attr:`params` so they will be - passed if ``forward`` is called at multiple levels. - """ - # Can only forward to other commands, not direct callbacks. - if not isinstance(__cmd, Command): - raise TypeError("Callback is not a command.") - - for param in __self.params: - if param not in kwargs: - kwargs[param] = __self.params[param] - - return __self.invoke(__cmd, *args, **kwargs) - - def set_parameter_source(self, name: str, source: ParameterSource) -> None: - """Set the source of a parameter. This indicates the location - from which the value of the parameter was obtained. - - :param name: The name of the parameter. - :param source: A member of :class:`~click.core.ParameterSource`. - """ - self._parameter_source[name] = source - - def get_parameter_source(self, name: str) -> t.Optional[ParameterSource]: - """Get the source of a parameter. This indicates the location - from which the value of the parameter was obtained. - - This can be useful for determining when a user specified a value - on the command line that is the same as the default value. It - will be :attr:`~click.core.ParameterSource.DEFAULT` only if the - value was actually taken from the default. - - :param name: The name of the parameter. - :rtype: ParameterSource - - .. versionchanged:: 8.0 - Returns ``None`` if the parameter was not provided from any - source. - """ - return self._parameter_source.get(name) - - -class BaseCommand: - """The base command implements the minimal API contract of commands. - Most code will never use this as it does not implement a lot of useful - functionality but it can act as the direct subclass of alternative - parsing methods that do not depend on the Click parser. - - For instance, this can be used to bridge Click and other systems like - argparse or docopt. - - Because base commands do not implement a lot of the API that other - parts of Click take for granted, they are not supported for all - operations. For instance, they cannot be used with the decorators - usually and they have no built-in callback system. - - .. versionchanged:: 2.0 - Added the `context_settings` parameter. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - """ - - #: The context class to create with :meth:`make_context`. - #: - #: .. versionadded:: 8.0 - context_class: t.Type[Context] = Context - #: the default for the :attr:`Context.allow_extra_args` flag. - allow_extra_args = False - #: the default for the :attr:`Context.allow_interspersed_args` flag. - allow_interspersed_args = True - #: the default for the :attr:`Context.ignore_unknown_options` flag. - ignore_unknown_options = False - - def __init__( - self, - name: t.Optional[str], - context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, - ) -> None: - #: the name the command thinks it has. Upon registering a command - #: on a :class:`Group` the group will default the command name - #: with this information. You should instead use the - #: :class:`Context`\'s :attr:`~Context.info_name` attribute. - self.name = name - - if context_settings is None: - context_settings = {} - - #: an optional dictionary with defaults passed to the context. - self.context_settings: t.MutableMapping[str, t.Any] = context_settings - - def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: - """Gather information that could be useful for a tool generating - user-facing documentation. This traverses the entire structure - below this command. - - Use :meth:`click.Context.to_info_dict` to traverse the entire - CLI structure. - - :param ctx: A :class:`Context` representing this command. - - .. versionadded:: 8.0 - """ - return {"name": self.name} - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} {self.name}>" - - def get_usage(self, ctx: Context) -> str: - raise NotImplementedError("Base commands cannot get usage") - - def get_help(self, ctx: Context) -> str: - raise NotImplementedError("Base commands cannot get help") - - def make_context( - self, - info_name: t.Optional[str], - args: t.List[str], - parent: t.Optional[Context] = None, - **extra: t.Any, - ) -> Context: - """This function when given an info name and arguments will kick - off the parsing and create a new :class:`Context`. It does not - invoke the actual command callback though. - - To quickly customize the context class used without overriding - this method, set the :attr:`context_class` attribute. - - :param info_name: the info name for this invocation. Generally this - is the most descriptive name for the script or - command. For the toplevel script it's usually - the name of the script, for commands below it's - the name of the command. - :param args: the arguments to parse as list of strings. - :param parent: the parent context if available. - :param extra: extra keyword arguments forwarded to the context - constructor. - - .. versionchanged:: 8.0 - Added the :attr:`context_class` attribute. - """ - for key, value in self.context_settings.items(): - if key not in extra: - extra[key] = value - - ctx = self.context_class( - self, # type: ignore[arg-type] - info_name=info_name, - parent=parent, - **extra, - ) - - with ctx.scope(cleanup=False): - self.parse_args(ctx, args) - return ctx - - def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: - """Given a context and a list of arguments this creates the parser - and parses the arguments, then modifies the context as necessary. - This is automatically invoked by :meth:`make_context`. - """ - raise NotImplementedError("Base commands do not know how to parse arguments.") - - def invoke(self, ctx: Context) -> t.Any: - """Given a context, this invokes the command. The default - implementation is raising a not implemented error. - """ - raise NotImplementedError("Base commands are not invocable by default") - - def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: - """Return a list of completions for the incomplete value. Looks - at the names of chained multi-commands. - - Any command could be part of a chained multi-command, so sibling - commands are valid at any point during command completion. Other - command classes will return more completions. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - results: t.List[CompletionItem] = [] - - while ctx.parent is not None: - ctx = ctx.parent - - if isinstance(ctx.command, MultiCommand) and ctx.command.chain: - results.extend( - CompletionItem(name, help=command.get_short_help_str()) - for name, command in _complete_visible_commands(ctx, incomplete) - if name not in ctx.protected_args - ) - - return results - - @t.overload - def main( - self, - args: t.Optional[t.Sequence[str]] = None, - prog_name: t.Optional[str] = None, - complete_var: t.Optional[str] = None, - standalone_mode: "te.Literal[True]" = True, - **extra: t.Any, - ) -> "te.NoReturn": ... - - @t.overload - def main( - self, - args: t.Optional[t.Sequence[str]] = None, - prog_name: t.Optional[str] = None, - complete_var: t.Optional[str] = None, - standalone_mode: bool = ..., - **extra: t.Any, - ) -> t.Any: ... - - def main( - self, - args: t.Optional[t.Sequence[str]] = None, - prog_name: t.Optional[str] = None, - complete_var: t.Optional[str] = None, - standalone_mode: bool = True, - windows_expand_args: bool = True, - **extra: t.Any, - ) -> t.Any: - """This is the way to invoke a script with all the bells and - whistles as a command line application. This will always terminate - the application after a call. If this is not wanted, ``SystemExit`` - needs to be caught. - - This method is also available by directly calling the instance of - a :class:`Command`. - - :param args: the arguments that should be used for parsing. If not - provided, ``sys.argv[1:]`` is used. - :param prog_name: the program name that should be used. By default - the program name is constructed by taking the file - name from ``sys.argv[0]``. - :param complete_var: the environment variable that controls the - bash completion support. The default is - ``"__COMPLETE"`` with prog_name in - uppercase. - :param standalone_mode: the default behavior is to invoke the script - in standalone mode. Click will then - handle exceptions and convert them into - error messages and the function will never - return but shut down the interpreter. If - this is set to `False` they will be - propagated to the caller and the return - value of this function is the return value - of :meth:`invoke`. - :param windows_expand_args: Expand glob patterns, user dir, and - env vars in command line args on Windows. - :param extra: extra keyword arguments are forwarded to the context - constructor. See :class:`Context` for more information. - - .. versionchanged:: 8.0.1 - Added the ``windows_expand_args`` parameter to allow - disabling command line arg expansion on Windows. - - .. versionchanged:: 8.0 - When taking arguments from ``sys.argv`` on Windows, glob - patterns, user dir, and env vars are expanded. - - .. versionchanged:: 3.0 - Added the ``standalone_mode`` parameter. - """ - if args is None: - args = sys.argv[1:] - - if os.name == "nt" and windows_expand_args: - args = _expand_args(args) - else: - args = list(args) - - if prog_name is None: - prog_name = _detect_program_name() - - # Process shell completion requests and exit early. - self._main_shell_completion(extra, prog_name, complete_var) - - try: - try: - with self.make_context(prog_name, args, **extra) as ctx: - rv = self.invoke(ctx) - if not standalone_mode: - return rv - # it's not safe to `ctx.exit(rv)` here! - # note that `rv` may actually contain data like "1" which - # has obvious effects - # more subtle case: `rv=[None, None]` can come out of - # chained commands which all returned `None` -- so it's not - # even always obvious that `rv` indicates success/failure - # by its truthiness/falsiness - ctx.exit() - except (EOFError, KeyboardInterrupt) as e: - echo(file=sys.stderr) - raise Abort() from e - except ClickException as e: - if not standalone_mode: - raise - e.show() - sys.exit(e.exit_code) - except OSError as e: - if e.errno == errno.EPIPE: - sys.stdout = t.cast(t.TextIO, PacifyFlushWrapper(sys.stdout)) - sys.stderr = t.cast(t.TextIO, PacifyFlushWrapper(sys.stderr)) - sys.exit(1) - else: - raise - except Exit as e: - if standalone_mode: - sys.exit(e.exit_code) - else: - # in non-standalone mode, return the exit code - # note that this is only reached if `self.invoke` above raises - # an Exit explicitly -- thus bypassing the check there which - # would return its result - # the results of non-standalone execution may therefore be - # somewhat ambiguous: if there are codepaths which lead to - # `ctx.exit(1)` and to `return 1`, the caller won't be able to - # tell the difference between the two - return e.exit_code - except Abort: - if not standalone_mode: - raise - echo(_("Aborted!"), file=sys.stderr) - sys.exit(1) - - def _main_shell_completion( - self, - ctx_args: t.MutableMapping[str, t.Any], - prog_name: str, - complete_var: t.Optional[str] = None, - ) -> None: - """Check if the shell is asking for tab completion, process - that, then exit early. Called from :meth:`main` before the - program is invoked. - - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. Defaults to - ``_{PROG_NAME}_COMPLETE``. - - .. versionchanged:: 8.2.0 - Dots (``.``) in ``prog_name`` are replaced with underscores (``_``). - """ - if complete_var is None: - complete_name = prog_name.replace("-", "_").replace(".", "_") - complete_var = f"_{complete_name}_COMPLETE".upper() - - instruction = os.environ.get(complete_var) - - if not instruction: - return - - from .shell_completion import shell_complete - - rv = shell_complete(self, ctx_args, prog_name, complete_var, instruction) - sys.exit(rv) - - def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any: - """Alias for :meth:`main`.""" - return self.main(*args, **kwargs) - - -class Command(BaseCommand): - """Commands are the basic building block of command line interfaces in - Click. A basic command handles command line parsing and might dispatch - more parsing to commands nested below it. - - :param name: the name of the command to use unless a group overrides it. - :param context_settings: an optional dictionary with defaults that are - passed to the context object. - :param callback: the callback to invoke. This is optional. - :param params: the parameters to register with this command. This can - be either :class:`Option` or :class:`Argument` objects. - :param help: the help string to use for this command. - :param epilog: like the help string but it's printed at the end of the - help page after everything else. - :param short_help: the short help to use for this command. This is - shown on the command listing of the parent command. - :param add_help_option: by default each command registers a ``--help`` - option. This can be disabled by this parameter. - :param no_args_is_help: this controls what happens if no arguments are - provided. This option is disabled by default. - If enabled this will add ``--help`` as argument - if no arguments are passed - :param hidden: hide this command from help outputs. - - :param deprecated: issues a message indicating that - the command is deprecated. - - .. versionchanged:: 8.1 - ``help``, ``epilog``, and ``short_help`` are stored unprocessed, - all formatting is done when outputting help text, not at init, - and is done even if not using the ``@command`` decorator. - - .. versionchanged:: 8.0 - Added a ``repr`` showing the command name. - - .. versionchanged:: 7.1 - Added the ``no_args_is_help`` parameter. - - .. versionchanged:: 2.0 - Added the ``context_settings`` parameter. - """ - - def __init__( - self, - name: t.Optional[str], - context_settings: t.Optional[t.MutableMapping[str, t.Any]] = None, - callback: t.Optional[t.Callable[..., t.Any]] = None, - params: t.Optional[t.List["Parameter"]] = None, - help: t.Optional[str] = None, - epilog: t.Optional[str] = None, - short_help: t.Optional[str] = None, - options_metavar: t.Optional[str] = "[OPTIONS]", - add_help_option: bool = True, - no_args_is_help: bool = False, - hidden: bool = False, - deprecated: bool = False, - ) -> None: - super().__init__(name, context_settings) - #: the callback to execute when the command fires. This might be - #: `None` in which case nothing happens. - self.callback = callback - #: the list of parameters for this command in the order they - #: should show up in the help page and execute. Eager parameters - #: will automatically be handled before non eager ones. - self.params: t.List[Parameter] = params or [] - self.help = help - self.epilog = epilog - self.options_metavar = options_metavar - self.short_help = short_help - self.add_help_option = add_help_option - self._help_option: t.Optional[HelpOption] = None - self.no_args_is_help = no_args_is_help - self.hidden = hidden - self.deprecated = deprecated - - def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict(ctx) - info_dict.update( - params=[param.to_info_dict() for param in self.get_params(ctx)], - help=self.help, - epilog=self.epilog, - short_help=self.short_help, - hidden=self.hidden, - deprecated=self.deprecated, - ) - return info_dict - - def get_usage(self, ctx: Context) -> str: - """Formats the usage line into a string and returns it. - - Calls :meth:`format_usage` internally. - """ - formatter = ctx.make_formatter() - self.format_usage(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_params(self, ctx: Context) -> t.List["Parameter"]: - rv = self.params - help_option = self.get_help_option(ctx) - - if help_option is not None: - rv = [*rv, help_option] - - return rv - - def format_usage(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the usage line into the formatter. - - This is a low-level method called by :meth:`get_usage`. - """ - pieces = self.collect_usage_pieces(ctx) - formatter.write_usage(ctx.command_path, " ".join(pieces)) - - def collect_usage_pieces(self, ctx: Context) -> t.List[str]: - """Returns all the pieces that go into the usage line and returns - it as a list of strings. - """ - rv = [self.options_metavar] if self.options_metavar else [] - - for param in self.get_params(ctx): - rv.extend(param.get_usage_pieces(ctx)) - - return rv - - def get_help_option_names(self, ctx: Context) -> t.List[str]: - """Returns the names for the help option.""" - all_names = set(ctx.help_option_names) - for param in self.params: - all_names.difference_update(param.opts) - all_names.difference_update(param.secondary_opts) - return list(all_names) - - def get_help_option(self, ctx: Context) -> t.Optional["Option"]: - """Returns the help option object. - - Unless ``add_help_option`` is ``False``. - - .. versionchanged:: 8.1.8 - The help option is now cached to avoid creating it multiple times. - """ - help_options = self.get_help_option_names(ctx) - - if not help_options or not self.add_help_option: - return None - - # Cache the help option object in private _help_option attribute to - # avoid creating it multiple times. Not doing this will break the - # callback odering by iter_params_for_processing(), which relies on - # object comparison. - if self._help_option is None: - # Avoid circular import. - from .decorators import HelpOption - - self._help_option = HelpOption(help_options) - - return self._help_option - - def make_parser(self, ctx: Context) -> OptionParser: - """Creates the underlying option parser for this command.""" - parser = OptionParser(ctx) - for param in self.get_params(ctx): - param.add_to_parser(parser, ctx) - return parser - - def get_help(self, ctx: Context) -> str: - """Formats the help into a string and returns it. - - Calls :meth:`format_help` internally. - """ - formatter = ctx.make_formatter() - self.format_help(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - def get_short_help_str(self, limit: int = 45) -> str: - """Gets short help for the command or makes it by shortening the - long help string. - """ - if self.short_help: - text = inspect.cleandoc(self.short_help) - elif self.help: - text = make_default_short_help(self.help, limit) - else: - text = "" - - if self.deprecated: - text = _("(Deprecated) {text}").format(text=text) - - return text.strip() - - def format_help(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the help into the formatter if it exists. - - This is a low-level method called by :meth:`get_help`. - - This calls the following methods: - - - :meth:`format_usage` - - :meth:`format_help_text` - - :meth:`format_options` - - :meth:`format_epilog` - """ - self.format_usage(ctx, formatter) - self.format_help_text(ctx, formatter) - self.format_options(ctx, formatter) - self.format_epilog(ctx, formatter) - - def format_help_text(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the help text to the formatter if it exists.""" - if self.help is not None: - # truncate the help text to the first form feed - text = inspect.cleandoc(self.help).partition("\f")[0] - else: - text = "" - - if self.deprecated: - text = _("(Deprecated) {text}").format(text=text) - - if text: - formatter.write_paragraph() - - with formatter.indentation(): - formatter.write_text(text) - - def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes all the options into the formatter if they exist.""" - opts = [] - for param in self.get_params(ctx): - rv = param.get_help_record(ctx) - if rv is not None: - opts.append(rv) - - if opts: - with formatter.section(_("Options")): - formatter.write_dl(opts) - - def format_epilog(self, ctx: Context, formatter: HelpFormatter) -> None: - """Writes the epilog into the formatter if it exists.""" - if self.epilog: - epilog = inspect.cleandoc(self.epilog) - formatter.write_paragraph() - - with formatter.indentation(): - formatter.write_text(epilog) - - def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: - if not args and self.no_args_is_help and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - parser = self.make_parser(ctx) - opts, args, param_order = parser.parse_args(args=args) - - for param in iter_params_for_processing(param_order, self.get_params(ctx)): - value, args = param.handle_parse_result(ctx, opts, args) - - if args and not ctx.allow_extra_args and not ctx.resilient_parsing: - ctx.fail( - ngettext( - "Got unexpected extra argument ({args})", - "Got unexpected extra arguments ({args})", - len(args), - ).format(args=" ".join(map(str, args))) - ) - - ctx.args = args - ctx._opt_prefixes.update(parser._opt_prefixes) - return args - - def invoke(self, ctx: Context) -> t.Any: - """Given a context, this invokes the attached callback (if it exists) - in the right way. - """ - if self.deprecated: - message = _( - "DeprecationWarning: The command {name!r} is deprecated." - ).format(name=self.name) - echo(style(message, fg="red"), err=True) - - if self.callback is not None: - return ctx.invoke(self.callback, **ctx.params) - - def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: - """Return a list of completions for the incomplete value. Looks - at the names of options and chained multi-commands. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - results: t.List[CompletionItem] = [] - - if incomplete and not incomplete[0].isalnum(): - for param in self.get_params(ctx): - if ( - not isinstance(param, Option) - or param.hidden - or ( - not param.multiple - and ctx.get_parameter_source(param.name) # type: ignore - is ParameterSource.COMMANDLINE - ) - ): - continue - - results.extend( - CompletionItem(name, help=param.help) - for name in [*param.opts, *param.secondary_opts] - if name.startswith(incomplete) - ) - - results.extend(super().shell_complete(ctx, incomplete)) - return results - - -class MultiCommand(Command): - """A multi command is the basic implementation of a command that - dispatches to subcommands. The most common version is the - :class:`Group`. - - :param invoke_without_command: this controls how the multi command itself - is invoked. By default it's only invoked - if a subcommand is provided. - :param no_args_is_help: this controls what happens if no arguments are - provided. This option is enabled by default if - `invoke_without_command` is disabled or disabled - if it's enabled. If enabled this will add - ``--help`` as argument if no arguments are - passed. - :param subcommand_metavar: the string that is used in the documentation - to indicate the subcommand place. - :param chain: if this is set to `True` chaining of multiple subcommands - is enabled. This restricts the form of commands in that - they cannot have optional arguments but it allows - multiple commands to be chained together. - :param result_callback: The result callback to attach to this multi - command. This can be set or changed later with the - :meth:`result_callback` decorator. - :param attrs: Other command arguments described in :class:`Command`. - """ - - allow_extra_args = True - allow_interspersed_args = False - - def __init__( - self, - name: t.Optional[str] = None, - invoke_without_command: bool = False, - no_args_is_help: t.Optional[bool] = None, - subcommand_metavar: t.Optional[str] = None, - chain: bool = False, - result_callback: t.Optional[t.Callable[..., t.Any]] = None, - **attrs: t.Any, - ) -> None: - super().__init__(name, **attrs) - - if no_args_is_help is None: - no_args_is_help = not invoke_without_command - - self.no_args_is_help = no_args_is_help - self.invoke_without_command = invoke_without_command - - if subcommand_metavar is None: - if chain: - subcommand_metavar = "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..." - else: - subcommand_metavar = "COMMAND [ARGS]..." - - self.subcommand_metavar = subcommand_metavar - self.chain = chain - # The result callback that is stored. This can be set or - # overridden with the :func:`result_callback` decorator. - self._result_callback = result_callback - - if self.chain: - for param in self.params: - if isinstance(param, Argument) and not param.required: - raise RuntimeError( - "Multi commands in chain mode cannot have" - " optional arguments." - ) - - def to_info_dict(self, ctx: Context) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict(ctx) - commands = {} - - for name in self.list_commands(ctx): - command = self.get_command(ctx, name) - - if command is None: - continue - - sub_ctx = ctx._make_sub_context(command) - - with sub_ctx.scope(cleanup=False): - commands[name] = command.to_info_dict(sub_ctx) - - info_dict.update(commands=commands, chain=self.chain) - return info_dict - - def collect_usage_pieces(self, ctx: Context) -> t.List[str]: - rv = super().collect_usage_pieces(ctx) - rv.append(self.subcommand_metavar) - return rv - - def format_options(self, ctx: Context, formatter: HelpFormatter) -> None: - super().format_options(ctx, formatter) - self.format_commands(ctx, formatter) - - def result_callback(self, replace: bool = False) -> t.Callable[[F], F]: - """Adds a result callback to the command. By default if a - result callback is already registered this will chain them but - this can be disabled with the `replace` parameter. The result - callback is invoked with the return value of the subcommand - (or the list of return values from all subcommands if chaining - is enabled) as well as the parameters as they would be passed - to the main callback. - - Example:: - - @click.group() - @click.option('-i', '--input', default=23) - def cli(input): - return 42 - - @cli.result_callback() - def process_result(result, input): - return result + input - - :param replace: if set to `True` an already existing result - callback will be removed. - - .. versionchanged:: 8.0 - Renamed from ``resultcallback``. - - .. versionadded:: 3.0 - """ - - def decorator(f: F) -> F: - old_callback = self._result_callback - - if old_callback is None or replace: - self._result_callback = f - return f - - def function(__value, *args, **kwargs): # type: ignore - inner = old_callback(__value, *args, **kwargs) - return f(inner, *args, **kwargs) - - self._result_callback = rv = update_wrapper(t.cast(F, function), f) - return rv # type: ignore[return-value] - - return decorator - - def format_commands(self, ctx: Context, formatter: HelpFormatter) -> None: - """Extra format methods for multi methods that adds all the commands - after the options. - """ - commands = [] - for subcommand in self.list_commands(ctx): - cmd = self.get_command(ctx, subcommand) - # What is this, the tool lied about a command. Ignore it - if cmd is None: - continue - if cmd.hidden: - continue - - commands.append((subcommand, cmd)) - - # allow for 3 times the default spacing - if len(commands): - limit = formatter.width - 6 - max(len(cmd[0]) for cmd in commands) - - rows = [] - for subcommand, cmd in commands: - help = cmd.get_short_help_str(limit) - rows.append((subcommand, help)) - - if rows: - with formatter.section(_("Commands")): - formatter.write_dl(rows) - - def parse_args(self, ctx: Context, args: t.List[str]) -> t.List[str]: - if not args and self.no_args_is_help and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - rest = super().parse_args(ctx, args) - - if self.chain: - ctx.protected_args = rest - ctx.args = [] - elif rest: - ctx.protected_args, ctx.args = rest[:1], rest[1:] - - return ctx.args - - def invoke(self, ctx: Context) -> t.Any: - def _process_result(value: t.Any) -> t.Any: - if self._result_callback is not None: - value = ctx.invoke(self._result_callback, value, **ctx.params) - return value - - if not ctx.protected_args: - if self.invoke_without_command: - # No subcommand was invoked, so the result callback is - # invoked with the group return value for regular - # groups, or an empty list for chained groups. - with ctx: - rv = super().invoke(ctx) - return _process_result([] if self.chain else rv) - ctx.fail(_("Missing command.")) - - # Fetch args back out - args = [*ctx.protected_args, *ctx.args] - ctx.args = [] - ctx.protected_args = [] - - # If we're not in chain mode, we only allow the invocation of a - # single command but we also inform the current context about the - # name of the command to invoke. - if not self.chain: - # Make sure the context is entered so we do not clean up - # resources until the result processor has worked. - with ctx: - cmd_name, cmd, args = self.resolve_command(ctx, args) - assert cmd is not None - ctx.invoked_subcommand = cmd_name - super().invoke(ctx) - sub_ctx = cmd.make_context(cmd_name, args, parent=ctx) - with sub_ctx: - return _process_result(sub_ctx.command.invoke(sub_ctx)) - - # In chain mode we create the contexts step by step, but after the - # base command has been invoked. Because at that point we do not - # know the subcommands yet, the invoked subcommand attribute is - # set to ``*`` to inform the command that subcommands are executed - # but nothing else. - with ctx: - ctx.invoked_subcommand = "*" if args else None - super().invoke(ctx) - - # Otherwise we make every single context and invoke them in a - # chain. In that case the return value to the result processor - # is the list of all invoked subcommand's results. - contexts = [] - while args: - cmd_name, cmd, args = self.resolve_command(ctx, args) - assert cmd is not None - sub_ctx = cmd.make_context( - cmd_name, - args, - parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - ) - contexts.append(sub_ctx) - args, sub_ctx.args = sub_ctx.args, [] - - rv = [] - for sub_ctx in contexts: - with sub_ctx: - rv.append(sub_ctx.command.invoke(sub_ctx)) - return _process_result(rv) - - def resolve_command( - self, ctx: Context, args: t.List[str] - ) -> t.Tuple[t.Optional[str], t.Optional[Command], t.List[str]]: - cmd_name = make_str(args[0]) - original_cmd_name = cmd_name - - # Get the command - cmd = self.get_command(ctx, cmd_name) - - # If we can't find the command but there is a normalization - # function available, we try with that one. - if cmd is None and ctx.token_normalize_func is not None: - cmd_name = ctx.token_normalize_func(cmd_name) - cmd = self.get_command(ctx, cmd_name) - - # If we don't find the command we want to show an error message - # to the user that it was not provided. However, there is - # something else we should do: if the first argument looks like - # an option we want to kick off parsing again for arguments to - # resolve things like --help which now should go to the main - # place. - if cmd is None and not ctx.resilient_parsing: - if split_opt(cmd_name)[0]: - self.parse_args(ctx, ctx.args) - ctx.fail(_("No such command {name!r}.").format(name=original_cmd_name)) - return cmd_name if cmd else None, cmd, args[1:] - - def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: - """Given a context and a command name, this returns a - :class:`Command` object if it exists or returns `None`. - """ - raise NotImplementedError - - def list_commands(self, ctx: Context) -> t.List[str]: - """Returns a list of subcommand names in the order they should - appear. - """ - return [] - - def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: - """Return a list of completions for the incomplete value. Looks - at the names of options, subcommands, and chained - multi-commands. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - results = [ - CompletionItem(name, help=command.get_short_help_str()) - for name, command in _complete_visible_commands(ctx, incomplete) - ] - results.extend(super().shell_complete(ctx, incomplete)) - return results - - -class Group(MultiCommand): - """A group allows a command to have subcommands attached. This is - the most common way to implement nesting in Click. - - :param name: The name of the group command. - :param commands: A dict mapping names to :class:`Command` objects. - Can also be a list of :class:`Command`, which will use - :attr:`Command.name` to create the dict. - :param attrs: Other command arguments described in - :class:`MultiCommand`, :class:`Command`, and - :class:`BaseCommand`. - - .. versionchanged:: 8.0 - The ``commands`` argument can be a list of command objects. - """ - - #: If set, this is used by the group's :meth:`command` decorator - #: as the default :class:`Command` class. This is useful to make all - #: subcommands use a custom command class. - #: - #: .. versionadded:: 8.0 - command_class: t.Optional[t.Type[Command]] = None - - #: If set, this is used by the group's :meth:`group` decorator - #: as the default :class:`Group` class. This is useful to make all - #: subgroups use a custom group class. - #: - #: If set to the special value :class:`type` (literally - #: ``group_class = type``), this group's class will be used as the - #: default class. This makes a custom group class continue to make - #: custom groups. - #: - #: .. versionadded:: 8.0 - group_class: t.Optional[t.Union[t.Type["Group"], t.Type[type]]] = None - # Literal[type] isn't valid, so use Type[type] - - def __init__( - self, - name: t.Optional[str] = None, - commands: t.Optional[ - t.Union[t.MutableMapping[str, Command], t.Sequence[Command]] - ] = None, - **attrs: t.Any, - ) -> None: - super().__init__(name, **attrs) - - if commands is None: - commands = {} - elif isinstance(commands, abc.Sequence): - commands = {c.name: c for c in commands if c.name is not None} - - #: The registered subcommands by their exported names. - self.commands: t.MutableMapping[str, Command] = commands - - def add_command(self, cmd: Command, name: t.Optional[str] = None) -> None: - """Registers another :class:`Command` with this group. If the name - is not provided, the name of the command is used. - """ - name = name or cmd.name - if name is None: - raise TypeError("Command has no name.") - _check_multicommand(self, name, cmd, register=True) - self.commands[name] = cmd - - @t.overload - def command(self, __func: t.Callable[..., t.Any]) -> Command: ... - - @t.overload - def command( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], Command]: ... - - def command( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], Command], Command]: - """A shortcut decorator for declaring and attaching a command to - the group. This takes the same arguments as :func:`command` and - immediately registers the created command with this group by - calling :meth:`add_command`. - - To customize the command class used, set the - :attr:`command_class` attribute. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - - .. versionchanged:: 8.0 - Added the :attr:`command_class` attribute. - """ - from .decorators import command - - func: t.Optional[t.Callable[..., t.Any]] = None - - if args and callable(args[0]): - assert ( - len(args) == 1 and not kwargs - ), "Use 'command(**kwargs)(callable)' to provide arguments." - (func,) = args - args = () - - if self.command_class and kwargs.get("cls") is None: - kwargs["cls"] = self.command_class - - def decorator(f: t.Callable[..., t.Any]) -> Command: - cmd: Command = command(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - if func is not None: - return decorator(func) - - return decorator - - @t.overload - def group(self, __func: t.Callable[..., t.Any]) -> "Group": ... - - @t.overload - def group( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Callable[[t.Callable[..., t.Any]], "Group"]: ... - - def group( - self, *args: t.Any, **kwargs: t.Any - ) -> t.Union[t.Callable[[t.Callable[..., t.Any]], "Group"], "Group"]: - """A shortcut decorator for declaring and attaching a group to - the group. This takes the same arguments as :func:`group` and - immediately registers the created group with this group by - calling :meth:`add_command`. - - To customize the group class used, set the :attr:`group_class` - attribute. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - - .. versionchanged:: 8.0 - Added the :attr:`group_class` attribute. - """ - from .decorators import group - - func: t.Optional[t.Callable[..., t.Any]] = None - - if args and callable(args[0]): - assert ( - len(args) == 1 and not kwargs - ), "Use 'group(**kwargs)(callable)' to provide arguments." - (func,) = args - args = () - - if self.group_class is not None and kwargs.get("cls") is None: - if self.group_class is type: - kwargs["cls"] = type(self) - else: - kwargs["cls"] = self.group_class - - def decorator(f: t.Callable[..., t.Any]) -> "Group": - cmd: Group = group(*args, **kwargs)(f) - self.add_command(cmd) - return cmd - - if func is not None: - return decorator(func) - - return decorator - - def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: - return self.commands.get(cmd_name) - - def list_commands(self, ctx: Context) -> t.List[str]: - return sorted(self.commands) - - -class CommandCollection(MultiCommand): - """A command collection is a multi command that merges multiple multi - commands together into one. This is a straightforward implementation - that accepts a list of different multi commands as sources and - provides all the commands for each of them. - - See :class:`MultiCommand` and :class:`Command` for the description of - ``name`` and ``attrs``. - """ - - def __init__( - self, - name: t.Optional[str] = None, - sources: t.Optional[t.List[MultiCommand]] = None, - **attrs: t.Any, - ) -> None: - super().__init__(name, **attrs) - #: The list of registered multi commands. - self.sources: t.List[MultiCommand] = sources or [] - - def add_source(self, multi_cmd: MultiCommand) -> None: - """Adds a new multi command to the chain dispatcher.""" - self.sources.append(multi_cmd) - - def get_command(self, ctx: Context, cmd_name: str) -> t.Optional[Command]: - for source in self.sources: - rv = source.get_command(ctx, cmd_name) - - if rv is not None: - if self.chain: - _check_multicommand(self, cmd_name, rv) - - return rv - - return None - - def list_commands(self, ctx: Context) -> t.List[str]: - rv: t.Set[str] = set() - - for source in self.sources: - rv.update(source.list_commands(ctx)) - - return sorted(rv) - - -def _check_iter(value: t.Any) -> t.Iterator[t.Any]: - """Check if the value is iterable but not a string. Raises a type - error, or return an iterator over the value. - """ - if isinstance(value, str): - raise TypeError - - return iter(value) - - -class Parameter: - r"""A parameter to a command comes in two versions: they are either - :class:`Option`\s or :class:`Argument`\s. Other subclasses are currently - not supported by design as some of the internals for parsing are - intentionally not finalized. - - Some settings are supported by both options and arguments. - - :param param_decls: the parameter declarations for this option or - argument. This is a list of flags or argument - names. - :param type: the type that should be used. Either a :class:`ParamType` - or a Python type. The latter is converted into the former - automatically if supported. - :param required: controls if this is optional or not. - :param default: the default value if omitted. This can also be a callable, - in which case it's invoked when the default is needed - without any arguments. - :param callback: A function to further process or validate the value - after type conversion. It is called as ``f(ctx, param, value)`` - and must return the value. It is called for all sources, - including prompts. - :param nargs: the number of arguments to match. If not ``1`` the return - value is a tuple instead of single value. The default for - nargs is ``1`` (except if the type is a tuple, then it's - the arity of the tuple). If ``nargs=-1``, all remaining - parameters are collected. - :param metavar: how the value is represented in the help page. - :param expose_value: if this is `True` then the value is passed onwards - to the command callback and stored on the context, - otherwise it's skipped. - :param is_eager: eager values are processed before non eager ones. This - should not be set for arguments or it will inverse the - order of processing. - :param envvar: a string or list of strings that are environment variables - that should be checked. - :param shell_complete: A function that returns custom shell - completions. Used instead of the param's type completion if - given. Takes ``ctx, param, incomplete`` and must return a list - of :class:`~click.shell_completion.CompletionItem` or a list of - strings. - - .. versionchanged:: 8.0 - ``process_value`` validates required parameters and bounded - ``nargs``, and invokes the parameter callback before returning - the value. This allows the callback to validate prompts. - ``full_process_value`` is removed. - - .. versionchanged:: 8.0 - ``autocompletion`` is renamed to ``shell_complete`` and has new - semantics described above. The old name is deprecated and will - be removed in 8.1, until then it will be wrapped to match the - new requirements. - - .. versionchanged:: 8.0 - For ``multiple=True, nargs>1``, the default must be a list of - tuples. - - .. versionchanged:: 8.0 - Setting a default is no longer required for ``nargs>1``, it will - default to ``None``. ``multiple=True`` or ``nargs=-1`` will - default to ``()``. - - .. versionchanged:: 7.1 - Empty environment variables are ignored rather than taking the - empty string value. This makes it possible for scripts to clear - variables if they can't unset them. - - .. versionchanged:: 2.0 - Changed signature for parameter callback to also be passed the - parameter. The old callback format will still work, but it will - raise a warning to give you a chance to migrate the code easier. - """ - - param_type_name = "parameter" - - def __init__( - self, - param_decls: t.Optional[t.Sequence[str]] = None, - type: t.Optional[t.Union[types.ParamType, t.Any]] = None, - required: bool = False, - default: t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]] = None, - callback: t.Optional[t.Callable[[Context, "Parameter", t.Any], t.Any]] = None, - nargs: t.Optional[int] = None, - multiple: bool = False, - metavar: t.Optional[str] = None, - expose_value: bool = True, - is_eager: bool = False, - envvar: t.Optional[t.Union[str, t.Sequence[str]]] = None, - shell_complete: t.Optional[ - t.Callable[ - [Context, "Parameter", str], - t.Union[t.List["CompletionItem"], t.List[str]], - ] - ] = None, - ) -> None: - self.name: t.Optional[str] - self.opts: t.List[str] - self.secondary_opts: t.List[str] - self.name, self.opts, self.secondary_opts = self._parse_decls( - param_decls or (), expose_value - ) - self.type: types.ParamType = types.convert_type(type, default) - - # Default nargs to what the type tells us if we have that - # information available. - if nargs is None: - if self.type.is_composite: - nargs = self.type.arity - else: - nargs = 1 - - self.required = required - self.callback = callback - self.nargs = nargs - self.multiple = multiple - self.expose_value = expose_value - self.default = default - self.is_eager = is_eager - self.metavar = metavar - self.envvar = envvar - self._custom_shell_complete = shell_complete - - if __debug__: - if self.type.is_composite and nargs != self.type.arity: - raise ValueError( - f"'nargs' must be {self.type.arity} (or None) for" - f" type {self.type!r}, but it was {nargs}." - ) - - # Skip no default or callable default. - check_default = default if not callable(default) else None - - if check_default is not None: - if multiple: - try: - # Only check the first value against nargs. - check_default = next(_check_iter(check_default), None) - except TypeError: - raise ValueError( - "'default' must be a list when 'multiple' is true." - ) from None - - # Can be None for multiple with empty default. - if nargs != 1 and check_default is not None: - try: - _check_iter(check_default) - except TypeError: - if multiple: - message = ( - "'default' must be a list of lists when 'multiple' is" - " true and 'nargs' != 1." - ) - else: - message = "'default' must be a list when 'nargs' != 1." - - raise ValueError(message) from None - - if nargs > 1 and len(check_default) != nargs: - subject = "item length" if multiple else "length" - raise ValueError( - f"'default' {subject} must match nargs={nargs}." - ) - - def to_info_dict(self) -> t.Dict[str, t.Any]: - """Gather information that could be useful for a tool generating - user-facing documentation. - - Use :meth:`click.Context.to_info_dict` to traverse the entire - CLI structure. - - .. versionadded:: 8.0 - """ - return { - "name": self.name, - "param_type_name": self.param_type_name, - "opts": self.opts, - "secondary_opts": self.secondary_opts, - "type": self.type.to_info_dict(), - "required": self.required, - "nargs": self.nargs, - "multiple": self.multiple, - "default": self.default, - "envvar": self.envvar, - } - - def __repr__(self) -> str: - return f"<{self.__class__.__name__} {self.name}>" - - def _parse_decls( - self, decls: t.Sequence[str], expose_value: bool - ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: - raise NotImplementedError() - - @property - def human_readable_name(self) -> str: - """Returns the human readable name of this parameter. This is the - same as the name for options, but the metavar for arguments. - """ - return self.name # type: ignore - - def make_metavar(self) -> str: - if self.metavar is not None: - return self.metavar - - metavar = self.type.get_metavar(self) - - if metavar is None: - metavar = self.type.name.upper() - - if self.nargs != 1: - metavar += "..." - - return metavar - - @t.overload - def get_default( - self, ctx: Context, call: "te.Literal[True]" = True - ) -> t.Optional[t.Any]: ... - - @t.overload - def get_default( - self, ctx: Context, call: bool = ... - ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... - - def get_default( - self, ctx: Context, call: bool = True - ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: - """Get the default for the parameter. Tries - :meth:`Context.lookup_default` first, then the local default. - - :param ctx: Current context. - :param call: If the default is a callable, call it. Disable to - return the callable instead. - - .. versionchanged:: 8.0.2 - Type casting is no longer performed when getting a default. - - .. versionchanged:: 8.0.1 - Type casting can fail in resilient parsing mode. Invalid - defaults will not prevent showing help text. - - .. versionchanged:: 8.0 - Looks at ``ctx.default_map`` first. - - .. versionchanged:: 8.0 - Added the ``call`` parameter. - """ - value = ctx.lookup_default(self.name, call=False) # type: ignore - - if value is None: - value = self.default - - if call and callable(value): - value = value() - - return value - - def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: - raise NotImplementedError() - - def consume_value( - self, ctx: Context, opts: t.Mapping[str, t.Any] - ) -> t.Tuple[t.Any, ParameterSource]: - value = opts.get(self.name) # type: ignore - source = ParameterSource.COMMANDLINE - - if value is None: - value = self.value_from_envvar(ctx) - source = ParameterSource.ENVIRONMENT - - if value is None: - value = ctx.lookup_default(self.name) # type: ignore - source = ParameterSource.DEFAULT_MAP - - if value is None: - value = self.get_default(ctx) - source = ParameterSource.DEFAULT - - return value, source - - def type_cast_value(self, ctx: Context, value: t.Any) -> t.Any: - """Convert and validate a value against the option's - :attr:`type`, :attr:`multiple`, and :attr:`nargs`. - """ - if value is None: - return () if self.multiple or self.nargs == -1 else None - - def check_iter(value: t.Any) -> t.Iterator[t.Any]: - try: - return _check_iter(value) - except TypeError: - # This should only happen when passing in args manually, - # the parser should construct an iterable when parsing - # the command line. - raise BadParameter( - _("Value must be an iterable."), ctx=ctx, param=self - ) from None - - if self.nargs == 1 or self.type.is_composite: - - def convert(value: t.Any) -> t.Any: - return self.type(value, param=self, ctx=ctx) - - elif self.nargs == -1: - - def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] - return tuple(self.type(x, self, ctx) for x in check_iter(value)) - - else: # nargs > 1 - - def convert(value: t.Any) -> t.Any: # t.Tuple[t.Any, ...] - value = tuple(check_iter(value)) - - if len(value) != self.nargs: - raise BadParameter( - ngettext( - "Takes {nargs} values but 1 was given.", - "Takes {nargs} values but {len} were given.", - len(value), - ).format(nargs=self.nargs, len=len(value)), - ctx=ctx, - param=self, - ) - - return tuple(self.type(x, self, ctx) for x in value) - - if self.multiple: - return tuple(convert(x) for x in check_iter(value)) - - return convert(value) - - def value_is_missing(self, value: t.Any) -> bool: - if value is None: - return True - - if (self.nargs != 1 or self.multiple) and value == (): - return True - - return False - - def process_value(self, ctx: Context, value: t.Any) -> t.Any: - value = self.type_cast_value(ctx, value) - - if self.required and self.value_is_missing(value): - raise MissingParameter(ctx=ctx, param=self) - - if self.callback is not None: - value = self.callback(ctx, self, value) - - return value - - def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: - if self.envvar is None: - return None - - if isinstance(self.envvar, str): - rv = os.environ.get(self.envvar) - - if rv: - return rv - else: - for envvar in self.envvar: - rv = os.environ.get(envvar) - - if rv: - return rv - - return None - - def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: - rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) - - if rv is not None and self.nargs != 1: - rv = self.type.split_envvar_value(rv) - - return rv - - def handle_parse_result( - self, ctx: Context, opts: t.Mapping[str, t.Any], args: t.List[str] - ) -> t.Tuple[t.Any, t.List[str]]: - with augment_usage_errors(ctx, param=self): - value, source = self.consume_value(ctx, opts) - ctx.set_parameter_source(self.name, source) # type: ignore - - try: - value = self.process_value(ctx, value) - except Exception: - if not ctx.resilient_parsing: - raise - - value = None - - if self.expose_value: - ctx.params[self.name] = value # type: ignore - - return value, args - - def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: - pass - - def get_usage_pieces(self, ctx: Context) -> t.List[str]: - return [] - - def get_error_hint(self, ctx: Context) -> str: - """Get a stringified version of the param for use in error messages to - indicate which param caused the error. - """ - hint_list = self.opts or [self.human_readable_name] - return " / ".join(f"'{x}'" for x in hint_list) - - def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]: - """Return a list of completions for the incomplete value. If a - ``shell_complete`` function was given during init, it is used. - Otherwise, the :attr:`type` - :meth:`~click.types.ParamType.shell_complete` function is used. - - :param ctx: Invocation context for this command. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - if self._custom_shell_complete is not None: - results = self._custom_shell_complete(ctx, self, incomplete) - - if results and isinstance(results[0], str): - from click.shell_completion import CompletionItem - - results = [CompletionItem(c) for c in results] - - return t.cast(t.List["CompletionItem"], results) - - return self.type.shell_complete(ctx, self, incomplete) - - -class Option(Parameter): - """Options are usually optional values on the command line and - have some extra features that arguments don't have. - - All other parameters are passed onwards to the parameter constructor. - - :param show_default: Show the default value for this option in its - help text. Values are not shown by default, unless - :attr:`Context.show_default` is ``True``. If this value is a - string, it shows that string in parentheses instead of the - actual value. This is particularly useful for dynamic options. - For single option boolean flags, the default remains hidden if - its value is ``False``. - :param show_envvar: Controls if an environment variable should be - shown on the help page. Normally, environment variables are not - shown. - :param prompt: If set to ``True`` or a non empty string then the - user will be prompted for input. If set to ``True`` the prompt - will be the option name capitalized. - :param confirmation_prompt: Prompt a second time to confirm the - value if it was prompted for. Can be set to a string instead of - ``True`` to customize the message. - :param prompt_required: If set to ``False``, the user will be - prompted for input only when the option was specified as a flag - without a value. - :param hide_input: If this is ``True`` then the input on the prompt - will be hidden from the user. This is useful for password input. - :param is_flag: forces this option to act as a flag. The default is - auto detection. - :param flag_value: which value should be used for this flag if it's - enabled. This is set to a boolean automatically if - the option string contains a slash to mark two options. - :param multiple: if this is set to `True` then the argument is accepted - multiple times and recorded. This is similar to ``nargs`` - in how it works but supports arbitrary number of - arguments. - :param count: this flag makes an option increment an integer. - :param allow_from_autoenv: if this is enabled then the value of this - parameter will be pulled from an environment - variable in case a prefix is defined on the - context. - :param help: the help string. - :param hidden: hide this option from help outputs. - :param attrs: Other command arguments described in :class:`Parameter`. - - .. versionchanged:: 8.1.0 - Help text indentation is cleaned here instead of only in the - ``@option`` decorator. - - .. versionchanged:: 8.1.0 - The ``show_default`` parameter overrides - ``Context.show_default``. - - .. versionchanged:: 8.1.0 - The default of a single option boolean flag is not shown if the - default value is ``False``. - - .. versionchanged:: 8.0.1 - ``type`` is detected from ``flag_value`` if given. - """ - - param_type_name = "option" - - def __init__( - self, - param_decls: t.Optional[t.Sequence[str]] = None, - show_default: t.Union[bool, str, None] = None, - prompt: t.Union[bool, str] = False, - confirmation_prompt: t.Union[bool, str] = False, - prompt_required: bool = True, - hide_input: bool = False, - is_flag: t.Optional[bool] = None, - flag_value: t.Optional[t.Any] = None, - multiple: bool = False, - count: bool = False, - allow_from_autoenv: bool = True, - type: t.Optional[t.Union[types.ParamType, t.Any]] = None, - help: t.Optional[str] = None, - hidden: bool = False, - show_choices: bool = True, - show_envvar: bool = False, - **attrs: t.Any, - ) -> None: - if help: - help = inspect.cleandoc(help) - - default_is_missing = "default" not in attrs - super().__init__(param_decls, type=type, multiple=multiple, **attrs) - - if prompt is True: - if self.name is None: - raise TypeError("'name' is required with 'prompt=True'.") - - prompt_text: t.Optional[str] = self.name.replace("_", " ").capitalize() - elif prompt is False: - prompt_text = None - else: - prompt_text = prompt - - self.prompt = prompt_text - self.confirmation_prompt = confirmation_prompt - self.prompt_required = prompt_required - self.hide_input = hide_input - self.hidden = hidden - - # If prompt is enabled but not required, then the option can be - # used as a flag to indicate using prompt or flag_value. - self._flag_needs_value = self.prompt is not None and not self.prompt_required - - if is_flag is None: - if flag_value is not None: - # Implicitly a flag because flag_value was set. - is_flag = True - elif self._flag_needs_value: - # Not a flag, but when used as a flag it shows a prompt. - is_flag = False - else: - # Implicitly a flag because flag options were given. - is_flag = bool(self.secondary_opts) - elif is_flag is False and not self._flag_needs_value: - # Not a flag, and prompt is not enabled, can be used as a - # flag if flag_value is set. - self._flag_needs_value = flag_value is not None - - self.default: t.Union[t.Any, t.Callable[[], t.Any]] - - if is_flag and default_is_missing and not self.required: - if multiple: - self.default = () - else: - self.default = False - - if flag_value is None: - flag_value = not self.default - - self.type: types.ParamType - if is_flag and type is None: - # Re-guess the type from the flag value instead of the - # default. - self.type = types.convert_type(None, flag_value) - - self.is_flag: bool = is_flag - self.is_bool_flag: bool = is_flag and isinstance(self.type, types.BoolParamType) - self.flag_value: t.Any = flag_value - - # Counting - self.count = count - if count: - if type is None: - self.type = types.IntRange(min=0) - if default_is_missing: - self.default = 0 - - self.allow_from_autoenv = allow_from_autoenv - self.help = help - self.show_default = show_default - self.show_choices = show_choices - self.show_envvar = show_envvar - - if __debug__: - if self.nargs == -1: - raise TypeError("nargs=-1 is not supported for options.") - - if self.prompt and self.is_flag and not self.is_bool_flag: - raise TypeError("'prompt' is not valid for non-boolean flag.") - - if not self.is_bool_flag and self.secondary_opts: - raise TypeError("Secondary flag is not valid for non-boolean flag.") - - if self.is_bool_flag and self.hide_input and self.prompt is not None: - raise TypeError( - "'prompt' with 'hide_input' is not valid for boolean flag." - ) - - if self.count: - if self.multiple: - raise TypeError("'count' is not valid with 'multiple'.") - - if self.is_flag: - raise TypeError("'count' is not valid with 'is_flag'.") - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict.update( - help=self.help, - prompt=self.prompt, - is_flag=self.is_flag, - flag_value=self.flag_value, - count=self.count, - hidden=self.hidden, - ) - return info_dict - - def _parse_decls( - self, decls: t.Sequence[str], expose_value: bool - ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: - opts = [] - secondary_opts = [] - name = None - possible_names = [] - - for decl in decls: - if decl.isidentifier(): - if name is not None: - raise TypeError(f"Name '{name}' defined twice") - name = decl - else: - split_char = ";" if decl[:1] == "/" else "/" - if split_char in decl: - first, second = decl.split(split_char, 1) - first = first.rstrip() - if first: - possible_names.append(split_opt(first)) - opts.append(first) - second = second.lstrip() - if second: - secondary_opts.append(second.lstrip()) - if first == second: - raise ValueError( - f"Boolean option {decl!r} cannot use the" - " same flag for true/false." - ) - else: - possible_names.append(split_opt(decl)) - opts.append(decl) - - if name is None and possible_names: - possible_names.sort(key=lambda x: -len(x[0])) # group long options first - name = possible_names[0][1].replace("-", "_").lower() - if not name.isidentifier(): - name = None - - if name is None: - if not expose_value: - return None, opts, secondary_opts - raise TypeError( - f"Could not determine name for option with declarations {decls!r}" - ) - - if not opts and not secondary_opts: - raise TypeError( - f"No options defined but a name was passed ({name})." - " Did you mean to declare an argument instead? Did" - f" you mean to pass '--{name}'?" - ) - - return name, opts, secondary_opts - - def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: - if self.multiple: - action = "append" - elif self.count: - action = "count" - else: - action = "store" - - if self.is_flag: - action = f"{action}_const" - - if self.is_bool_flag and self.secondary_opts: - parser.add_option( - obj=self, opts=self.opts, dest=self.name, action=action, const=True - ) - parser.add_option( - obj=self, - opts=self.secondary_opts, - dest=self.name, - action=action, - const=False, - ) - else: - parser.add_option( - obj=self, - opts=self.opts, - dest=self.name, - action=action, - const=self.flag_value, - ) - else: - parser.add_option( - obj=self, - opts=self.opts, - dest=self.name, - action=action, - nargs=self.nargs, - ) - - def get_help_record(self, ctx: Context) -> t.Optional[t.Tuple[str, str]]: - if self.hidden: - return None - - any_prefix_is_slash = False - - def _write_opts(opts: t.Sequence[str]) -> str: - nonlocal any_prefix_is_slash - - rv, any_slashes = join_options(opts) - - if any_slashes: - any_prefix_is_slash = True - - if not self.is_flag and not self.count: - rv += f" {self.make_metavar()}" - - return rv - - rv = [_write_opts(self.opts)] - - if self.secondary_opts: - rv.append(_write_opts(self.secondary_opts)) - - help = self.help or "" - extra = [] - - if self.show_envvar: - envvar = self.envvar - - if envvar is None: - if ( - self.allow_from_autoenv - and ctx.auto_envvar_prefix is not None - and self.name is not None - ): - envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" - - if envvar is not None: - var_str = ( - envvar - if isinstance(envvar, str) - else ", ".join(str(d) for d in envvar) - ) - extra.append(_("env var: {var}").format(var=var_str)) - - # Temporarily enable resilient parsing to avoid type casting - # failing for the default. Might be possible to extend this to - # help formatting in general. - resilient = ctx.resilient_parsing - ctx.resilient_parsing = True - - try: - default_value = self.get_default(ctx, call=False) - finally: - ctx.resilient_parsing = resilient - - show_default = False - show_default_is_str = False - - if self.show_default is not None: - if isinstance(self.show_default, str): - show_default_is_str = show_default = True - else: - show_default = self.show_default - elif ctx.show_default is not None: - show_default = ctx.show_default - - if show_default_is_str or (show_default and (default_value is not None)): - if show_default_is_str: - default_string = f"({self.show_default})" - elif isinstance(default_value, (list, tuple)): - default_string = ", ".join(str(d) for d in default_value) - elif inspect.isfunction(default_value): - default_string = _("(dynamic)") - elif self.is_bool_flag and self.secondary_opts: - # For boolean flags that have distinct True/False opts, - # use the opt without prefix instead of the value. - default_string = split_opt( - (self.opts if default_value else self.secondary_opts)[0] - )[1] - elif self.is_bool_flag and not self.secondary_opts and not default_value: - default_string = "" - elif default_value == "": - default_string = '""' - else: - default_string = str(default_value) - - if default_string: - extra.append(_("default: {default}").format(default=default_string)) - - if ( - isinstance(self.type, types._NumberRangeBase) - # skip count with default range type - and not (self.count and self.type.min == 0 and self.type.max is None) - ): - range_str = self.type._describe_range() - - if range_str: - extra.append(range_str) - - if self.required: - extra.append(_("required")) - - if extra: - extra_str = "; ".join(extra) - help = f"{help} [{extra_str}]" if help else f"[{extra_str}]" - - return ("; " if any_prefix_is_slash else " / ").join(rv), help - - @t.overload - def get_default( - self, ctx: Context, call: "te.Literal[True]" = True - ) -> t.Optional[t.Any]: ... - - @t.overload - def get_default( - self, ctx: Context, call: bool = ... - ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: ... - - def get_default( - self, ctx: Context, call: bool = True - ) -> t.Optional[t.Union[t.Any, t.Callable[[], t.Any]]]: - # If we're a non boolean flag our default is more complex because - # we need to look at all flags in the same group to figure out - # if we're the default one in which case we return the flag - # value as default. - if self.is_flag and not self.is_bool_flag: - for param in ctx.command.params: - if param.name == self.name and param.default: - return t.cast(Option, param).flag_value - - return None - - return super().get_default(ctx, call=call) - - def prompt_for_value(self, ctx: Context) -> t.Any: - """This is an alternative flow that can be activated in the full - value processing if a value does not exist. It will prompt the - user until a valid value exists and then returns the processed - value as result. - """ - assert self.prompt is not None - - # Calculate the default before prompting anything to be stable. - default = self.get_default(ctx) - - # If this is a prompt for a flag we need to handle this - # differently. - if self.is_bool_flag: - return confirm(self.prompt, default) - - return prompt( - self.prompt, - default=default, - type=self.type, - hide_input=self.hide_input, - show_choices=self.show_choices, - confirmation_prompt=self.confirmation_prompt, - value_proc=lambda x: self.process_value(ctx, x), - ) - - def resolve_envvar_value(self, ctx: Context) -> t.Optional[str]: - rv = super().resolve_envvar_value(ctx) - - if rv is not None: - return rv - - if ( - self.allow_from_autoenv - and ctx.auto_envvar_prefix is not None - and self.name is not None - ): - envvar = f"{ctx.auto_envvar_prefix}_{self.name.upper()}" - rv = os.environ.get(envvar) - - if rv: - return rv - - return None - - def value_from_envvar(self, ctx: Context) -> t.Optional[t.Any]: - rv: t.Optional[t.Any] = self.resolve_envvar_value(ctx) - - if rv is None: - return None - - value_depth = (self.nargs != 1) + bool(self.multiple) - - if value_depth > 0: - rv = self.type.split_envvar_value(rv) - - if self.multiple and self.nargs != 1: - rv = batch(rv, self.nargs) - - return rv - - def consume_value( - self, ctx: Context, opts: t.Mapping[str, "Parameter"] - ) -> t.Tuple[t.Any, ParameterSource]: - value, source = super().consume_value(ctx, opts) - - # The parser will emit a sentinel value if the option can be - # given as a flag without a value. This is different from None - # to distinguish from the flag not being given at all. - if value is _flag_needs_value: - if self.prompt is not None and not ctx.resilient_parsing: - value = self.prompt_for_value(ctx) - source = ParameterSource.PROMPT - else: - value = self.flag_value - source = ParameterSource.COMMANDLINE - - elif ( - self.multiple - and value is not None - and any(v is _flag_needs_value for v in value) - ): - value = [self.flag_value if v is _flag_needs_value else v for v in value] - source = ParameterSource.COMMANDLINE - - # The value wasn't set, or used the param's default, prompt if - # prompting is enabled. - elif ( - source in {None, ParameterSource.DEFAULT} - and self.prompt is not None - and (self.required or self.prompt_required) - and not ctx.resilient_parsing - ): - value = self.prompt_for_value(ctx) - source = ParameterSource.PROMPT - - return value, source - - -class Argument(Parameter): - """Arguments are positional parameters to a command. They generally - provide fewer features than options but can have infinite ``nargs`` - and are required by default. - - All parameters are passed onwards to the constructor of :class:`Parameter`. - """ - - param_type_name = "argument" - - def __init__( - self, - param_decls: t.Sequence[str], - required: t.Optional[bool] = None, - **attrs: t.Any, - ) -> None: - if required is None: - if attrs.get("default") is not None: - required = False - else: - required = attrs.get("nargs", 1) > 0 - - if "multiple" in attrs: - raise TypeError("__init__() got an unexpected keyword argument 'multiple'.") - - super().__init__(param_decls, required=required, **attrs) - - if __debug__: - if self.default is not None and self.nargs == -1: - raise TypeError("'default' is not supported for nargs=-1.") - - @property - def human_readable_name(self) -> str: - if self.metavar is not None: - return self.metavar - return self.name.upper() # type: ignore - - def make_metavar(self) -> str: - if self.metavar is not None: - return self.metavar - var = self.type.get_metavar(self) - if not var: - var = self.name.upper() # type: ignore - if not self.required: - var = f"[{var}]" - if self.nargs != 1: - var += "..." - return var - - def _parse_decls( - self, decls: t.Sequence[str], expose_value: bool - ) -> t.Tuple[t.Optional[str], t.List[str], t.List[str]]: - if not decls: - if not expose_value: - return None, [], [] - raise TypeError("Argument is marked as exposed, but does not have a name.") - if len(decls) == 1: - name = arg = decls[0] - name = name.replace("-", "_").lower() - else: - raise TypeError( - "Arguments take exactly one parameter declaration, got" - f" {len(decls)}." - ) - return name, [arg], [] - - def get_usage_pieces(self, ctx: Context) -> t.List[str]: - return [self.make_metavar()] - - def get_error_hint(self, ctx: Context) -> str: - return f"'{self.make_metavar()}'" - - def add_to_parser(self, parser: OptionParser, ctx: Context) -> None: - parser.add_argument(dest=self.name, nargs=self.nargs, obj=self) diff --git a/venv/Lib/site-packages/click/decorators.py b/venv/Lib/site-packages/click/decorators.py deleted file mode 100644 index bcf8906..0000000 --- a/venv/Lib/site-packages/click/decorators.py +++ /dev/null @@ -1,562 +0,0 @@ -import inspect -import types -import typing as t -from functools import update_wrapper -from gettext import gettext as _ - -from .core import Argument -from .core import Command -from .core import Context -from .core import Group -from .core import Option -from .core import Parameter -from .globals import get_current_context -from .utils import echo - -if t.TYPE_CHECKING: - import typing_extensions as te - - P = te.ParamSpec("P") - -R = t.TypeVar("R") -T = t.TypeVar("T") -_AnyCallable = t.Callable[..., t.Any] -FC = t.TypeVar("FC", bound=t.Union[_AnyCallable, Command]) - - -def pass_context(f: "t.Callable[te.Concatenate[Context, P], R]") -> "t.Callable[P, R]": - """Marks a callback as wanting to receive the current context - object as first argument. - """ - - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": - return f(get_current_context(), *args, **kwargs) - - return update_wrapper(new_func, f) - - -def pass_obj(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": - """Similar to :func:`pass_context`, but only pass the object on the - context onwards (:attr:`Context.obj`). This is useful if that object - represents the state of a nested system. - """ - - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": - return f(get_current_context().obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - -def make_pass_decorator( - object_type: t.Type[T], ensure: bool = False -) -> t.Callable[["t.Callable[te.Concatenate[T, P], R]"], "t.Callable[P, R]"]: - """Given an object type this creates a decorator that will work - similar to :func:`pass_obj` but instead of passing the object of the - current context, it will find the innermost context of type - :func:`object_type`. - - This generates a decorator that works roughly like this:: - - from functools import update_wrapper - - def decorator(f): - @pass_context - def new_func(ctx, *args, **kwargs): - obj = ctx.find_object(object_type) - return ctx.invoke(f, obj, *args, **kwargs) - return update_wrapper(new_func, f) - return decorator - - :param object_type: the type of the object to pass. - :param ensure: if set to `True`, a new object will be created and - remembered on the context if it's not there yet. - """ - - def decorator(f: "t.Callable[te.Concatenate[T, P], R]") -> "t.Callable[P, R]": - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> "R": - ctx = get_current_context() - - obj: t.Optional[T] - if ensure: - obj = ctx.ensure_object(object_type) - else: - obj = ctx.find_object(object_type) - - if obj is None: - raise RuntimeError( - "Managed to invoke callback without a context" - f" object of type {object_type.__name__!r}" - " existing." - ) - - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - return decorator - - -def pass_meta_key( - key: str, *, doc_description: t.Optional[str] = None -) -> "t.Callable[[t.Callable[te.Concatenate[t.Any, P], R]], t.Callable[P, R]]": - """Create a decorator that passes a key from - :attr:`click.Context.meta` as the first argument to the decorated - function. - - :param key: Key in ``Context.meta`` to pass. - :param doc_description: Description of the object being passed, - inserted into the decorator's docstring. Defaults to "the 'key' - key from Context.meta". - - .. versionadded:: 8.0 - """ - - def decorator(f: "t.Callable[te.Concatenate[t.Any, P], R]") -> "t.Callable[P, R]": - def new_func(*args: "P.args", **kwargs: "P.kwargs") -> R: - ctx = get_current_context() - obj = ctx.meta[key] - return ctx.invoke(f, obj, *args, **kwargs) - - return update_wrapper(new_func, f) - - if doc_description is None: - doc_description = f"the {key!r} key from :attr:`click.Context.meta`" - - decorator.__doc__ = ( - f"Decorator that passes {doc_description} as the first argument" - " to the decorated function." - ) - return decorator - - -CmdType = t.TypeVar("CmdType", bound=Command) - - -# variant: no call, directly as decorator for a function. -@t.overload -def command(name: _AnyCallable) -> Command: ... - - -# variant: with positional name and with positional or keyword cls argument: -# @command(namearg, CommandCls, ...) or @command(namearg, cls=CommandCls, ...) -@t.overload -def command( - name: t.Optional[str], - cls: t.Type[CmdType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], CmdType]: ... - - -# variant: name omitted, cls _must_ be a keyword argument, @command(cls=CommandCls, ...) -@t.overload -def command( - name: None = None, - *, - cls: t.Type[CmdType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], CmdType]: ... - - -# variant: with optional string name, no cls argument provided. -@t.overload -def command( - name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any -) -> t.Callable[[_AnyCallable], Command]: ... - - -def command( - name: t.Union[t.Optional[str], _AnyCallable] = None, - cls: t.Optional[t.Type[CmdType]] = None, - **attrs: t.Any, -) -> t.Union[Command, t.Callable[[_AnyCallable], t.Union[Command, CmdType]]]: - r"""Creates a new :class:`Command` and uses the decorated function as - callback. This will also automatically attach all decorated - :func:`option`\s and :func:`argument`\s as parameters to the command. - - The name of the command defaults to the name of the function with - underscores replaced by dashes. If you want to change that, you can - pass the intended name as the first argument. - - All keyword arguments are forwarded to the underlying command class. - For the ``params`` argument, any decorated params are appended to - the end of the list. - - Once decorated the function turns into a :class:`Command` instance - that can be invoked as a command line utility or be attached to a - command :class:`Group`. - - :param name: the name of the command. This defaults to the function - name with underscores replaced by dashes. - :param cls: the command class to instantiate. This defaults to - :class:`Command`. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - - .. versionchanged:: 8.1 - The ``params`` argument can be used. Decorated params are - appended to the end of the list. - """ - - func: t.Optional[t.Callable[[_AnyCallable], t.Any]] = None - - if callable(name): - func = name - name = None - assert cls is None, "Use 'command(cls=cls)(callable)' to specify a class." - assert not attrs, "Use 'command(**kwargs)(callable)' to provide arguments." - - if cls is None: - cls = t.cast(t.Type[CmdType], Command) - - def decorator(f: _AnyCallable) -> CmdType: - if isinstance(f, Command): - raise TypeError("Attempted to convert a callback into a command twice.") - - attr_params = attrs.pop("params", None) - params = attr_params if attr_params is not None else [] - - try: - decorator_params = f.__click_params__ # type: ignore - except AttributeError: - pass - else: - del f.__click_params__ # type: ignore - params.extend(reversed(decorator_params)) - - if attrs.get("help") is None: - attrs["help"] = f.__doc__ - - if t.TYPE_CHECKING: - assert cls is not None - assert not callable(name) - - cmd = cls( - name=name or f.__name__.lower().replace("_", "-"), - callback=f, - params=params, - **attrs, - ) - cmd.__doc__ = f.__doc__ - return cmd - - if func is not None: - return decorator(func) - - return decorator - - -GrpType = t.TypeVar("GrpType", bound=Group) - - -# variant: no call, directly as decorator for a function. -@t.overload -def group(name: _AnyCallable) -> Group: ... - - -# variant: with positional name and with positional or keyword cls argument: -# @group(namearg, GroupCls, ...) or @group(namearg, cls=GroupCls, ...) -@t.overload -def group( - name: t.Optional[str], - cls: t.Type[GrpType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], GrpType]: ... - - -# variant: name omitted, cls _must_ be a keyword argument, @group(cmd=GroupCls, ...) -@t.overload -def group( - name: None = None, - *, - cls: t.Type[GrpType], - **attrs: t.Any, -) -> t.Callable[[_AnyCallable], GrpType]: ... - - -# variant: with optional string name, no cls argument provided. -@t.overload -def group( - name: t.Optional[str] = ..., cls: None = None, **attrs: t.Any -) -> t.Callable[[_AnyCallable], Group]: ... - - -def group( - name: t.Union[str, _AnyCallable, None] = None, - cls: t.Optional[t.Type[GrpType]] = None, - **attrs: t.Any, -) -> t.Union[Group, t.Callable[[_AnyCallable], t.Union[Group, GrpType]]]: - """Creates a new :class:`Group` with a function as callback. This - works otherwise the same as :func:`command` just that the `cls` - parameter is set to :class:`Group`. - - .. versionchanged:: 8.1 - This decorator can be applied without parentheses. - """ - if cls is None: - cls = t.cast(t.Type[GrpType], Group) - - if callable(name): - return command(cls=cls, **attrs)(name) - - return command(name, cls, **attrs) - - -def _param_memo(f: t.Callable[..., t.Any], param: Parameter) -> None: - if isinstance(f, Command): - f.params.append(param) - else: - if not hasattr(f, "__click_params__"): - f.__click_params__ = [] # type: ignore - - f.__click_params__.append(param) # type: ignore - - -def argument( - *param_decls: str, cls: t.Optional[t.Type[Argument]] = None, **attrs: t.Any -) -> t.Callable[[FC], FC]: - """Attaches an argument to the command. All positional arguments are - passed as parameter declarations to :class:`Argument`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Argument` instance manually - and attaching it to the :attr:`Command.params` list. - - For the default argument class, refer to :class:`Argument` and - :class:`Parameter` for descriptions of parameters. - - :param cls: the argument class to instantiate. This defaults to - :class:`Argument`. - :param param_decls: Passed as positional arguments to the constructor of - ``cls``. - :param attrs: Passed as keyword arguments to the constructor of ``cls``. - """ - if cls is None: - cls = Argument - - def decorator(f: FC) -> FC: - _param_memo(f, cls(param_decls, **attrs)) - return f - - return decorator - - -def option( - *param_decls: str, cls: t.Optional[t.Type[Option]] = None, **attrs: t.Any -) -> t.Callable[[FC], FC]: - """Attaches an option to the command. All positional arguments are - passed as parameter declarations to :class:`Option`; all keyword - arguments are forwarded unchanged (except ``cls``). - This is equivalent to creating an :class:`Option` instance manually - and attaching it to the :attr:`Command.params` list. - - For the default option class, refer to :class:`Option` and - :class:`Parameter` for descriptions of parameters. - - :param cls: the option class to instantiate. This defaults to - :class:`Option`. - :param param_decls: Passed as positional arguments to the constructor of - ``cls``. - :param attrs: Passed as keyword arguments to the constructor of ``cls``. - """ - if cls is None: - cls = Option - - def decorator(f: FC) -> FC: - _param_memo(f, cls(param_decls, **attrs)) - return f - - return decorator - - -def confirmation_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Add a ``--yes`` option which shows a prompt before continuing if - not passed. If the prompt is declined, the program will exit. - - :param param_decls: One or more option names. Defaults to the single - value ``"--yes"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - - def callback(ctx: Context, param: Parameter, value: bool) -> None: - if not value: - ctx.abort() - - if not param_decls: - param_decls = ("--yes",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("callback", callback) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("prompt", "Do you want to continue?") - kwargs.setdefault("help", "Confirm the action without prompting.") - return option(*param_decls, **kwargs) - - -def password_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Add a ``--password`` option which prompts for a password, hiding - input and asking to enter the value again for confirmation. - - :param param_decls: One or more option names. Defaults to the single - value ``"--password"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - if not param_decls: - param_decls = ("--password",) - - kwargs.setdefault("prompt", True) - kwargs.setdefault("confirmation_prompt", True) - kwargs.setdefault("hide_input", True) - return option(*param_decls, **kwargs) - - -def version_option( - version: t.Optional[str] = None, - *param_decls: str, - package_name: t.Optional[str] = None, - prog_name: t.Optional[str] = None, - message: t.Optional[str] = None, - **kwargs: t.Any, -) -> t.Callable[[FC], FC]: - """Add a ``--version`` option which immediately prints the version - number and exits the program. - - If ``version`` is not provided, Click will try to detect it using - :func:`importlib.metadata.version` to get the version for the - ``package_name``. On Python < 3.8, the ``importlib_metadata`` - backport must be installed. - - If ``package_name`` is not provided, Click will try to detect it by - inspecting the stack frames. This will be used to detect the - version, so it must match the name of the installed package. - - :param version: The version number to show. If not provided, Click - will try to detect it. - :param param_decls: One or more option names. Defaults to the single - value ``"--version"``. - :param package_name: The package name to detect the version from. If - not provided, Click will try to detect it. - :param prog_name: The name of the CLI to show in the message. If not - provided, it will be detected from the command. - :param message: The message to show. The values ``%(prog)s``, - ``%(package)s``, and ``%(version)s`` are available. Defaults to - ``"%(prog)s, version %(version)s"``. - :param kwargs: Extra arguments are passed to :func:`option`. - :raise RuntimeError: ``version`` could not be detected. - - .. versionchanged:: 8.0 - Add the ``package_name`` parameter, and the ``%(package)s`` - value for messages. - - .. versionchanged:: 8.0 - Use :mod:`importlib.metadata` instead of ``pkg_resources``. The - version is detected based on the package name, not the entry - point name. The Python package name must match the installed - package name, or be passed with ``package_name=``. - """ - if message is None: - message = _("%(prog)s, version %(version)s") - - if version is None and package_name is None: - frame = inspect.currentframe() - f_back = frame.f_back if frame is not None else None - f_globals = f_back.f_globals if f_back is not None else None - # break reference cycle - # https://docs.python.org/3/library/inspect.html#the-interpreter-stack - del frame - - if f_globals is not None: - package_name = f_globals.get("__name__") - - if package_name == "__main__": - package_name = f_globals.get("__package__") - - if package_name: - package_name = package_name.partition(".")[0] - - def callback(ctx: Context, param: Parameter, value: bool) -> None: - if not value or ctx.resilient_parsing: - return - - nonlocal prog_name - nonlocal version - - if prog_name is None: - prog_name = ctx.find_root().info_name - - if version is None and package_name is not None: - metadata: t.Optional[types.ModuleType] - - try: - from importlib import metadata - except ImportError: - # Python < 3.8 - import importlib_metadata as metadata # type: ignore - - try: - version = metadata.version(package_name) # type: ignore - except metadata.PackageNotFoundError: # type: ignore - raise RuntimeError( - f"{package_name!r} is not installed. Try passing" - " 'package_name' instead." - ) from None - - if version is None: - raise RuntimeError( - f"Could not determine the version for {package_name!r} automatically." - ) - - echo( - message % {"prog": prog_name, "package": package_name, "version": version}, - color=ctx.color, - ) - ctx.exit() - - if not param_decls: - param_decls = ("--version",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("is_eager", True) - kwargs.setdefault("help", _("Show the version and exit.")) - kwargs["callback"] = callback - return option(*param_decls, **kwargs) - - -class HelpOption(Option): - """Pre-configured ``--help`` option which immediately prints the help page - and exits the program. - """ - - def __init__( - self, - param_decls: t.Optional[t.Sequence[str]] = None, - **kwargs: t.Any, - ) -> None: - if not param_decls: - param_decls = ("--help",) - - kwargs.setdefault("is_flag", True) - kwargs.setdefault("expose_value", False) - kwargs.setdefault("is_eager", True) - kwargs.setdefault("help", _("Show this message and exit.")) - kwargs.setdefault("callback", self.show_help) - - super().__init__(param_decls, **kwargs) - - @staticmethod - def show_help(ctx: Context, param: Parameter, value: bool) -> None: - """Callback that print the help page on ```` and exits.""" - if value and not ctx.resilient_parsing: - echo(ctx.get_help(), color=ctx.color) - ctx.exit() - - -def help_option(*param_decls: str, **kwargs: t.Any) -> t.Callable[[FC], FC]: - """Decorator for the pre-configured ``--help`` option defined above. - - :param param_decls: One or more option names. Defaults to the single - value ``"--help"``. - :param kwargs: Extra arguments are passed to :func:`option`. - """ - kwargs.setdefault("cls", HelpOption) - return option(*param_decls, **kwargs) diff --git a/venv/Lib/site-packages/click/exceptions.py b/venv/Lib/site-packages/click/exceptions.py deleted file mode 100644 index 0b83151..0000000 --- a/venv/Lib/site-packages/click/exceptions.py +++ /dev/null @@ -1,296 +0,0 @@ -import typing as t -from gettext import gettext as _ -from gettext import ngettext - -from ._compat import get_text_stderr -from .globals import resolve_color_default -from .utils import echo -from .utils import format_filename - -if t.TYPE_CHECKING: - from .core import Command - from .core import Context - from .core import Parameter - - -def _join_param_hints( - param_hint: t.Optional[t.Union[t.Sequence[str], str]], -) -> t.Optional[str]: - if param_hint is not None and not isinstance(param_hint, str): - return " / ".join(repr(x) for x in param_hint) - - return param_hint - - -class ClickException(Exception): - """An exception that Click can handle and show to the user.""" - - #: The exit code for this exception. - exit_code = 1 - - def __init__(self, message: str) -> None: - super().__init__(message) - # The context will be removed by the time we print the message, so cache - # the color settings here to be used later on (in `show`) - self.show_color: t.Optional[bool] = resolve_color_default() - self.message = message - - def format_message(self) -> str: - return self.message - - def __str__(self) -> str: - return self.message - - def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: - if file is None: - file = get_text_stderr() - - echo( - _("Error: {message}").format(message=self.format_message()), - file=file, - color=self.show_color, - ) - - -class UsageError(ClickException): - """An internal exception that signals a usage error. This typically - aborts any further handling. - - :param message: the error message to display. - :param ctx: optionally the context that caused this error. Click will - fill in the context automatically in some situations. - """ - - exit_code = 2 - - def __init__(self, message: str, ctx: t.Optional["Context"] = None) -> None: - super().__init__(message) - self.ctx = ctx - self.cmd: t.Optional[Command] = self.ctx.command if self.ctx else None - - def show(self, file: t.Optional[t.IO[t.Any]] = None) -> None: - if file is None: - file = get_text_stderr() - color = None - hint = "" - if ( - self.ctx is not None - and self.ctx.command.get_help_option(self.ctx) is not None - ): - hint = _("Try '{command} {option}' for help.").format( - command=self.ctx.command_path, option=self.ctx.help_option_names[0] - ) - hint = f"{hint}\n" - if self.ctx is not None: - color = self.ctx.color - echo(f"{self.ctx.get_usage()}\n{hint}", file=file, color=color) - echo( - _("Error: {message}").format(message=self.format_message()), - file=file, - color=color, - ) - - -class BadParameter(UsageError): - """An exception that formats out a standardized error message for a - bad parameter. This is useful when thrown from a callback or type as - Click will attach contextual information to it (for instance, which - parameter it is). - - .. versionadded:: 2.0 - - :param param: the parameter object that caused this error. This can - be left out, and Click will attach this info itself - if possible. - :param param_hint: a string that shows up as parameter name. This - can be used as alternative to `param` in cases - where custom validation should happen. If it is - a string it's used as such, if it's a list then - each item is quoted and separated. - """ - - def __init__( - self, - message: str, - ctx: t.Optional["Context"] = None, - param: t.Optional["Parameter"] = None, - param_hint: t.Optional[str] = None, - ) -> None: - super().__init__(message, ctx) - self.param = param - self.param_hint = param_hint - - def format_message(self) -> str: - if self.param_hint is not None: - param_hint = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) # type: ignore - else: - return _("Invalid value: {message}").format(message=self.message) - - return _("Invalid value for {param_hint}: {message}").format( - param_hint=_join_param_hints(param_hint), message=self.message - ) - - -class MissingParameter(BadParameter): - """Raised if click required an option or argument but it was not - provided when invoking the script. - - .. versionadded:: 4.0 - - :param param_type: a string that indicates the type of the parameter. - The default is to inherit the parameter type from - the given `param`. Valid values are ``'parameter'``, - ``'option'`` or ``'argument'``. - """ - - def __init__( - self, - message: t.Optional[str] = None, - ctx: t.Optional["Context"] = None, - param: t.Optional["Parameter"] = None, - param_hint: t.Optional[str] = None, - param_type: t.Optional[str] = None, - ) -> None: - super().__init__(message or "", ctx, param, param_hint) - self.param_type = param_type - - def format_message(self) -> str: - if self.param_hint is not None: - param_hint: t.Optional[str] = self.param_hint - elif self.param is not None: - param_hint = self.param.get_error_hint(self.ctx) # type: ignore - else: - param_hint = None - - param_hint = _join_param_hints(param_hint) - param_hint = f" {param_hint}" if param_hint else "" - - param_type = self.param_type - if param_type is None and self.param is not None: - param_type = self.param.param_type_name - - msg = self.message - if self.param is not None: - msg_extra = self.param.type.get_missing_message(self.param) - if msg_extra: - if msg: - msg += f". {msg_extra}" - else: - msg = msg_extra - - msg = f" {msg}" if msg else "" - - # Translate param_type for known types. - if param_type == "argument": - missing = _("Missing argument") - elif param_type == "option": - missing = _("Missing option") - elif param_type == "parameter": - missing = _("Missing parameter") - else: - missing = _("Missing {param_type}").format(param_type=param_type) - - return f"{missing}{param_hint}.{msg}" - - def __str__(self) -> str: - if not self.message: - param_name = self.param.name if self.param else None - return _("Missing parameter: {param_name}").format(param_name=param_name) - else: - return self.message - - -class NoSuchOption(UsageError): - """Raised if click attempted to handle an option that does not - exist. - - .. versionadded:: 4.0 - """ - - def __init__( - self, - option_name: str, - message: t.Optional[str] = None, - possibilities: t.Optional[t.Sequence[str]] = None, - ctx: t.Optional["Context"] = None, - ) -> None: - if message is None: - message = _("No such option: {name}").format(name=option_name) - - super().__init__(message, ctx) - self.option_name = option_name - self.possibilities = possibilities - - def format_message(self) -> str: - if not self.possibilities: - return self.message - - possibility_str = ", ".join(sorted(self.possibilities)) - suggest = ngettext( - "Did you mean {possibility}?", - "(Possible options: {possibilities})", - len(self.possibilities), - ).format(possibility=possibility_str, possibilities=possibility_str) - return f"{self.message} {suggest}" - - -class BadOptionUsage(UsageError): - """Raised if an option is generally supplied but the use of the option - was incorrect. This is for instance raised if the number of arguments - for an option is not correct. - - .. versionadded:: 4.0 - - :param option_name: the name of the option being used incorrectly. - """ - - def __init__( - self, option_name: str, message: str, ctx: t.Optional["Context"] = None - ) -> None: - super().__init__(message, ctx) - self.option_name = option_name - - -class BadArgumentUsage(UsageError): - """Raised if an argument is generally supplied but the use of the argument - was incorrect. This is for instance raised if the number of values - for an argument is not correct. - - .. versionadded:: 6.0 - """ - - -class FileError(ClickException): - """Raised if a file cannot be opened.""" - - def __init__(self, filename: str, hint: t.Optional[str] = None) -> None: - if hint is None: - hint = _("unknown error") - - super().__init__(hint) - self.ui_filename: str = format_filename(filename) - self.filename = filename - - def format_message(self) -> str: - return _("Could not open file {filename!r}: {message}").format( - filename=self.ui_filename, message=self.message - ) - - -class Abort(RuntimeError): - """An internal signalling exception that signals Click to abort.""" - - -class Exit(RuntimeError): - """An exception that indicates that the application should exit with some - status code. - - :param code: the status code to exit with. - """ - - __slots__ = ("exit_code",) - - def __init__(self, code: int = 0) -> None: - self.exit_code: int = code diff --git a/venv/Lib/site-packages/click/formatting.py b/venv/Lib/site-packages/click/formatting.py deleted file mode 100644 index ddd2a2f..0000000 --- a/venv/Lib/site-packages/click/formatting.py +++ /dev/null @@ -1,301 +0,0 @@ -import typing as t -from contextlib import contextmanager -from gettext import gettext as _ - -from ._compat import term_len -from .parser import split_opt - -# Can force a width. This is used by the test system -FORCED_WIDTH: t.Optional[int] = None - - -def measure_table(rows: t.Iterable[t.Tuple[str, str]]) -> t.Tuple[int, ...]: - widths: t.Dict[int, int] = {} - - for row in rows: - for idx, col in enumerate(row): - widths[idx] = max(widths.get(idx, 0), term_len(col)) - - return tuple(y for x, y in sorted(widths.items())) - - -def iter_rows( - rows: t.Iterable[t.Tuple[str, str]], col_count: int -) -> t.Iterator[t.Tuple[str, ...]]: - for row in rows: - yield row + ("",) * (col_count - len(row)) - - -def wrap_text( - text: str, - width: int = 78, - initial_indent: str = "", - subsequent_indent: str = "", - preserve_paragraphs: bool = False, -) -> str: - """A helper function that intelligently wraps text. By default, it - assumes that it operates on a single paragraph of text but if the - `preserve_paragraphs` parameter is provided it will intelligently - handle paragraphs (defined by two empty lines). - - If paragraphs are handled, a paragraph can be prefixed with an empty - line containing the ``\\b`` character (``\\x08``) to indicate that - no rewrapping should happen in that block. - - :param text: the text that should be rewrapped. - :param width: the maximum width for the text. - :param initial_indent: the initial indent that should be placed on the - first line as a string. - :param subsequent_indent: the indent string that should be placed on - each consecutive line. - :param preserve_paragraphs: if this flag is set then the wrapping will - intelligently handle paragraphs. - """ - from ._textwrap import TextWrapper - - text = text.expandtabs() - wrapper = TextWrapper( - width, - initial_indent=initial_indent, - subsequent_indent=subsequent_indent, - replace_whitespace=False, - ) - if not preserve_paragraphs: - return wrapper.fill(text) - - p: t.List[t.Tuple[int, bool, str]] = [] - buf: t.List[str] = [] - indent = None - - def _flush_par() -> None: - if not buf: - return - if buf[0].strip() == "\b": - p.append((indent or 0, True, "\n".join(buf[1:]))) - else: - p.append((indent or 0, False, " ".join(buf))) - del buf[:] - - for line in text.splitlines(): - if not line: - _flush_par() - indent = None - else: - if indent is None: - orig_len = term_len(line) - line = line.lstrip() - indent = orig_len - term_len(line) - buf.append(line) - _flush_par() - - rv = [] - for indent, raw, text in p: - with wrapper.extra_indent(" " * indent): - if raw: - rv.append(wrapper.indent_only(text)) - else: - rv.append(wrapper.fill(text)) - - return "\n\n".join(rv) - - -class HelpFormatter: - """This class helps with formatting text-based help pages. It's - usually just needed for very special internal cases, but it's also - exposed so that developers can write their own fancy outputs. - - At present, it always writes into memory. - - :param indent_increment: the additional increment for each level. - :param width: the width for the text. This defaults to the terminal - width clamped to a maximum of 78. - """ - - def __init__( - self, - indent_increment: int = 2, - width: t.Optional[int] = None, - max_width: t.Optional[int] = None, - ) -> None: - import shutil - - self.indent_increment = indent_increment - if max_width is None: - max_width = 80 - if width is None: - width = FORCED_WIDTH - if width is None: - width = max(min(shutil.get_terminal_size().columns, max_width) - 2, 50) - self.width = width - self.current_indent = 0 - self.buffer: t.List[str] = [] - - def write(self, string: str) -> None: - """Writes a unicode string into the internal buffer.""" - self.buffer.append(string) - - def indent(self) -> None: - """Increases the indentation.""" - self.current_indent += self.indent_increment - - def dedent(self) -> None: - """Decreases the indentation.""" - self.current_indent -= self.indent_increment - - def write_usage( - self, prog: str, args: str = "", prefix: t.Optional[str] = None - ) -> None: - """Writes a usage line into the buffer. - - :param prog: the program name. - :param args: whitespace separated list of arguments. - :param prefix: The prefix for the first line. Defaults to - ``"Usage: "``. - """ - if prefix is None: - prefix = f"{_('Usage:')} " - - usage_prefix = f"{prefix:>{self.current_indent}}{prog} " - text_width = self.width - self.current_indent - - if text_width >= (term_len(usage_prefix) + 20): - # The arguments will fit to the right of the prefix. - indent = " " * term_len(usage_prefix) - self.write( - wrap_text( - args, - text_width, - initial_indent=usage_prefix, - subsequent_indent=indent, - ) - ) - else: - # The prefix is too long, put the arguments on the next line. - self.write(usage_prefix) - self.write("\n") - indent = " " * (max(self.current_indent, term_len(prefix)) + 4) - self.write( - wrap_text( - args, text_width, initial_indent=indent, subsequent_indent=indent - ) - ) - - self.write("\n") - - def write_heading(self, heading: str) -> None: - """Writes a heading into the buffer.""" - self.write(f"{'':>{self.current_indent}}{heading}:\n") - - def write_paragraph(self) -> None: - """Writes a paragraph into the buffer.""" - if self.buffer: - self.write("\n") - - def write_text(self, text: str) -> None: - """Writes re-indented text into the buffer. This rewraps and - preserves paragraphs. - """ - indent = " " * self.current_indent - self.write( - wrap_text( - text, - self.width, - initial_indent=indent, - subsequent_indent=indent, - preserve_paragraphs=True, - ) - ) - self.write("\n") - - def write_dl( - self, - rows: t.Sequence[t.Tuple[str, str]], - col_max: int = 30, - col_spacing: int = 2, - ) -> None: - """Writes a definition list into the buffer. This is how options - and commands are usually formatted. - - :param rows: a list of two item tuples for the terms and values. - :param col_max: the maximum width of the first column. - :param col_spacing: the number of spaces between the first and - second column. - """ - rows = list(rows) - widths = measure_table(rows) - if len(widths) != 2: - raise TypeError("Expected two columns for definition list") - - first_col = min(widths[0], col_max) + col_spacing - - for first, second in iter_rows(rows, len(widths)): - self.write(f"{'':>{self.current_indent}}{first}") - if not second: - self.write("\n") - continue - if term_len(first) <= first_col - col_spacing: - self.write(" " * (first_col - term_len(first))) - else: - self.write("\n") - self.write(" " * (first_col + self.current_indent)) - - text_width = max(self.width - first_col - 2, 10) - wrapped_text = wrap_text(second, text_width, preserve_paragraphs=True) - lines = wrapped_text.splitlines() - - if lines: - self.write(f"{lines[0]}\n") - - for line in lines[1:]: - self.write(f"{'':>{first_col + self.current_indent}}{line}\n") - else: - self.write("\n") - - @contextmanager - def section(self, name: str) -> t.Iterator[None]: - """Helpful context manager that writes a paragraph, a heading, - and the indents. - - :param name: the section name that is written as heading. - """ - self.write_paragraph() - self.write_heading(name) - self.indent() - try: - yield - finally: - self.dedent() - - @contextmanager - def indentation(self) -> t.Iterator[None]: - """A context manager that increases the indentation.""" - self.indent() - try: - yield - finally: - self.dedent() - - def getvalue(self) -> str: - """Returns the buffer contents.""" - return "".join(self.buffer) - - -def join_options(options: t.Sequence[str]) -> t.Tuple[str, bool]: - """Given a list of option strings this joins them in the most appropriate - way and returns them in the form ``(formatted_string, - any_prefix_is_slash)`` where the second item in the tuple is a flag that - indicates if any of the option prefixes was a slash. - """ - rv = [] - any_prefix_is_slash = False - - for opt in options: - prefix = split_opt(opt)[0] - - if prefix == "/": - any_prefix_is_slash = True - - rv.append((len(prefix), opt)) - - rv.sort(key=lambda x: x[0]) - return ", ".join(x[1] for x in rv), any_prefix_is_slash diff --git a/venv/Lib/site-packages/click/globals.py b/venv/Lib/site-packages/click/globals.py deleted file mode 100644 index 191e712..0000000 --- a/venv/Lib/site-packages/click/globals.py +++ /dev/null @@ -1,67 +0,0 @@ -import typing as t -from threading import local - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .core import Context - -_local = local() - - -@t.overload -def get_current_context(silent: "te.Literal[False]" = False) -> "Context": ... - - -@t.overload -def get_current_context(silent: bool = ...) -> t.Optional["Context"]: ... - - -def get_current_context(silent: bool = False) -> t.Optional["Context"]: - """Returns the current click context. This can be used as a way to - access the current context object from anywhere. This is a more implicit - alternative to the :func:`pass_context` decorator. This function is - primarily useful for helpers such as :func:`echo` which might be - interested in changing its behavior based on the current context. - - To push the current context, :meth:`Context.scope` can be used. - - .. versionadded:: 5.0 - - :param silent: if set to `True` the return value is `None` if no context - is available. The default behavior is to raise a - :exc:`RuntimeError`. - """ - try: - return t.cast("Context", _local.stack[-1]) - except (AttributeError, IndexError) as e: - if not silent: - raise RuntimeError("There is no active click context.") from e - - return None - - -def push_context(ctx: "Context") -> None: - """Pushes a new context to the current stack.""" - _local.__dict__.setdefault("stack", []).append(ctx) - - -def pop_context() -> None: - """Removes the top level from the stack.""" - _local.stack.pop() - - -def resolve_color_default(color: t.Optional[bool] = None) -> t.Optional[bool]: - """Internal helper to get the default value of the color flag. If a - value is passed it's returned unchanged, otherwise it's looked up from - the current context. - """ - if color is not None: - return color - - ctx = get_current_context(silent=True) - - if ctx is not None: - return ctx.color - - return None diff --git a/venv/Lib/site-packages/click/parser.py b/venv/Lib/site-packages/click/parser.py deleted file mode 100644 index 600b843..0000000 --- a/venv/Lib/site-packages/click/parser.py +++ /dev/null @@ -1,531 +0,0 @@ -""" -This module started out as largely a copy paste from the stdlib's -optparse module with the features removed that we do not need from -optparse because we implement them in Click on a higher level (for -instance type handling, help formatting and a lot more). - -The plan is to remove more and more from here over time. - -The reason this is a different module and not optparse from the stdlib -is that there are differences in 2.x and 3.x about the error messages -generated and optparse in the stdlib uses gettext for no good reason -and might cause us issues. - -Click uses parts of optparse written by Gregory P. Ward and maintained -by the Python Software Foundation. This is limited to code in parser.py. - -Copyright 2001-2006 Gregory P. Ward. All rights reserved. -Copyright 2002-2006 Python Software Foundation. All rights reserved. -""" - -# This code uses parts of optparse written by Gregory P. Ward and -# maintained by the Python Software Foundation. -# Copyright 2001-2006 Gregory P. Ward -# Copyright 2002-2006 Python Software Foundation -import typing as t -from collections import deque -from gettext import gettext as _ -from gettext import ngettext - -from .exceptions import BadArgumentUsage -from .exceptions import BadOptionUsage -from .exceptions import NoSuchOption -from .exceptions import UsageError - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .core import Argument as CoreArgument - from .core import Context - from .core import Option as CoreOption - from .core import Parameter as CoreParameter - -V = t.TypeVar("V") - -# Sentinel value that indicates an option was passed as a flag without a -# value but is not a flag option. Option.consume_value uses this to -# prompt or use the flag_value. -_flag_needs_value = object() - - -def _unpack_args( - args: t.Sequence[str], nargs_spec: t.Sequence[int] -) -> t.Tuple[t.Sequence[t.Union[str, t.Sequence[t.Optional[str]], None]], t.List[str]]: - """Given an iterable of arguments and an iterable of nargs specifications, - it returns a tuple with all the unpacked arguments at the first index - and all remaining arguments as the second. - - The nargs specification is the number of arguments that should be consumed - or `-1` to indicate that this position should eat up all the remainders. - - Missing items are filled with `None`. - """ - args = deque(args) - nargs_spec = deque(nargs_spec) - rv: t.List[t.Union[str, t.Tuple[t.Optional[str], ...], None]] = [] - spos: t.Optional[int] = None - - def _fetch(c: "te.Deque[V]") -> t.Optional[V]: - try: - if spos is None: - return c.popleft() - else: - return c.pop() - except IndexError: - return None - - while nargs_spec: - nargs = _fetch(nargs_spec) - - if nargs is None: - continue - - if nargs == 1: - rv.append(_fetch(args)) - elif nargs > 1: - x = [_fetch(args) for _ in range(nargs)] - - # If we're reversed, we're pulling in the arguments in reverse, - # so we need to turn them around. - if spos is not None: - x.reverse() - - rv.append(tuple(x)) - elif nargs < 0: - if spos is not None: - raise TypeError("Cannot have two nargs < 0") - - spos = len(rv) - rv.append(None) - - # spos is the position of the wildcard (star). If it's not `None`, - # we fill it with the remainder. - if spos is not None: - rv[spos] = tuple(args) - args = [] - rv[spos + 1 :] = reversed(rv[spos + 1 :]) - - return tuple(rv), list(args) - - -def split_opt(opt: str) -> t.Tuple[str, str]: - first = opt[:1] - if first.isalnum(): - return "", opt - if opt[1:2] == first: - return opt[:2], opt[2:] - return first, opt[1:] - - -def normalize_opt(opt: str, ctx: t.Optional["Context"]) -> str: - if ctx is None or ctx.token_normalize_func is None: - return opt - prefix, opt = split_opt(opt) - return f"{prefix}{ctx.token_normalize_func(opt)}" - - -def split_arg_string(string: str) -> t.List[str]: - """Split an argument string as with :func:`shlex.split`, but don't - fail if the string is incomplete. Ignores a missing closing quote or - incomplete escape sequence and uses the partial token as-is. - - .. code-block:: python - - split_arg_string("example 'my file") - ["example", "my file"] - - split_arg_string("example my\\") - ["example", "my"] - - :param string: String to split. - """ - import shlex - - lex = shlex.shlex(string, posix=True) - lex.whitespace_split = True - lex.commenters = "" - out = [] - - try: - for token in lex: - out.append(token) - except ValueError: - # Raised when end-of-string is reached in an invalid state. Use - # the partial token as-is. The quote or escape character is in - # lex.state, not lex.token. - out.append(lex.token) - - return out - - -class Option: - def __init__( - self, - obj: "CoreOption", - opts: t.Sequence[str], - dest: t.Optional[str], - action: t.Optional[str] = None, - nargs: int = 1, - const: t.Optional[t.Any] = None, - ): - self._short_opts = [] - self._long_opts = [] - self.prefixes: t.Set[str] = set() - - for opt in opts: - prefix, value = split_opt(opt) - if not prefix: - raise ValueError(f"Invalid start character for option ({opt})") - self.prefixes.add(prefix[0]) - if len(prefix) == 1 and len(value) == 1: - self._short_opts.append(opt) - else: - self._long_opts.append(opt) - self.prefixes.add(prefix) - - if action is None: - action = "store" - - self.dest = dest - self.action = action - self.nargs = nargs - self.const = const - self.obj = obj - - @property - def takes_value(self) -> bool: - return self.action in ("store", "append") - - def process(self, value: t.Any, state: "ParsingState") -> None: - if self.action == "store": - state.opts[self.dest] = value # type: ignore - elif self.action == "store_const": - state.opts[self.dest] = self.const # type: ignore - elif self.action == "append": - state.opts.setdefault(self.dest, []).append(value) # type: ignore - elif self.action == "append_const": - state.opts.setdefault(self.dest, []).append(self.const) # type: ignore - elif self.action == "count": - state.opts[self.dest] = state.opts.get(self.dest, 0) + 1 # type: ignore - else: - raise ValueError(f"unknown action '{self.action}'") - state.order.append(self.obj) - - -class Argument: - def __init__(self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1): - self.dest = dest - self.nargs = nargs - self.obj = obj - - def process( - self, - value: t.Union[t.Optional[str], t.Sequence[t.Optional[str]]], - state: "ParsingState", - ) -> None: - if self.nargs > 1: - assert value is not None - holes = sum(1 for x in value if x is None) - if holes == len(value): - value = None - elif holes != 0: - raise BadArgumentUsage( - _("Argument {name!r} takes {nargs} values.").format( - name=self.dest, nargs=self.nargs - ) - ) - - if self.nargs == -1 and self.obj.envvar is not None and value == (): - # Replace empty tuple with None so that a value from the - # environment may be tried. - value = None - - state.opts[self.dest] = value # type: ignore - state.order.append(self.obj) - - -class ParsingState: - def __init__(self, rargs: t.List[str]) -> None: - self.opts: t.Dict[str, t.Any] = {} - self.largs: t.List[str] = [] - self.rargs = rargs - self.order: t.List[CoreParameter] = [] - - -class OptionParser: - """The option parser is an internal class that is ultimately used to - parse options and arguments. It's modelled after optparse and brings - a similar but vastly simplified API. It should generally not be used - directly as the high level Click classes wrap it for you. - - It's not nearly as extensible as optparse or argparse as it does not - implement features that are implemented on a higher level (such as - types or defaults). - - :param ctx: optionally the :class:`~click.Context` where this parser - should go with. - """ - - def __init__(self, ctx: t.Optional["Context"] = None) -> None: - #: The :class:`~click.Context` for this parser. This might be - #: `None` for some advanced use cases. - self.ctx = ctx - #: This controls how the parser deals with interspersed arguments. - #: If this is set to `False`, the parser will stop on the first - #: non-option. Click uses this to implement nested subcommands - #: safely. - self.allow_interspersed_args: bool = True - #: This tells the parser how to deal with unknown options. By - #: default it will error out (which is sensible), but there is a - #: second mode where it will ignore it and continue processing - #: after shifting all the unknown options into the resulting args. - self.ignore_unknown_options: bool = False - - if ctx is not None: - self.allow_interspersed_args = ctx.allow_interspersed_args - self.ignore_unknown_options = ctx.ignore_unknown_options - - self._short_opt: t.Dict[str, Option] = {} - self._long_opt: t.Dict[str, Option] = {} - self._opt_prefixes = {"-", "--"} - self._args: t.List[Argument] = [] - - def add_option( - self, - obj: "CoreOption", - opts: t.Sequence[str], - dest: t.Optional[str], - action: t.Optional[str] = None, - nargs: int = 1, - const: t.Optional[t.Any] = None, - ) -> None: - """Adds a new option named `dest` to the parser. The destination - is not inferred (unlike with optparse) and needs to be explicitly - provided. Action can be any of ``store``, ``store_const``, - ``append``, ``append_const`` or ``count``. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - opts = [normalize_opt(opt, self.ctx) for opt in opts] - option = Option(obj, opts, dest, action=action, nargs=nargs, const=const) - self._opt_prefixes.update(option.prefixes) - for opt in option._short_opts: - self._short_opt[opt] = option - for opt in option._long_opts: - self._long_opt[opt] = option - - def add_argument( - self, obj: "CoreArgument", dest: t.Optional[str], nargs: int = 1 - ) -> None: - """Adds a positional argument named `dest` to the parser. - - The `obj` can be used to identify the option in the order list - that is returned from the parser. - """ - self._args.append(Argument(obj, dest=dest, nargs=nargs)) - - def parse_args( - self, args: t.List[str] - ) -> t.Tuple[t.Dict[str, t.Any], t.List[str], t.List["CoreParameter"]]: - """Parses positional arguments and returns ``(values, args, order)`` - for the parsed options and arguments as well as the leftover - arguments if there are any. The order is a list of objects as they - appear on the command line. If arguments appear multiple times they - will be memorized multiple times as well. - """ - state = ParsingState(args) - try: - self._process_args_for_options(state) - self._process_args_for_args(state) - except UsageError: - if self.ctx is None or not self.ctx.resilient_parsing: - raise - return state.opts, state.largs, state.order - - def _process_args_for_args(self, state: ParsingState) -> None: - pargs, args = _unpack_args( - state.largs + state.rargs, [x.nargs for x in self._args] - ) - - for idx, arg in enumerate(self._args): - arg.process(pargs[idx], state) - - state.largs = args - state.rargs = [] - - def _process_args_for_options(self, state: ParsingState) -> None: - while state.rargs: - arg = state.rargs.pop(0) - arglen = len(arg) - # Double dashes always handled explicitly regardless of what - # prefixes are valid. - if arg == "--": - return - elif arg[:1] in self._opt_prefixes and arglen > 1: - self._process_opts(arg, state) - elif self.allow_interspersed_args: - state.largs.append(arg) - else: - state.rargs.insert(0, arg) - return - - # Say this is the original argument list: - # [arg0, arg1, ..., arg(i-1), arg(i), arg(i+1), ..., arg(N-1)] - # ^ - # (we are about to process arg(i)). - # - # Then rargs is [arg(i), ..., arg(N-1)] and largs is a *subset* of - # [arg0, ..., arg(i-1)] (any options and their arguments will have - # been removed from largs). - # - # The while loop will usually consume 1 or more arguments per pass. - # If it consumes 1 (eg. arg is an option that takes no arguments), - # then after _process_arg() is done the situation is: - # - # largs = subset of [arg0, ..., arg(i)] - # rargs = [arg(i+1), ..., arg(N-1)] - # - # If allow_interspersed_args is false, largs will always be - # *empty* -- still a subset of [arg0, ..., arg(i-1)], but - # not a very interesting subset! - - def _match_long_opt( - self, opt: str, explicit_value: t.Optional[str], state: ParsingState - ) -> None: - if opt not in self._long_opt: - from difflib import get_close_matches - - possibilities = get_close_matches(opt, self._long_opt) - raise NoSuchOption(opt, possibilities=possibilities, ctx=self.ctx) - - option = self._long_opt[opt] - if option.takes_value: - # At this point it's safe to modify rargs by injecting the - # explicit value, because no exception is raised in this - # branch. This means that the inserted value will be fully - # consumed. - if explicit_value is not None: - state.rargs.insert(0, explicit_value) - - value = self._get_value_from_state(opt, option, state) - - elif explicit_value is not None: - raise BadOptionUsage( - opt, _("Option {name!r} does not take a value.").format(name=opt) - ) - - else: - value = None - - option.process(value, state) - - def _match_short_opt(self, arg: str, state: ParsingState) -> None: - stop = False - i = 1 - prefix = arg[0] - unknown_options = [] - - for ch in arg[1:]: - opt = normalize_opt(f"{prefix}{ch}", self.ctx) - option = self._short_opt.get(opt) - i += 1 - - if not option: - if self.ignore_unknown_options: - unknown_options.append(ch) - continue - raise NoSuchOption(opt, ctx=self.ctx) - if option.takes_value: - # Any characters left in arg? Pretend they're the - # next arg, and stop consuming characters of arg. - if i < len(arg): - state.rargs.insert(0, arg[i:]) - stop = True - - value = self._get_value_from_state(opt, option, state) - - else: - value = None - - option.process(value, state) - - if stop: - break - - # If we got any unknown options we recombine the string of the - # remaining options and re-attach the prefix, then report that - # to the state as new larg. This way there is basic combinatorics - # that can be achieved while still ignoring unknown arguments. - if self.ignore_unknown_options and unknown_options: - state.largs.append(f"{prefix}{''.join(unknown_options)}") - - def _get_value_from_state( - self, option_name: str, option: Option, state: ParsingState - ) -> t.Any: - nargs = option.nargs - - if len(state.rargs) < nargs: - if option.obj._flag_needs_value: - # Option allows omitting the value. - value = _flag_needs_value - else: - raise BadOptionUsage( - option_name, - ngettext( - "Option {name!r} requires an argument.", - "Option {name!r} requires {nargs} arguments.", - nargs, - ).format(name=option_name, nargs=nargs), - ) - elif nargs == 1: - next_rarg = state.rargs[0] - - if ( - option.obj._flag_needs_value - and isinstance(next_rarg, str) - and next_rarg[:1] in self._opt_prefixes - and len(next_rarg) > 1 - ): - # The next arg looks like the start of an option, don't - # use it as the value if omitting the value is allowed. - value = _flag_needs_value - else: - value = state.rargs.pop(0) - else: - value = tuple(state.rargs[:nargs]) - del state.rargs[:nargs] - - return value - - def _process_opts(self, arg: str, state: ParsingState) -> None: - explicit_value = None - # Long option handling happens in two parts. The first part is - # supporting explicitly attached values. In any case, we will try - # to long match the option first. - if "=" in arg: - long_opt, explicit_value = arg.split("=", 1) - else: - long_opt = arg - norm_long_opt = normalize_opt(long_opt, self.ctx) - - # At this point we will match the (assumed) long option through - # the long option matching code. Note that this allows options - # like "-foo" to be matched as long options. - try: - self._match_long_opt(norm_long_opt, explicit_value, state) - except NoSuchOption: - # At this point the long option matching failed, and we need - # to try with short options. However there is a special rule - # which says, that if we have a two character options prefix - # (applies to "--foo" for instance), we do not dispatch to the - # short option code and will instead raise the no option - # error. - if arg[:2] not in self._opt_prefixes: - self._match_short_opt(arg, state) - return - - if not self.ignore_unknown_options: - raise - - state.largs.append(arg) diff --git a/venv/Lib/site-packages/click/py.typed b/venv/Lib/site-packages/click/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/click/shell_completion.py b/venv/Lib/site-packages/click/shell_completion.py deleted file mode 100644 index 07d0f09..0000000 --- a/venv/Lib/site-packages/click/shell_completion.py +++ /dev/null @@ -1,603 +0,0 @@ -import os -import re -import typing as t -from gettext import gettext as _ - -from .core import Argument -from .core import BaseCommand -from .core import Context -from .core import MultiCommand -from .core import Option -from .core import Parameter -from .core import ParameterSource -from .parser import split_arg_string -from .utils import echo - - -def shell_complete( - cli: BaseCommand, - ctx_args: t.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str, - instruction: str, -) -> int: - """Perform shell completion for the given CLI program. - - :param cli: Command being called. - :param ctx_args: Extra arguments to pass to - ``cli.make_context``. - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. - :param instruction: Value of ``complete_var`` with the completion - instruction and shell, in the form ``instruction_shell``. - :return: Status code to exit with. - """ - shell, _, instruction = instruction.partition("_") - comp_cls = get_completion_class(shell) - - if comp_cls is None: - return 1 - - comp = comp_cls(cli, ctx_args, prog_name, complete_var) - - if instruction == "source": - echo(comp.source()) - return 0 - - if instruction == "complete": - echo(comp.complete()) - return 0 - - return 1 - - -class CompletionItem: - """Represents a completion value and metadata about the value. The - default metadata is ``type`` to indicate special shell handling, - and ``help`` if a shell supports showing a help string next to the - value. - - Arbitrary parameters can be passed when creating the object, and - accessed using ``item.attr``. If an attribute wasn't passed, - accessing it returns ``None``. - - :param value: The completion suggestion. - :param type: Tells the shell script to provide special completion - support for the type. Click uses ``"dir"`` and ``"file"``. - :param help: String shown next to the value if supported. - :param kwargs: Arbitrary metadata. The built-in implementations - don't use this, but custom type completions paired with custom - shell support could use it. - """ - - __slots__ = ("value", "type", "help", "_info") - - def __init__( - self, - value: t.Any, - type: str = "plain", - help: t.Optional[str] = None, - **kwargs: t.Any, - ) -> None: - self.value: t.Any = value - self.type: str = type - self.help: t.Optional[str] = help - self._info = kwargs - - def __getattr__(self, name: str) -> t.Any: - return self._info.get(name) - - -# Only Bash >= 4.4 has the nosort option. -_SOURCE_BASH = """\ -%(complete_func)s() { - local IFS=$'\\n' - local response - - response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ -%(complete_var)s=bash_complete $1) - - for completion in $response; do - IFS=',' read type value <<< "$completion" - - if [[ $type == 'dir' ]]; then - COMPREPLY=() - compopt -o dirnames - elif [[ $type == 'file' ]]; then - COMPREPLY=() - compopt -o default - elif [[ $type == 'plain' ]]; then - COMPREPLY+=($value) - fi - done - - return 0 -} - -%(complete_func)s_setup() { - complete -o nosort -F %(complete_func)s %(prog_name)s -} - -%(complete_func)s_setup; -""" - -_SOURCE_ZSH = """\ -#compdef %(prog_name)s - -%(complete_func)s() { - local -a completions - local -a completions_with_descriptions - local -a response - (( ! $+commands[%(prog_name)s] )) && return 1 - - response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ -%(complete_var)s=zsh_complete %(prog_name)s)}") - - for type key descr in ${response}; do - if [[ "$type" == "plain" ]]; then - if [[ "$descr" == "_" ]]; then - completions+=("$key") - else - completions_with_descriptions+=("$key":"$descr") - fi - elif [[ "$type" == "dir" ]]; then - _path_files -/ - elif [[ "$type" == "file" ]]; then - _path_files -f - fi - done - - if [ -n "$completions_with_descriptions" ]; then - _describe -V unsorted completions_with_descriptions -U - fi - - if [ -n "$completions" ]; then - compadd -U -V unsorted -a completions - fi -} - -if [[ $zsh_eval_context[-1] == loadautofunc ]]; then - # autoload from fpath, call function directly - %(complete_func)s "$@" -else - # eval/source/. command, register function for later - compdef %(complete_func)s %(prog_name)s -fi -""" - -_SOURCE_FISH = """\ -function %(complete_func)s; - set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ -COMP_CWORD=(commandline -t) %(prog_name)s); - - for completion in $response; - set -l metadata (string split "," $completion); - - if test $metadata[1] = "dir"; - __fish_complete_directories $metadata[2]; - else if test $metadata[1] = "file"; - __fish_complete_path $metadata[2]; - else if test $metadata[1] = "plain"; - echo $metadata[2]; - end; - end; -end; - -complete --no-files --command %(prog_name)s --arguments \ -"(%(complete_func)s)"; -""" - - -class ShellComplete: - """Base class for providing shell completion support. A subclass for - a given shell will override attributes and methods to implement the - completion instructions (``source`` and ``complete``). - - :param cli: Command being called. - :param prog_name: Name of the executable in the shell. - :param complete_var: Name of the environment variable that holds - the completion instruction. - - .. versionadded:: 8.0 - """ - - name: t.ClassVar[str] - """Name to register the shell as with :func:`add_completion_class`. - This is used in completion instructions (``{name}_source`` and - ``{name}_complete``). - """ - - source_template: t.ClassVar[str] - """Completion script template formatted by :meth:`source`. This must - be provided by subclasses. - """ - - def __init__( - self, - cli: BaseCommand, - ctx_args: t.MutableMapping[str, t.Any], - prog_name: str, - complete_var: str, - ) -> None: - self.cli = cli - self.ctx_args = ctx_args - self.prog_name = prog_name - self.complete_var = complete_var - - @property - def func_name(self) -> str: - """The name of the shell function defined by the completion - script. - """ - safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) - return f"_{safe_name}_completion" - - def source_vars(self) -> t.Dict[str, t.Any]: - """Vars for formatting :attr:`source_template`. - - By default this provides ``complete_func``, ``complete_var``, - and ``prog_name``. - """ - return { - "complete_func": self.func_name, - "complete_var": self.complete_var, - "prog_name": self.prog_name, - } - - def source(self) -> str: - """Produce the shell script that defines the completion - function. By default this ``%``-style formats - :attr:`source_template` with the dict returned by - :meth:`source_vars`. - """ - return self.source_template % self.source_vars() - - def get_completion_args(self) -> t.Tuple[t.List[str], str]: - """Use the env vars defined by the shell script to return a - tuple of ``args, incomplete``. This must be implemented by - subclasses. - """ - raise NotImplementedError - - def get_completions( - self, args: t.List[str], incomplete: str - ) -> t.List[CompletionItem]: - """Determine the context and last complete command or parameter - from the complete args. Call that object's ``shell_complete`` - method to get the completions for the incomplete value. - - :param args: List of complete args before the incomplete value. - :param incomplete: Value being completed. May be empty. - """ - ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) - obj, incomplete = _resolve_incomplete(ctx, args, incomplete) - return obj.shell_complete(ctx, incomplete) - - def format_completion(self, item: CompletionItem) -> str: - """Format a completion item into the form recognized by the - shell script. This must be implemented by subclasses. - - :param item: Completion item to format. - """ - raise NotImplementedError - - def complete(self) -> str: - """Produce the completion data to send back to the shell. - - By default this calls :meth:`get_completion_args`, gets the - completions, then calls :meth:`format_completion` for each - completion. - """ - args, incomplete = self.get_completion_args() - completions = self.get_completions(args, incomplete) - out = [self.format_completion(item) for item in completions] - return "\n".join(out) - - -class BashComplete(ShellComplete): - """Shell completion for Bash.""" - - name = "bash" - source_template = _SOURCE_BASH - - @staticmethod - def _check_version() -> None: - import shutil - import subprocess - - bash_exe = shutil.which("bash") - - if bash_exe is None: - match = None - else: - output = subprocess.run( - [bash_exe, "--norc", "-c", 'echo "${BASH_VERSION}"'], - stdout=subprocess.PIPE, - ) - match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) - - if match is not None: - major, minor = match.groups() - - if major < "4" or major == "4" and minor < "4": - echo( - _( - "Shell completion is not supported for Bash" - " versions older than 4.4." - ), - err=True, - ) - else: - echo( - _("Couldn't detect Bash version, shell completion is not supported."), - err=True, - ) - - def source(self) -> str: - self._check_version() - return super().source() - - def get_completion_args(self) -> t.Tuple[t.List[str], str]: - cwords = split_arg_string(os.environ["COMP_WORDS"]) - cword = int(os.environ["COMP_CWORD"]) - args = cwords[1:cword] - - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - return args, incomplete - - def format_completion(self, item: CompletionItem) -> str: - return f"{item.type},{item.value}" - - -class ZshComplete(ShellComplete): - """Shell completion for Zsh.""" - - name = "zsh" - source_template = _SOURCE_ZSH - - def get_completion_args(self) -> t.Tuple[t.List[str], str]: - cwords = split_arg_string(os.environ["COMP_WORDS"]) - cword = int(os.environ["COMP_CWORD"]) - args = cwords[1:cword] - - try: - incomplete = cwords[cword] - except IndexError: - incomplete = "" - - return args, incomplete - - def format_completion(self, item: CompletionItem) -> str: - return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" - - -class FishComplete(ShellComplete): - """Shell completion for Fish.""" - - name = "fish" - source_template = _SOURCE_FISH - - def get_completion_args(self) -> t.Tuple[t.List[str], str]: - cwords = split_arg_string(os.environ["COMP_WORDS"]) - incomplete = os.environ["COMP_CWORD"] - args = cwords[1:] - - # Fish stores the partial word in both COMP_WORDS and - # COMP_CWORD, remove it from complete args. - if incomplete and args and args[-1] == incomplete: - args.pop() - - return args, incomplete - - def format_completion(self, item: CompletionItem) -> str: - if item.help: - return f"{item.type},{item.value}\t{item.help}" - - return f"{item.type},{item.value}" - - -ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) - - -_available_shells: t.Dict[str, t.Type[ShellComplete]] = { - "bash": BashComplete, - "fish": FishComplete, - "zsh": ZshComplete, -} - - -def add_completion_class( - cls: ShellCompleteType, name: t.Optional[str] = None -) -> ShellCompleteType: - """Register a :class:`ShellComplete` subclass under the given name. - The name will be provided by the completion instruction environment - variable during completion. - - :param cls: The completion class that will handle completion for the - shell. - :param name: Name to register the class under. Defaults to the - class's ``name`` attribute. - """ - if name is None: - name = cls.name - - _available_shells[name] = cls - - return cls - - -def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: - """Look up a registered :class:`ShellComplete` subclass by the name - provided by the completion instruction environment variable. If the - name isn't registered, returns ``None``. - - :param shell: Name the class is registered under. - """ - return _available_shells.get(shell) - - -def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: - """Determine if the given parameter is an argument that can still - accept values. - - :param ctx: Invocation context for the command represented by the - parsed complete args. - :param param: Argument object being checked. - """ - if not isinstance(param, Argument): - return False - - assert param.name is not None - # Will be None if expose_value is False. - value = ctx.params.get(param.name) - return ( - param.nargs == -1 - or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE - or ( - param.nargs > 1 - and isinstance(value, (tuple, list)) - and len(value) < param.nargs - ) - ) - - -def _start_of_option(ctx: Context, value: str) -> bool: - """Check if the value looks like the start of an option.""" - if not value: - return False - - c = value[0] - return c in ctx._opt_prefixes - - -def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: - """Determine if the given parameter is an option that needs a value. - - :param args: List of complete args before the incomplete value. - :param param: Option object being checked. - """ - if not isinstance(param, Option): - return False - - if param.is_flag or param.count: - return False - - last_option = None - - for index, arg in enumerate(reversed(args)): - if index + 1 > param.nargs: - break - - if _start_of_option(ctx, arg): - last_option = arg - - return last_option is not None and last_option in param.opts - - -def _resolve_context( - cli: BaseCommand, - ctx_args: t.MutableMapping[str, t.Any], - prog_name: str, - args: t.List[str], -) -> Context: - """Produce the context hierarchy starting with the command and - traversing the complete arguments. This only follows the commands, - it doesn't trigger input prompts or callbacks. - - :param cli: Command being called. - :param prog_name: Name of the executable in the shell. - :param args: List of complete args before the incomplete value. - """ - ctx_args["resilient_parsing"] = True - ctx = cli.make_context(prog_name, args.copy(), **ctx_args) - args = ctx.protected_args + ctx.args - - while args: - command = ctx.command - - if isinstance(command, MultiCommand): - if not command.chain: - name, cmd, args = command.resolve_command(ctx, args) - - if cmd is None: - return ctx - - ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) - args = ctx.protected_args + ctx.args - else: - sub_ctx = ctx - - while args: - name, cmd, args = command.resolve_command(ctx, args) - - if cmd is None: - return ctx - - sub_ctx = cmd.make_context( - name, - args, - parent=ctx, - allow_extra_args=True, - allow_interspersed_args=False, - resilient_parsing=True, - ) - args = sub_ctx.args - - ctx = sub_ctx - args = [*sub_ctx.protected_args, *sub_ctx.args] - else: - break - - return ctx - - -def _resolve_incomplete( - ctx: Context, args: t.List[str], incomplete: str -) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: - """Find the Click object that will handle the completion of the - incomplete value. Return the object and the incomplete value. - - :param ctx: Invocation context for the command represented by - the parsed complete args. - :param args: List of complete args before the incomplete value. - :param incomplete: Value being completed. May be empty. - """ - # Different shells treat an "=" between a long option name and - # value differently. Might keep the value joined, return the "=" - # as a separate item, or return the split name and value. Always - # split and discard the "=" to make completion easier. - if incomplete == "=": - incomplete = "" - elif "=" in incomplete and _start_of_option(ctx, incomplete): - name, _, incomplete = incomplete.partition("=") - args.append(name) - - # The "--" marker tells Click to stop treating values as options - # even if they start with the option character. If it hasn't been - # given and the incomplete arg looks like an option, the current - # command will provide option name completions. - if "--" not in args and _start_of_option(ctx, incomplete): - return ctx.command, incomplete - - params = ctx.command.get_params(ctx) - - # If the last complete arg is an option name with an incomplete - # value, the option will provide value completions. - for param in params: - if _is_incomplete_option(ctx, args, param): - return param, incomplete - - # It's not an option name or value. The first argument without a - # parsed value will provide value completions. - for param in params: - if _is_incomplete_argument(ctx, param): - return param, incomplete - - # There were no unparsed arguments, the command may be a group that - # will provide command name completions. - return ctx.command, incomplete diff --git a/venv/Lib/site-packages/click/termui.py b/venv/Lib/site-packages/click/termui.py deleted file mode 100644 index c084f19..0000000 --- a/venv/Lib/site-packages/click/termui.py +++ /dev/null @@ -1,784 +0,0 @@ -import inspect -import io -import itertools -import sys -import typing as t -from gettext import gettext as _ - -from ._compat import isatty -from ._compat import strip_ansi -from .exceptions import Abort -from .exceptions import UsageError -from .globals import resolve_color_default -from .types import Choice -from .types import convert_type -from .types import ParamType -from .utils import echo -from .utils import LazyFile - -if t.TYPE_CHECKING: - from ._termui_impl import ProgressBar - -V = t.TypeVar("V") - -# The prompt functions to use. The doc tools currently override these -# functions to customize how they work. -visible_prompt_func: t.Callable[[str], str] = input - -_ansi_colors = { - "black": 30, - "red": 31, - "green": 32, - "yellow": 33, - "blue": 34, - "magenta": 35, - "cyan": 36, - "white": 37, - "reset": 39, - "bright_black": 90, - "bright_red": 91, - "bright_green": 92, - "bright_yellow": 93, - "bright_blue": 94, - "bright_magenta": 95, - "bright_cyan": 96, - "bright_white": 97, -} -_ansi_reset_all = "\033[0m" - - -def hidden_prompt_func(prompt: str) -> str: - import getpass - - return getpass.getpass(prompt) - - -def _build_prompt( - text: str, - suffix: str, - show_default: bool = False, - default: t.Optional[t.Any] = None, - show_choices: bool = True, - type: t.Optional[ParamType] = None, -) -> str: - prompt = text - if type is not None and show_choices and isinstance(type, Choice): - prompt += f" ({', '.join(map(str, type.choices))})" - if default is not None and show_default: - prompt = f"{prompt} [{_format_default(default)}]" - return f"{prompt}{suffix}" - - -def _format_default(default: t.Any) -> t.Any: - if isinstance(default, (io.IOBase, LazyFile)) and hasattr(default, "name"): - return default.name - - return default - - -def prompt( - text: str, - default: t.Optional[t.Any] = None, - hide_input: bool = False, - confirmation_prompt: t.Union[bool, str] = False, - type: t.Optional[t.Union[ParamType, t.Any]] = None, - value_proc: t.Optional[t.Callable[[str], t.Any]] = None, - prompt_suffix: str = ": ", - show_default: bool = True, - err: bool = False, - show_choices: bool = True, -) -> t.Any: - """Prompts a user for input. This is a convenience function that can - be used to prompt a user for input later. - - If the user aborts the input by sending an interrupt signal, this - function will catch it and raise a :exc:`Abort` exception. - - :param text: the text to show for the prompt. - :param default: the default value to use if no input happens. If this - is not given it will prompt until it's aborted. - :param hide_input: if this is set to true then the input value will - be hidden. - :param confirmation_prompt: Prompt a second time to confirm the - value. Can be set to a string instead of ``True`` to customize - the message. - :param type: the type to use to check the value against. - :param value_proc: if this parameter is provided it's a function that - is invoked instead of the type conversion to - convert a value. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - :param show_choices: Show or hide choices if the passed type is a Choice. - For example if type is a Choice of either day or week, - show_choices is true and text is "Group by" then the - prompt will be "Group by (day, week): ". - - .. versionadded:: 8.0 - ``confirmation_prompt`` can be a custom string. - - .. versionadded:: 7.0 - Added the ``show_choices`` parameter. - - .. versionadded:: 6.0 - Added unicode support for cmd.exe on Windows. - - .. versionadded:: 4.0 - Added the `err` parameter. - - """ - - def prompt_func(text: str) -> str: - f = hidden_prompt_func if hide_input else visible_prompt_func - try: - # Write the prompt separately so that we get nice - # coloring through colorama on Windows - echo(text.rstrip(" "), nl=False, err=err) - # Echo a space to stdout to work around an issue where - # readline causes backspace to clear the whole line. - return f(" ") - except (KeyboardInterrupt, EOFError): - # getpass doesn't print a newline if the user aborts input with ^C. - # Allegedly this behavior is inherited from getpass(3). - # A doc bug has been filed at https://bugs.python.org/issue24711 - if hide_input: - echo(None, err=err) - raise Abort() from None - - if value_proc is None: - value_proc = convert_type(type, default) - - prompt = _build_prompt( - text, prompt_suffix, show_default, default, show_choices, type - ) - - if confirmation_prompt: - if confirmation_prompt is True: - confirmation_prompt = _("Repeat for confirmation") - - confirmation_prompt = _build_prompt(confirmation_prompt, prompt_suffix) - - while True: - while True: - value = prompt_func(prompt) - if value: - break - elif default is not None: - value = default - break - try: - result = value_proc(value) - except UsageError as e: - if hide_input: - echo(_("Error: The value you entered was invalid."), err=err) - else: - echo(_("Error: {e.message}").format(e=e), err=err) - continue - if not confirmation_prompt: - return result - while True: - value2 = prompt_func(confirmation_prompt) - is_empty = not value and not value2 - if value2 or is_empty: - break - if value == value2: - return result - echo(_("Error: The two entered values do not match."), err=err) - - -def confirm( - text: str, - default: t.Optional[bool] = False, - abort: bool = False, - prompt_suffix: str = ": ", - show_default: bool = True, - err: bool = False, -) -> bool: - """Prompts for confirmation (yes/no question). - - If the user aborts the input by sending a interrupt signal this - function will catch it and raise a :exc:`Abort` exception. - - :param text: the question to ask. - :param default: The default value to use when no input is given. If - ``None``, repeat until input is given. - :param abort: if this is set to `True` a negative answer aborts the - exception by raising :exc:`Abort`. - :param prompt_suffix: a suffix that should be added to the prompt. - :param show_default: shows or hides the default value in the prompt. - :param err: if set to true the file defaults to ``stderr`` instead of - ``stdout``, the same as with echo. - - .. versionchanged:: 8.0 - Repeat until input is given if ``default`` is ``None``. - - .. versionadded:: 4.0 - Added the ``err`` parameter. - """ - prompt = _build_prompt( - text, - prompt_suffix, - show_default, - "y/n" if default is None else ("Y/n" if default else "y/N"), - ) - - while True: - try: - # Write the prompt separately so that we get nice - # coloring through colorama on Windows - echo(prompt.rstrip(" "), nl=False, err=err) - # Echo a space to stdout to work around an issue where - # readline causes backspace to clear the whole line. - value = visible_prompt_func(" ").lower().strip() - except (KeyboardInterrupt, EOFError): - raise Abort() from None - if value in ("y", "yes"): - rv = True - elif value in ("n", "no"): - rv = False - elif default is not None and value == "": - rv = default - else: - echo(_("Error: invalid input"), err=err) - continue - break - if abort and not rv: - raise Abort() - return rv - - -def echo_via_pager( - text_or_generator: t.Union[t.Iterable[str], t.Callable[[], t.Iterable[str]], str], - color: t.Optional[bool] = None, -) -> None: - """This function takes a text and shows it via an environment specific - pager on stdout. - - .. versionchanged:: 3.0 - Added the `color` flag. - - :param text_or_generator: the text to page, or alternatively, a - generator emitting the text to page. - :param color: controls if the pager supports ANSI colors or not. The - default is autodetection. - """ - color = resolve_color_default(color) - - if inspect.isgeneratorfunction(text_or_generator): - i = t.cast(t.Callable[[], t.Iterable[str]], text_or_generator)() - elif isinstance(text_or_generator, str): - i = [text_or_generator] - else: - i = iter(t.cast(t.Iterable[str], text_or_generator)) - - # convert every element of i to a text type if necessary - text_generator = (el if isinstance(el, str) else str(el) for el in i) - - from ._termui_impl import pager - - return pager(itertools.chain(text_generator, "\n"), color) - - -def progressbar( - iterable: t.Optional[t.Iterable[V]] = None, - length: t.Optional[int] = None, - label: t.Optional[str] = None, - show_eta: bool = True, - show_percent: t.Optional[bool] = None, - show_pos: bool = False, - item_show_func: t.Optional[t.Callable[[t.Optional[V]], t.Optional[str]]] = None, - fill_char: str = "#", - empty_char: str = "-", - bar_template: str = "%(label)s [%(bar)s] %(info)s", - info_sep: str = " ", - width: int = 36, - file: t.Optional[t.TextIO] = None, - color: t.Optional[bool] = None, - update_min_steps: int = 1, -) -> "ProgressBar[V]": - """This function creates an iterable context manager that can be used - to iterate over something while showing a progress bar. It will - either iterate over the `iterable` or `length` items (that are counted - up). While iteration happens, this function will print a rendered - progress bar to the given `file` (defaults to stdout) and will attempt - to calculate remaining time and more. By default, this progress bar - will not be rendered if the file is not a terminal. - - The context manager creates the progress bar. When the context - manager is entered the progress bar is already created. With every - iteration over the progress bar, the iterable passed to the bar is - advanced and the bar is updated. When the context manager exits, - a newline is printed and the progress bar is finalized on screen. - - Note: The progress bar is currently designed for use cases where the - total progress can be expected to take at least several seconds. - Because of this, the ProgressBar class object won't display - progress that is considered too fast, and progress where the time - between steps is less than a second. - - No printing must happen or the progress bar will be unintentionally - destroyed. - - Example usage:: - - with progressbar(items) as bar: - for item in bar: - do_something_with(item) - - Alternatively, if no iterable is specified, one can manually update the - progress bar through the `update()` method instead of directly - iterating over the progress bar. The update method accepts the number - of steps to increment the bar with:: - - with progressbar(length=chunks.total_bytes) as bar: - for chunk in chunks: - process_chunk(chunk) - bar.update(chunks.bytes) - - The ``update()`` method also takes an optional value specifying the - ``current_item`` at the new position. This is useful when used - together with ``item_show_func`` to customize the output for each - manual step:: - - with click.progressbar( - length=total_size, - label='Unzipping archive', - item_show_func=lambda a: a.filename - ) as bar: - for archive in zip_file: - archive.extract() - bar.update(archive.size, archive) - - :param iterable: an iterable to iterate over. If not provided the length - is required. - :param length: the number of items to iterate over. By default the - progressbar will attempt to ask the iterator about its - length, which might or might not work. If an iterable is - also provided this parameter can be used to override the - length. If an iterable is not provided the progress bar - will iterate over a range of that length. - :param label: the label to show next to the progress bar. - :param show_eta: enables or disables the estimated time display. This is - automatically disabled if the length cannot be - determined. - :param show_percent: enables or disables the percentage display. The - default is `True` if the iterable has a length or - `False` if not. - :param show_pos: enables or disables the absolute position display. The - default is `False`. - :param item_show_func: A function called with the current item which - can return a string to show next to the progress bar. If the - function returns ``None`` nothing is shown. The current item can - be ``None``, such as when entering and exiting the bar. - :param fill_char: the character to use to show the filled part of the - progress bar. - :param empty_char: the character to use to show the non-filled part of - the progress bar. - :param bar_template: the format string to use as template for the bar. - The parameters in it are ``label`` for the label, - ``bar`` for the progress bar and ``info`` for the - info section. - :param info_sep: the separator between multiple info items (eta etc.) - :param width: the width of the progress bar in characters, 0 means full - terminal width - :param file: The file to write to. If this is not a terminal then - only the label is printed. - :param color: controls if the terminal supports ANSI colors or not. The - default is autodetection. This is only needed if ANSI - codes are included anywhere in the progress bar output - which is not the case by default. - :param update_min_steps: Render only when this many updates have - completed. This allows tuning for very fast iterators. - - .. versionchanged:: 8.0 - Output is shown even if execution time is less than 0.5 seconds. - - .. versionchanged:: 8.0 - ``item_show_func`` shows the current item, not the previous one. - - .. versionchanged:: 8.0 - Labels are echoed if the output is not a TTY. Reverts a change - in 7.0 that removed all output. - - .. versionadded:: 8.0 - Added the ``update_min_steps`` parameter. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. Added the ``update`` method to - the object. - - .. versionadded:: 2.0 - """ - from ._termui_impl import ProgressBar - - color = resolve_color_default(color) - return ProgressBar( - iterable=iterable, - length=length, - show_eta=show_eta, - show_percent=show_percent, - show_pos=show_pos, - item_show_func=item_show_func, - fill_char=fill_char, - empty_char=empty_char, - bar_template=bar_template, - info_sep=info_sep, - file=file, - label=label, - width=width, - color=color, - update_min_steps=update_min_steps, - ) - - -def clear() -> None: - """Clears the terminal screen. This will have the effect of clearing - the whole visible space of the terminal and moving the cursor to the - top left. This does not do anything if not connected to a terminal. - - .. versionadded:: 2.0 - """ - if not isatty(sys.stdout): - return - - # ANSI escape \033[2J clears the screen, \033[1;1H moves the cursor - echo("\033[2J\033[1;1H", nl=False) - - -def _interpret_color( - color: t.Union[int, t.Tuple[int, int, int], str], offset: int = 0 -) -> str: - if isinstance(color, int): - return f"{38 + offset};5;{color:d}" - - if isinstance(color, (tuple, list)): - r, g, b = color - return f"{38 + offset};2;{r:d};{g:d};{b:d}" - - return str(_ansi_colors[color] + offset) - - -def style( - text: t.Any, - fg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, - bg: t.Optional[t.Union[int, t.Tuple[int, int, int], str]] = None, - bold: t.Optional[bool] = None, - dim: t.Optional[bool] = None, - underline: t.Optional[bool] = None, - overline: t.Optional[bool] = None, - italic: t.Optional[bool] = None, - blink: t.Optional[bool] = None, - reverse: t.Optional[bool] = None, - strikethrough: t.Optional[bool] = None, - reset: bool = True, -) -> str: - """Styles a text with ANSI styles and returns the new string. By - default the styling is self contained which means that at the end - of the string a reset code is issued. This can be prevented by - passing ``reset=False``. - - Examples:: - - click.echo(click.style('Hello World!', fg='green')) - click.echo(click.style('ATTENTION!', blink=True)) - click.echo(click.style('Some things', reverse=True, fg='cyan')) - click.echo(click.style('More colors', fg=(255, 12, 128), bg=117)) - - Supported color names: - - * ``black`` (might be a gray) - * ``red`` - * ``green`` - * ``yellow`` (might be an orange) - * ``blue`` - * ``magenta`` - * ``cyan`` - * ``white`` (might be light gray) - * ``bright_black`` - * ``bright_red`` - * ``bright_green`` - * ``bright_yellow`` - * ``bright_blue`` - * ``bright_magenta`` - * ``bright_cyan`` - * ``bright_white`` - * ``reset`` (reset the color code only) - - If the terminal supports it, color may also be specified as: - - - An integer in the interval [0, 255]. The terminal must support - 8-bit/256-color mode. - - An RGB tuple of three integers in [0, 255]. The terminal must - support 24-bit/true-color mode. - - See https://en.wikipedia.org/wiki/ANSI_color and - https://gist.github.com/XVilka/8346728 for more information. - - :param text: the string to style with ansi codes. - :param fg: if provided this will become the foreground color. - :param bg: if provided this will become the background color. - :param bold: if provided this will enable or disable bold mode. - :param dim: if provided this will enable or disable dim mode. This is - badly supported. - :param underline: if provided this will enable or disable underline. - :param overline: if provided this will enable or disable overline. - :param italic: if provided this will enable or disable italic. - :param blink: if provided this will enable or disable blinking. - :param reverse: if provided this will enable or disable inverse - rendering (foreground becomes background and the - other way round). - :param strikethrough: if provided this will enable or disable - striking through text. - :param reset: by default a reset-all code is added at the end of the - string which means that styles do not carry over. This - can be disabled to compose styles. - - .. versionchanged:: 8.0 - A non-string ``message`` is converted to a string. - - .. versionchanged:: 8.0 - Added support for 256 and RGB color codes. - - .. versionchanged:: 8.0 - Added the ``strikethrough``, ``italic``, and ``overline`` - parameters. - - .. versionchanged:: 7.0 - Added support for bright colors. - - .. versionadded:: 2.0 - """ - if not isinstance(text, str): - text = str(text) - - bits = [] - - if fg: - try: - bits.append(f"\033[{_interpret_color(fg)}m") - except KeyError: - raise TypeError(f"Unknown color {fg!r}") from None - - if bg: - try: - bits.append(f"\033[{_interpret_color(bg, 10)}m") - except KeyError: - raise TypeError(f"Unknown color {bg!r}") from None - - if bold is not None: - bits.append(f"\033[{1 if bold else 22}m") - if dim is not None: - bits.append(f"\033[{2 if dim else 22}m") - if underline is not None: - bits.append(f"\033[{4 if underline else 24}m") - if overline is not None: - bits.append(f"\033[{53 if overline else 55}m") - if italic is not None: - bits.append(f"\033[{3 if italic else 23}m") - if blink is not None: - bits.append(f"\033[{5 if blink else 25}m") - if reverse is not None: - bits.append(f"\033[{7 if reverse else 27}m") - if strikethrough is not None: - bits.append(f"\033[{9 if strikethrough else 29}m") - bits.append(text) - if reset: - bits.append(_ansi_reset_all) - return "".join(bits) - - -def unstyle(text: str) -> str: - """Removes ANSI styling information from a string. Usually it's not - necessary to use this function as Click's echo function will - automatically remove styling if necessary. - - .. versionadded:: 2.0 - - :param text: the text to remove style information from. - """ - return strip_ansi(text) - - -def secho( - message: t.Optional[t.Any] = None, - file: t.Optional[t.IO[t.AnyStr]] = None, - nl: bool = True, - err: bool = False, - color: t.Optional[bool] = None, - **styles: t.Any, -) -> None: - """This function combines :func:`echo` and :func:`style` into one - call. As such the following two calls are the same:: - - click.secho('Hello World!', fg='green') - click.echo(click.style('Hello World!', fg='green')) - - All keyword arguments are forwarded to the underlying functions - depending on which one they go with. - - Non-string types will be converted to :class:`str`. However, - :class:`bytes` are passed directly to :meth:`echo` without applying - style. If you want to style bytes that represent text, call - :meth:`bytes.decode` first. - - .. versionchanged:: 8.0 - A non-string ``message`` is converted to a string. Bytes are - passed through without style applied. - - .. versionadded:: 2.0 - """ - if message is not None and not isinstance(message, (bytes, bytearray)): - message = style(message, **styles) - - return echo(message, file=file, nl=nl, err=err, color=color) - - -def edit( - text: t.Optional[t.AnyStr] = None, - editor: t.Optional[str] = None, - env: t.Optional[t.Mapping[str, str]] = None, - require_save: bool = True, - extension: str = ".txt", - filename: t.Optional[str] = None, -) -> t.Optional[t.AnyStr]: - r"""Edits the given text in the defined editor. If an editor is given - (should be the full path to the executable but the regular operating - system search path is used for finding the executable) it overrides - the detected editor. Optionally, some environment variables can be - used. If the editor is closed without changes, `None` is returned. In - case a file is edited directly the return value is always `None` and - `require_save` and `extension` are ignored. - - If the editor cannot be opened a :exc:`UsageError` is raised. - - Note for Windows: to simplify cross-platform usage, the newlines are - automatically converted from POSIX to Windows and vice versa. As such, - the message here will have ``\n`` as newline markers. - - :param text: the text to edit. - :param editor: optionally the editor to use. Defaults to automatic - detection. - :param env: environment variables to forward to the editor. - :param require_save: if this is true, then not saving in the editor - will make the return value become `None`. - :param extension: the extension to tell the editor about. This defaults - to `.txt` but changing this might change syntax - highlighting. - :param filename: if provided it will edit this file instead of the - provided text contents. It will not use a temporary - file as an indirection in that case. - """ - from ._termui_impl import Editor - - ed = Editor(editor=editor, env=env, require_save=require_save, extension=extension) - - if filename is None: - return ed.edit(text) - - ed.edit_file(filename) - return None - - -def launch(url: str, wait: bool = False, locate: bool = False) -> int: - """This function launches the given URL (or filename) in the default - viewer application for this file type. If this is an executable, it - might launch the executable in a new session. The return value is - the exit code of the launched application. Usually, ``0`` indicates - success. - - Examples:: - - click.launch('https://click.palletsprojects.com/') - click.launch('/my/downloaded/file', locate=True) - - .. versionadded:: 2.0 - - :param url: URL or filename of the thing to launch. - :param wait: Wait for the program to exit before returning. This - only works if the launched program blocks. In particular, - ``xdg-open`` on Linux does not block. - :param locate: if this is set to `True` then instead of launching the - application associated with the URL it will attempt to - launch a file manager with the file located. This - might have weird effects if the URL does not point to - the filesystem. - """ - from ._termui_impl import open_url - - return open_url(url, wait=wait, locate=locate) - - -# If this is provided, getchar() calls into this instead. This is used -# for unittesting purposes. -_getchar: t.Optional[t.Callable[[bool], str]] = None - - -def getchar(echo: bool = False) -> str: - """Fetches a single character from the terminal and returns it. This - will always return a unicode character and under certain rare - circumstances this might return more than one character. The - situations which more than one character is returned is when for - whatever reason multiple characters end up in the terminal buffer or - standard input was not actually a terminal. - - Note that this will always read from the terminal, even if something - is piped into the standard input. - - Note for Windows: in rare cases when typing non-ASCII characters, this - function might wait for a second character and then return both at once. - This is because certain Unicode characters look like special-key markers. - - .. versionadded:: 2.0 - - :param echo: if set to `True`, the character read will also show up on - the terminal. The default is to not show it. - """ - global _getchar - - if _getchar is None: - from ._termui_impl import getchar as f - - _getchar = f - - return _getchar(echo) - - -def raw_terminal() -> t.ContextManager[int]: - from ._termui_impl import raw_terminal as f - - return f() - - -def pause(info: t.Optional[str] = None, err: bool = False) -> None: - """This command stops execution and waits for the user to press any - key to continue. This is similar to the Windows batch "pause" - command. If the program is not run through a terminal, this command - will instead do nothing. - - .. versionadded:: 2.0 - - .. versionadded:: 4.0 - Added the `err` parameter. - - :param info: The message to print before pausing. Defaults to - ``"Press any key to continue..."``. - :param err: if set to message goes to ``stderr`` instead of - ``stdout``, the same as with echo. - """ - if not isatty(sys.stdin) or not isatty(sys.stdout): - return - - if info is None: - info = _("Press any key to continue...") - - try: - if info: - echo(info, nl=False, err=err) - try: - getchar() - except (KeyboardInterrupt, EOFError): - pass - finally: - if info: - echo(err=err) diff --git a/venv/Lib/site-packages/click/testing.py b/venv/Lib/site-packages/click/testing.py deleted file mode 100644 index 772b215..0000000 --- a/venv/Lib/site-packages/click/testing.py +++ /dev/null @@ -1,483 +0,0 @@ -import contextlib -import io -import os -import shlex -import shutil -import sys -import tempfile -import typing as t -from types import TracebackType - -from . import _compat -from . import formatting -from . import termui -from . import utils -from ._compat import _find_binary_reader - -if t.TYPE_CHECKING: - from .core import BaseCommand - - -class EchoingStdin: - def __init__(self, input: t.BinaryIO, output: t.BinaryIO) -> None: - self._input = input - self._output = output - self._paused = False - - def __getattr__(self, x: str) -> t.Any: - return getattr(self._input, x) - - def _echo(self, rv: bytes) -> bytes: - if not self._paused: - self._output.write(rv) - - return rv - - def read(self, n: int = -1) -> bytes: - return self._echo(self._input.read(n)) - - def read1(self, n: int = -1) -> bytes: - return self._echo(self._input.read1(n)) # type: ignore - - def readline(self, n: int = -1) -> bytes: - return self._echo(self._input.readline(n)) - - def readlines(self) -> t.List[bytes]: - return [self._echo(x) for x in self._input.readlines()] - - def __iter__(self) -> t.Iterator[bytes]: - return iter(self._echo(x) for x in self._input) - - def __repr__(self) -> str: - return repr(self._input) - - -@contextlib.contextmanager -def _pause_echo(stream: t.Optional[EchoingStdin]) -> t.Iterator[None]: - if stream is None: - yield - else: - stream._paused = True - yield - stream._paused = False - - -class _NamedTextIOWrapper(io.TextIOWrapper): - def __init__( - self, buffer: t.BinaryIO, name: str, mode: str, **kwargs: t.Any - ) -> None: - super().__init__(buffer, **kwargs) - self._name = name - self._mode = mode - - @property - def name(self) -> str: - return self._name - - @property - def mode(self) -> str: - return self._mode - - -def make_input_stream( - input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]], charset: str -) -> t.BinaryIO: - # Is already an input stream. - if hasattr(input, "read"): - rv = _find_binary_reader(t.cast(t.IO[t.Any], input)) - - if rv is not None: - return rv - - raise TypeError("Could not find binary reader for input stream.") - - if input is None: - input = b"" - elif isinstance(input, str): - input = input.encode(charset) - - return io.BytesIO(input) - - -class Result: - """Holds the captured result of an invoked CLI script.""" - - def __init__( - self, - runner: "CliRunner", - stdout_bytes: bytes, - stderr_bytes: t.Optional[bytes], - return_value: t.Any, - exit_code: int, - exception: t.Optional[BaseException], - exc_info: t.Optional[ - t.Tuple[t.Type[BaseException], BaseException, TracebackType] - ] = None, - ): - #: The runner that created the result - self.runner = runner - #: The standard output as bytes. - self.stdout_bytes = stdout_bytes - #: The standard error as bytes, or None if not available - self.stderr_bytes = stderr_bytes - #: The value returned from the invoked command. - #: - #: .. versionadded:: 8.0 - self.return_value = return_value - #: The exit code as integer. - self.exit_code = exit_code - #: The exception that happened if one did. - self.exception = exception - #: The traceback - self.exc_info = exc_info - - @property - def output(self) -> str: - """The (standard) output as unicode string.""" - return self.stdout - - @property - def stdout(self) -> str: - """The standard output as unicode string.""" - return self.stdout_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - @property - def stderr(self) -> str: - """The standard error as unicode string.""" - if self.stderr_bytes is None: - raise ValueError("stderr not separately captured") - return self.stderr_bytes.decode(self.runner.charset, "replace").replace( - "\r\n", "\n" - ) - - def __repr__(self) -> str: - exc_str = repr(self.exception) if self.exception else "okay" - return f"<{type(self).__name__} {exc_str}>" - - -class CliRunner: - """The CLI runner provides functionality to invoke a Click command line - script for unittesting purposes in a isolated environment. This only - works in single-threaded systems without any concurrency as it changes the - global interpreter state. - - :param charset: the character set for the input and output data. - :param env: a dictionary with environment variables for overriding. - :param echo_stdin: if this is set to `True`, then reading from stdin writes - to stdout. This is useful for showing examples in - some circumstances. Note that regular prompts - will automatically echo the input. - :param mix_stderr: if this is set to `False`, then stdout and stderr are - preserved as independent streams. This is useful for - Unix-philosophy apps that have predictable stdout and - noisy stderr, such that each may be measured - independently - """ - - def __init__( - self, - charset: str = "utf-8", - env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, - echo_stdin: bool = False, - mix_stderr: bool = True, - ) -> None: - self.charset = charset - self.env: t.Mapping[str, t.Optional[str]] = env or {} - self.echo_stdin = echo_stdin - self.mix_stderr = mix_stderr - - def get_default_prog_name(self, cli: "BaseCommand") -> str: - """Given a command object it will return the default program name - for it. The default is the `name` attribute or ``"root"`` if not - set. - """ - return cli.name or "root" - - def make_env( - self, overrides: t.Optional[t.Mapping[str, t.Optional[str]]] = None - ) -> t.Mapping[str, t.Optional[str]]: - """Returns the environment overrides for invoking a script.""" - rv = dict(self.env) - if overrides: - rv.update(overrides) - return rv - - @contextlib.contextmanager - def isolation( - self, - input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, - env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, - color: bool = False, - ) -> t.Iterator[t.Tuple[io.BytesIO, t.Optional[io.BytesIO]]]: - """A context manager that sets up the isolation for invoking of a - command line tool. This sets up stdin with the given input data - and `os.environ` with the overrides from the given dictionary. - This also rebinds some internals in Click to be mocked (like the - prompt functionality). - - This is automatically done in the :meth:`invoke` method. - - :param input: the input stream to put into sys.stdin. - :param env: the environment overrides as dictionary. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - - .. versionchanged:: 8.0 - ``stderr`` is opened with ``errors="backslashreplace"`` - instead of the default ``"strict"``. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. - """ - bytes_input = make_input_stream(input, self.charset) - echo_input = None - - old_stdin = sys.stdin - old_stdout = sys.stdout - old_stderr = sys.stderr - old_forced_width = formatting.FORCED_WIDTH - formatting.FORCED_WIDTH = 80 - - env = self.make_env(env) - - bytes_output = io.BytesIO() - - if self.echo_stdin: - bytes_input = echo_input = t.cast( - t.BinaryIO, EchoingStdin(bytes_input, bytes_output) - ) - - sys.stdin = text_input = _NamedTextIOWrapper( - bytes_input, encoding=self.charset, name="", mode="r" - ) - - if self.echo_stdin: - # Force unbuffered reads, otherwise TextIOWrapper reads a - # large chunk which is echoed early. - text_input._CHUNK_SIZE = 1 # type: ignore - - sys.stdout = _NamedTextIOWrapper( - bytes_output, encoding=self.charset, name="", mode="w" - ) - - bytes_error = None - if self.mix_stderr: - sys.stderr = sys.stdout - else: - bytes_error = io.BytesIO() - sys.stderr = _NamedTextIOWrapper( - bytes_error, - encoding=self.charset, - name="", - mode="w", - errors="backslashreplace", - ) - - @_pause_echo(echo_input) # type: ignore - def visible_input(prompt: t.Optional[str] = None) -> str: - sys.stdout.write(prompt or "") - val = text_input.readline().rstrip("\r\n") - sys.stdout.write(f"{val}\n") - sys.stdout.flush() - return val - - @_pause_echo(echo_input) # type: ignore - def hidden_input(prompt: t.Optional[str] = None) -> str: - sys.stdout.write(f"{prompt or ''}\n") - sys.stdout.flush() - return text_input.readline().rstrip("\r\n") - - @_pause_echo(echo_input) # type: ignore - def _getchar(echo: bool) -> str: - char = sys.stdin.read(1) - - if echo: - sys.stdout.write(char) - - sys.stdout.flush() - return char - - default_color = color - - def should_strip_ansi( - stream: t.Optional[t.IO[t.Any]] = None, color: t.Optional[bool] = None - ) -> bool: - if color is None: - return not default_color - return not color - - old_visible_prompt_func = termui.visible_prompt_func - old_hidden_prompt_func = termui.hidden_prompt_func - old__getchar_func = termui._getchar - old_should_strip_ansi = utils.should_strip_ansi # type: ignore - old__compat_should_strip_ansi = _compat.should_strip_ansi - termui.visible_prompt_func = visible_input - termui.hidden_prompt_func = hidden_input - termui._getchar = _getchar - utils.should_strip_ansi = should_strip_ansi # type: ignore - _compat.should_strip_ansi = should_strip_ansi - - old_env = {} - try: - for key, value in env.items(): - old_env[key] = os.environ.get(key) - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - yield (bytes_output, bytes_error) - finally: - for key, value in old_env.items(): - if value is None: - try: - del os.environ[key] - except Exception: - pass - else: - os.environ[key] = value - sys.stdout = old_stdout - sys.stderr = old_stderr - sys.stdin = old_stdin - termui.visible_prompt_func = old_visible_prompt_func - termui.hidden_prompt_func = old_hidden_prompt_func - termui._getchar = old__getchar_func - utils.should_strip_ansi = old_should_strip_ansi # type: ignore - _compat.should_strip_ansi = old__compat_should_strip_ansi - formatting.FORCED_WIDTH = old_forced_width - - def invoke( - self, - cli: "BaseCommand", - args: t.Optional[t.Union[str, t.Sequence[str]]] = None, - input: t.Optional[t.Union[str, bytes, t.IO[t.Any]]] = None, - env: t.Optional[t.Mapping[str, t.Optional[str]]] = None, - catch_exceptions: bool = True, - color: bool = False, - **extra: t.Any, - ) -> Result: - """Invokes a command in an isolated environment. The arguments are - forwarded directly to the command line script, the `extra` keyword - arguments are passed to the :meth:`~clickpkg.Command.main` function of - the command. - - This returns a :class:`Result` object. - - :param cli: the command to invoke - :param args: the arguments to invoke. It may be given as an iterable - or a string. When given as string it will be interpreted - as a Unix shell command. More details at - :func:`shlex.split`. - :param input: the input data for `sys.stdin`. - :param env: the environment overrides. - :param catch_exceptions: Whether to catch any other exceptions than - ``SystemExit``. - :param extra: the keyword arguments to pass to :meth:`main`. - :param color: whether the output should contain color codes. The - application can still override this explicitly. - - .. versionchanged:: 8.0 - The result object has the ``return_value`` attribute with - the value returned from the invoked command. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. - - .. versionchanged:: 3.0 - Added the ``catch_exceptions`` parameter. - - .. versionchanged:: 3.0 - The result object has the ``exc_info`` attribute with the - traceback if available. - """ - exc_info = None - with self.isolation(input=input, env=env, color=color) as outstreams: - return_value = None - exception: t.Optional[BaseException] = None - exit_code = 0 - - if isinstance(args, str): - args = shlex.split(args) - - try: - prog_name = extra.pop("prog_name") - except KeyError: - prog_name = self.get_default_prog_name(cli) - - try: - return_value = cli.main(args=args or (), prog_name=prog_name, **extra) - except SystemExit as e: - exc_info = sys.exc_info() - e_code = t.cast(t.Optional[t.Union[int, t.Any]], e.code) - - if e_code is None: - e_code = 0 - - if e_code != 0: - exception = e - - if not isinstance(e_code, int): - sys.stdout.write(str(e_code)) - sys.stdout.write("\n") - e_code = 1 - - exit_code = e_code - - except Exception as e: - if not catch_exceptions: - raise - exception = e - exit_code = 1 - exc_info = sys.exc_info() - finally: - sys.stdout.flush() - stdout = outstreams[0].getvalue() - if self.mix_stderr: - stderr = None - else: - stderr = outstreams[1].getvalue() # type: ignore - - return Result( - runner=self, - stdout_bytes=stdout, - stderr_bytes=stderr, - return_value=return_value, - exit_code=exit_code, - exception=exception, - exc_info=exc_info, # type: ignore - ) - - @contextlib.contextmanager - def isolated_filesystem( - self, temp_dir: t.Optional[t.Union[str, "os.PathLike[str]"]] = None - ) -> t.Iterator[str]: - """A context manager that creates a temporary directory and - changes the current working directory to it. This isolates tests - that affect the contents of the CWD to prevent them from - interfering with each other. - - :param temp_dir: Create the temporary directory under this - directory. If given, the created directory is not removed - when exiting. - - .. versionchanged:: 8.0 - Added the ``temp_dir`` parameter. - """ - cwd = os.getcwd() - dt = tempfile.mkdtemp(dir=temp_dir) - os.chdir(dt) - - try: - yield dt - finally: - os.chdir(cwd) - - if temp_dir is None: - try: - shutil.rmtree(dt) - except OSError: - pass diff --git a/venv/Lib/site-packages/click/types.py b/venv/Lib/site-packages/click/types.py deleted file mode 100644 index a70fd58..0000000 --- a/venv/Lib/site-packages/click/types.py +++ /dev/null @@ -1,1093 +0,0 @@ -import os -import stat -import sys -import typing as t -from datetime import datetime -from gettext import gettext as _ -from gettext import ngettext - -from ._compat import _get_argv_encoding -from ._compat import open_stream -from .exceptions import BadParameter -from .utils import format_filename -from .utils import LazyFile -from .utils import safecall - -if t.TYPE_CHECKING: - import typing_extensions as te - - from .core import Context - from .core import Parameter - from .shell_completion import CompletionItem - - -class ParamType: - """Represents the type of a parameter. Validates and converts values - from the command line or Python into the correct type. - - To implement a custom type, subclass and implement at least the - following: - - - The :attr:`name` class attribute must be set. - - Calling an instance of the type with ``None`` must return - ``None``. This is already implemented by default. - - :meth:`convert` must convert string values to the correct type. - - :meth:`convert` must accept values that are already the correct - type. - - It must be able to convert a value if the ``ctx`` and ``param`` - arguments are ``None``. This can occur when converting prompt - input. - """ - - is_composite: t.ClassVar[bool] = False - arity: t.ClassVar[int] = 1 - - #: the descriptive name of this type - name: str - - #: if a list of this type is expected and the value is pulled from a - #: string environment variable, this is what splits it up. `None` - #: means any whitespace. For all parameters the general rule is that - #: whitespace splits them up. The exception are paths and files which - #: are split by ``os.path.pathsep`` by default (":" on Unix and ";" on - #: Windows). - envvar_list_splitter: t.ClassVar[t.Optional[str]] = None - - def to_info_dict(self) -> t.Dict[str, t.Any]: - """Gather information that could be useful for a tool generating - user-facing documentation. - - Use :meth:`click.Context.to_info_dict` to traverse the entire - CLI structure. - - .. versionadded:: 8.0 - """ - # The class name without the "ParamType" suffix. - param_type = type(self).__name__.partition("ParamType")[0] - param_type = param_type.partition("ParameterType")[0] - - # Custom subclasses might not remember to set a name. - if hasattr(self, "name"): - name = self.name - else: - name = param_type - - return {"param_type": param_type, "name": name} - - def __call__( - self, - value: t.Any, - param: t.Optional["Parameter"] = None, - ctx: t.Optional["Context"] = None, - ) -> t.Any: - if value is not None: - return self.convert(value, param, ctx) - - def get_metavar(self, param: "Parameter") -> t.Optional[str]: - """Returns the metavar default for this param if it provides one.""" - - def get_missing_message(self, param: "Parameter") -> t.Optional[str]: - """Optionally might return extra information about a missing - parameter. - - .. versionadded:: 2.0 - """ - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - """Convert the value to the correct type. This is not called if - the value is ``None`` (the missing value). - - This must accept string values from the command line, as well as - values that are already the correct type. It may also convert - other compatible types. - - The ``param`` and ``ctx`` arguments may be ``None`` in certain - situations, such as when converting prompt input. - - If the value cannot be converted, call :meth:`fail` with a - descriptive message. - - :param value: The value to convert. - :param param: The parameter that is using this type to convert - its value. May be ``None``. - :param ctx: The current context that arrived at this value. May - be ``None``. - """ - return value - - def split_envvar_value(self, rv: str) -> t.Sequence[str]: - """Given a value from an environment variable this splits it up - into small chunks depending on the defined envvar list splitter. - - If the splitter is set to `None`, which means that whitespace splits, - then leading and trailing whitespace is ignored. Otherwise, leading - and trailing splitters usually lead to empty items being included. - """ - return (rv or "").split(self.envvar_list_splitter) - - def fail( - self, - message: str, - param: t.Optional["Parameter"] = None, - ctx: t.Optional["Context"] = None, - ) -> "t.NoReturn": - """Helper method to fail with an invalid value message.""" - raise BadParameter(message, ctx=ctx, param=param) - - def shell_complete( - self, ctx: "Context", param: "Parameter", incomplete: str - ) -> t.List["CompletionItem"]: - """Return a list of - :class:`~click.shell_completion.CompletionItem` objects for the - incomplete value. Most types do not provide completions, but - some do, and this allows custom types to provide custom - completions as well. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - return [] - - -class CompositeParamType(ParamType): - is_composite = True - - @property - def arity(self) -> int: # type: ignore - raise NotImplementedError() - - -class FuncParamType(ParamType): - def __init__(self, func: t.Callable[[t.Any], t.Any]) -> None: - self.name: str = func.__name__ - self.func = func - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict["func"] = self.func - return info_dict - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - try: - return self.func(value) - except ValueError: - try: - value = str(value) - except UnicodeError: - value = value.decode("utf-8", "replace") - - self.fail(value, param, ctx) - - -class UnprocessedParamType(ParamType): - name = "text" - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - return value - - def __repr__(self) -> str: - return "UNPROCESSED" - - -class StringParamType(ParamType): - name = "text" - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - if isinstance(value, bytes): - enc = _get_argv_encoding() - try: - value = value.decode(enc) - except UnicodeError: - fs_enc = sys.getfilesystemencoding() - if fs_enc != enc: - try: - value = value.decode(fs_enc) - except UnicodeError: - value = value.decode("utf-8", "replace") - else: - value = value.decode("utf-8", "replace") - return value - return str(value) - - def __repr__(self) -> str: - return "STRING" - - -class Choice(ParamType): - """The choice type allows a value to be checked against a fixed set - of supported values. All of these values have to be strings. - - You should only pass a list or tuple of choices. Other iterables - (like generators) may lead to surprising results. - - The resulting value will always be one of the originally passed choices - regardless of ``case_sensitive`` or any ``ctx.token_normalize_func`` - being specified. - - See :ref:`choice-opts` for an example. - - :param case_sensitive: Set to false to make choices case - insensitive. Defaults to true. - """ - - name = "choice" - - def __init__(self, choices: t.Sequence[str], case_sensitive: bool = True) -> None: - self.choices = choices - self.case_sensitive = case_sensitive - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict["choices"] = self.choices - info_dict["case_sensitive"] = self.case_sensitive - return info_dict - - def get_metavar(self, param: "Parameter") -> str: - choices_str = "|".join(self.choices) - - # Use curly braces to indicate a required argument. - if param.required and param.param_type_name == "argument": - return f"{{{choices_str}}}" - - # Use square braces to indicate an option or optional argument. - return f"[{choices_str}]" - - def get_missing_message(self, param: "Parameter") -> str: - return _("Choose from:\n\t{choices}").format(choices=",\n\t".join(self.choices)) - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - # Match through normalization and case sensitivity - # first do token_normalize_func, then lowercase - # preserve original `value` to produce an accurate message in - # `self.fail` - normed_value = value - normed_choices = {choice: choice for choice in self.choices} - - if ctx is not None and ctx.token_normalize_func is not None: - normed_value = ctx.token_normalize_func(value) - normed_choices = { - ctx.token_normalize_func(normed_choice): original - for normed_choice, original in normed_choices.items() - } - - if not self.case_sensitive: - normed_value = normed_value.casefold() - normed_choices = { - normed_choice.casefold(): original - for normed_choice, original in normed_choices.items() - } - - if normed_value in normed_choices: - return normed_choices[normed_value] - - choices_str = ", ".join(map(repr, self.choices)) - self.fail( - ngettext( - "{value!r} is not {choice}.", - "{value!r} is not one of {choices}.", - len(self.choices), - ).format(value=value, choice=choices_str, choices=choices_str), - param, - ctx, - ) - - def __repr__(self) -> str: - return f"Choice({list(self.choices)})" - - def shell_complete( - self, ctx: "Context", param: "Parameter", incomplete: str - ) -> t.List["CompletionItem"]: - """Complete choices that start with the incomplete value. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - str_choices = map(str, self.choices) - - if self.case_sensitive: - matched = (c for c in str_choices if c.startswith(incomplete)) - else: - incomplete = incomplete.lower() - matched = (c for c in str_choices if c.lower().startswith(incomplete)) - - return [CompletionItem(c) for c in matched] - - -class DateTime(ParamType): - """The DateTime type converts date strings into `datetime` objects. - - The format strings which are checked are configurable, but default to some - common (non-timezone aware) ISO 8601 formats. - - When specifying *DateTime* formats, you should only pass a list or a tuple. - Other iterables, like generators, may lead to surprising results. - - The format strings are processed using ``datetime.strptime``, and this - consequently defines the format strings which are allowed. - - Parsing is tried using each format, in order, and the first format which - parses successfully is used. - - :param formats: A list or tuple of date format strings, in the order in - which they should be tried. Defaults to - ``'%Y-%m-%d'``, ``'%Y-%m-%dT%H:%M:%S'``, - ``'%Y-%m-%d %H:%M:%S'``. - """ - - name = "datetime" - - def __init__(self, formats: t.Optional[t.Sequence[str]] = None): - self.formats: t.Sequence[str] = formats or [ - "%Y-%m-%d", - "%Y-%m-%dT%H:%M:%S", - "%Y-%m-%d %H:%M:%S", - ] - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict["formats"] = self.formats - return info_dict - - def get_metavar(self, param: "Parameter") -> str: - return f"[{'|'.join(self.formats)}]" - - def _try_to_convert_date(self, value: t.Any, format: str) -> t.Optional[datetime]: - try: - return datetime.strptime(value, format) - except ValueError: - return None - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - if isinstance(value, datetime): - return value - - for format in self.formats: - converted = self._try_to_convert_date(value, format) - - if converted is not None: - return converted - - formats_str = ", ".join(map(repr, self.formats)) - self.fail( - ngettext( - "{value!r} does not match the format {format}.", - "{value!r} does not match the formats {formats}.", - len(self.formats), - ).format(value=value, format=formats_str, formats=formats_str), - param, - ctx, - ) - - def __repr__(self) -> str: - return "DateTime" - - -class _NumberParamTypeBase(ParamType): - _number_class: t.ClassVar[t.Type[t.Any]] - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - try: - return self._number_class(value) - except ValueError: - self.fail( - _("{value!r} is not a valid {number_type}.").format( - value=value, number_type=self.name - ), - param, - ctx, - ) - - -class _NumberRangeBase(_NumberParamTypeBase): - def __init__( - self, - min: t.Optional[float] = None, - max: t.Optional[float] = None, - min_open: bool = False, - max_open: bool = False, - clamp: bool = False, - ) -> None: - self.min = min - self.max = max - self.min_open = min_open - self.max_open = max_open - self.clamp = clamp - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict.update( - min=self.min, - max=self.max, - min_open=self.min_open, - max_open=self.max_open, - clamp=self.clamp, - ) - return info_dict - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - import operator - - rv = super().convert(value, param, ctx) - lt_min: bool = self.min is not None and ( - operator.le if self.min_open else operator.lt - )(rv, self.min) - gt_max: bool = self.max is not None and ( - operator.ge if self.max_open else operator.gt - )(rv, self.max) - - if self.clamp: - if lt_min: - return self._clamp(self.min, 1, self.min_open) # type: ignore - - if gt_max: - return self._clamp(self.max, -1, self.max_open) # type: ignore - - if lt_min or gt_max: - self.fail( - _("{value} is not in the range {range}.").format( - value=rv, range=self._describe_range() - ), - param, - ctx, - ) - - return rv - - def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: - """Find the valid value to clamp to bound in the given - direction. - - :param bound: The boundary value. - :param dir: 1 or -1 indicating the direction to move. - :param open: If true, the range does not include the bound. - """ - raise NotImplementedError - - def _describe_range(self) -> str: - """Describe the range for use in help text.""" - if self.min is None: - op = "<" if self.max_open else "<=" - return f"x{op}{self.max}" - - if self.max is None: - op = ">" if self.min_open else ">=" - return f"x{op}{self.min}" - - lop = "<" if self.min_open else "<=" - rop = "<" if self.max_open else "<=" - return f"{self.min}{lop}x{rop}{self.max}" - - def __repr__(self) -> str: - clamp = " clamped" if self.clamp else "" - return f"<{type(self).__name__} {self._describe_range()}{clamp}>" - - -class IntParamType(_NumberParamTypeBase): - name = "integer" - _number_class = int - - def __repr__(self) -> str: - return "INT" - - -class IntRange(_NumberRangeBase, IntParamType): - """Restrict an :data:`click.INT` value to a range of accepted - values. See :ref:`ranges`. - - If ``min`` or ``max`` are not passed, any value is accepted in that - direction. If ``min_open`` or ``max_open`` are enabled, the - corresponding boundary is not included in the range. - - If ``clamp`` is enabled, a value outside the range is clamped to the - boundary instead of failing. - - .. versionchanged:: 8.0 - Added the ``min_open`` and ``max_open`` parameters. - """ - - name = "integer range" - - def _clamp( # type: ignore - self, bound: int, dir: "te.Literal[1, -1]", open: bool - ) -> int: - if not open: - return bound - - return bound + dir - - -class FloatParamType(_NumberParamTypeBase): - name = "float" - _number_class = float - - def __repr__(self) -> str: - return "FLOAT" - - -class FloatRange(_NumberRangeBase, FloatParamType): - """Restrict a :data:`click.FLOAT` value to a range of accepted - values. See :ref:`ranges`. - - If ``min`` or ``max`` are not passed, any value is accepted in that - direction. If ``min_open`` or ``max_open`` are enabled, the - corresponding boundary is not included in the range. - - If ``clamp`` is enabled, a value outside the range is clamped to the - boundary instead of failing. This is not supported if either - boundary is marked ``open``. - - .. versionchanged:: 8.0 - Added the ``min_open`` and ``max_open`` parameters. - """ - - name = "float range" - - def __init__( - self, - min: t.Optional[float] = None, - max: t.Optional[float] = None, - min_open: bool = False, - max_open: bool = False, - clamp: bool = False, - ) -> None: - super().__init__( - min=min, max=max, min_open=min_open, max_open=max_open, clamp=clamp - ) - - if (min_open or max_open) and clamp: - raise TypeError("Clamping is not supported for open bounds.") - - def _clamp(self, bound: float, dir: "te.Literal[1, -1]", open: bool) -> float: - if not open: - return bound - - # Could use Python 3.9's math.nextafter here, but clamping an - # open float range doesn't seem to be particularly useful. It's - # left up to the user to write a callback to do it if needed. - raise RuntimeError("Clamping is not supported for open bounds.") - - -class BoolParamType(ParamType): - name = "boolean" - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - if value in {False, True}: - return bool(value) - - norm = value.strip().lower() - - if norm in {"1", "true", "t", "yes", "y", "on"}: - return True - - if norm in {"0", "false", "f", "no", "n", "off"}: - return False - - self.fail( - _("{value!r} is not a valid boolean.").format(value=value), param, ctx - ) - - def __repr__(self) -> str: - return "BOOL" - - -class UUIDParameterType(ParamType): - name = "uuid" - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - import uuid - - if isinstance(value, uuid.UUID): - return value - - value = value.strip() - - try: - return uuid.UUID(value) - except ValueError: - self.fail( - _("{value!r} is not a valid UUID.").format(value=value), param, ctx - ) - - def __repr__(self) -> str: - return "UUID" - - -class File(ParamType): - """Declares a parameter to be a file for reading or writing. The file - is automatically closed once the context tears down (after the command - finished working). - - Files can be opened for reading or writing. The special value ``-`` - indicates stdin or stdout depending on the mode. - - By default, the file is opened for reading text data, but it can also be - opened in binary mode or for writing. The encoding parameter can be used - to force a specific encoding. - - The `lazy` flag controls if the file should be opened immediately or upon - first IO. The default is to be non-lazy for standard input and output - streams as well as files opened for reading, `lazy` otherwise. When opening a - file lazily for reading, it is still opened temporarily for validation, but - will not be held open until first IO. lazy is mainly useful when opening - for writing to avoid creating the file until it is needed. - - Files can also be opened atomically in which case all writes go into a - separate file in the same folder and upon completion the file will - be moved over to the original location. This is useful if a file - regularly read by other users is modified. - - See :ref:`file-args` for more information. - - .. versionchanged:: 2.0 - Added the ``atomic`` parameter. - """ - - name = "filename" - envvar_list_splitter: t.ClassVar[str] = os.path.pathsep - - def __init__( - self, - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - lazy: t.Optional[bool] = None, - atomic: bool = False, - ) -> None: - self.mode = mode - self.encoding = encoding - self.errors = errors - self.lazy = lazy - self.atomic = atomic - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict.update(mode=self.mode, encoding=self.encoding) - return info_dict - - def resolve_lazy_flag(self, value: "t.Union[str, os.PathLike[str]]") -> bool: - if self.lazy is not None: - return self.lazy - if os.fspath(value) == "-": - return False - elif "w" in self.mode: - return True - return False - - def convert( - self, - value: t.Union[str, "os.PathLike[str]", t.IO[t.Any]], - param: t.Optional["Parameter"], - ctx: t.Optional["Context"], - ) -> t.IO[t.Any]: - if _is_file_like(value): - return value - - value = t.cast("t.Union[str, os.PathLike[str]]", value) - - try: - lazy = self.resolve_lazy_flag(value) - - if lazy: - lf = LazyFile( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - - if ctx is not None: - ctx.call_on_close(lf.close_intelligently) - - return t.cast(t.IO[t.Any], lf) - - f, should_close = open_stream( - value, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - - # If a context is provided, we automatically close the file - # at the end of the context execution (or flush out). If a - # context does not exist, it's the caller's responsibility to - # properly close the file. This for instance happens when the - # type is used with prompts. - if ctx is not None: - if should_close: - ctx.call_on_close(safecall(f.close)) - else: - ctx.call_on_close(safecall(f.flush)) - - return f - except OSError as e: - self.fail(f"'{format_filename(value)}': {e.strerror}", param, ctx) - - def shell_complete( - self, ctx: "Context", param: "Parameter", incomplete: str - ) -> t.List["CompletionItem"]: - """Return a special completion marker that tells the completion - system to use the shell to provide file path completions. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - return [CompletionItem(incomplete, type="file")] - - -def _is_file_like(value: t.Any) -> "te.TypeGuard[t.IO[t.Any]]": - return hasattr(value, "read") or hasattr(value, "write") - - -class Path(ParamType): - """The ``Path`` type is similar to the :class:`File` type, but - returns the filename instead of an open file. Various checks can be - enabled to validate the type of file and permissions. - - :param exists: The file or directory needs to exist for the value to - be valid. If this is not set to ``True``, and the file does not - exist, then all further checks are silently skipped. - :param file_okay: Allow a file as a value. - :param dir_okay: Allow a directory as a value. - :param readable: if true, a readable check is performed. - :param writable: if true, a writable check is performed. - :param executable: if true, an executable check is performed. - :param resolve_path: Make the value absolute and resolve any - symlinks. A ``~`` is not expanded, as this is supposed to be - done by the shell only. - :param allow_dash: Allow a single dash as a value, which indicates - a standard stream (but does not open it). Use - :func:`~click.open_file` to handle opening this value. - :param path_type: Convert the incoming path value to this type. If - ``None``, keep Python's default, which is ``str``. Useful to - convert to :class:`pathlib.Path`. - - .. versionchanged:: 8.1 - Added the ``executable`` parameter. - - .. versionchanged:: 8.0 - Allow passing ``path_type=pathlib.Path``. - - .. versionchanged:: 6.0 - Added the ``allow_dash`` parameter. - """ - - envvar_list_splitter: t.ClassVar[str] = os.path.pathsep - - def __init__( - self, - exists: bool = False, - file_okay: bool = True, - dir_okay: bool = True, - writable: bool = False, - readable: bool = True, - resolve_path: bool = False, - allow_dash: bool = False, - path_type: t.Optional[t.Type[t.Any]] = None, - executable: bool = False, - ): - self.exists = exists - self.file_okay = file_okay - self.dir_okay = dir_okay - self.readable = readable - self.writable = writable - self.executable = executable - self.resolve_path = resolve_path - self.allow_dash = allow_dash - self.type = path_type - - if self.file_okay and not self.dir_okay: - self.name: str = _("file") - elif self.dir_okay and not self.file_okay: - self.name = _("directory") - else: - self.name = _("path") - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict.update( - exists=self.exists, - file_okay=self.file_okay, - dir_okay=self.dir_okay, - writable=self.writable, - readable=self.readable, - allow_dash=self.allow_dash, - ) - return info_dict - - def coerce_path_result( - self, value: "t.Union[str, os.PathLike[str]]" - ) -> "t.Union[str, bytes, os.PathLike[str]]": - if self.type is not None and not isinstance(value, self.type): - if self.type is str: - return os.fsdecode(value) - elif self.type is bytes: - return os.fsencode(value) - else: - return t.cast("os.PathLike[str]", self.type(value)) - - return value - - def convert( - self, - value: "t.Union[str, os.PathLike[str]]", - param: t.Optional["Parameter"], - ctx: t.Optional["Context"], - ) -> "t.Union[str, bytes, os.PathLike[str]]": - rv = value - - is_dash = self.file_okay and self.allow_dash and rv in (b"-", "-") - - if not is_dash: - if self.resolve_path: - # os.path.realpath doesn't resolve symlinks on Windows - # until Python 3.8. Use pathlib for now. - import pathlib - - rv = os.fsdecode(pathlib.Path(rv).resolve()) - - try: - st = os.stat(rv) - except OSError: - if not self.exists: - return self.coerce_path_result(rv) - self.fail( - _("{name} {filename!r} does not exist.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if not self.file_okay and stat.S_ISREG(st.st_mode): - self.fail( - _("{name} {filename!r} is a file.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - if not self.dir_okay and stat.S_ISDIR(st.st_mode): - self.fail( - _("{name} {filename!r} is a directory.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.readable and not os.access(rv, os.R_OK): - self.fail( - _("{name} {filename!r} is not readable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.writable and not os.access(rv, os.W_OK): - self.fail( - _("{name} {filename!r} is not writable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - if self.executable and not os.access(value, os.X_OK): - self.fail( - _("{name} {filename!r} is not executable.").format( - name=self.name.title(), filename=format_filename(value) - ), - param, - ctx, - ) - - return self.coerce_path_result(rv) - - def shell_complete( - self, ctx: "Context", param: "Parameter", incomplete: str - ) -> t.List["CompletionItem"]: - """Return a special completion marker that tells the completion - system to use the shell to provide path completions for only - directories or any paths. - - :param ctx: Invocation context for this command. - :param param: The parameter that is requesting completion. - :param incomplete: Value being completed. May be empty. - - .. versionadded:: 8.0 - """ - from click.shell_completion import CompletionItem - - type = "dir" if self.dir_okay and not self.file_okay else "file" - return [CompletionItem(incomplete, type=type)] - - -class Tuple(CompositeParamType): - """The default behavior of Click is to apply a type on a value directly. - This works well in most cases, except for when `nargs` is set to a fixed - count and different types should be used for different items. In this - case the :class:`Tuple` type can be used. This type can only be used - if `nargs` is set to a fixed number. - - For more information see :ref:`tuple-type`. - - This can be selected by using a Python tuple literal as a type. - - :param types: a list of types that should be used for the tuple items. - """ - - def __init__(self, types: t.Sequence[t.Union[t.Type[t.Any], ParamType]]) -> None: - self.types: t.Sequence[ParamType] = [convert_type(ty) for ty in types] - - def to_info_dict(self) -> t.Dict[str, t.Any]: - info_dict = super().to_info_dict() - info_dict["types"] = [t.to_info_dict() for t in self.types] - return info_dict - - @property - def name(self) -> str: # type: ignore - return f"<{' '.join(ty.name for ty in self.types)}>" - - @property - def arity(self) -> int: # type: ignore - return len(self.types) - - def convert( - self, value: t.Any, param: t.Optional["Parameter"], ctx: t.Optional["Context"] - ) -> t.Any: - len_type = len(self.types) - len_value = len(value) - - if len_value != len_type: - self.fail( - ngettext( - "{len_type} values are required, but {len_value} was given.", - "{len_type} values are required, but {len_value} were given.", - len_value, - ).format(len_type=len_type, len_value=len_value), - param=param, - ctx=ctx, - ) - - return tuple(ty(x, param, ctx) for ty, x in zip(self.types, value)) - - -def convert_type(ty: t.Optional[t.Any], default: t.Optional[t.Any] = None) -> ParamType: - """Find the most appropriate :class:`ParamType` for the given Python - type. If the type isn't provided, it can be inferred from a default - value. - """ - guessed_type = False - - if ty is None and default is not None: - if isinstance(default, (tuple, list)): - # If the default is empty, ty will remain None and will - # return STRING. - if default: - item = default[0] - - # A tuple of tuples needs to detect the inner types. - # Can't call convert recursively because that would - # incorrectly unwind the tuple to a single type. - if isinstance(item, (tuple, list)): - ty = tuple(map(type, item)) - else: - ty = type(item) - else: - ty = type(default) - - guessed_type = True - - if isinstance(ty, tuple): - return Tuple(ty) - - if isinstance(ty, ParamType): - return ty - - if ty is str or ty is None: - return STRING - - if ty is int: - return INT - - if ty is float: - return FLOAT - - if ty is bool: - return BOOL - - if guessed_type: - return STRING - - if __debug__: - try: - if issubclass(ty, ParamType): - raise AssertionError( - f"Attempted to use an uninstantiated parameter type ({ty})." - ) - except TypeError: - # ty is an instance (correct), so issubclass fails. - pass - - return FuncParamType(ty) - - -#: A dummy parameter type that just does nothing. From a user's -#: perspective this appears to just be the same as `STRING` but -#: internally no string conversion takes place if the input was bytes. -#: This is usually useful when working with file paths as they can -#: appear in bytes and unicode. -#: -#: For path related uses the :class:`Path` type is a better choice but -#: there are situations where an unprocessed type is useful which is why -#: it is is provided. -#: -#: .. versionadded:: 4.0 -UNPROCESSED = UnprocessedParamType() - -#: A unicode string parameter type which is the implicit default. This -#: can also be selected by using ``str`` as type. -STRING = StringParamType() - -#: An integer parameter. This can also be selected by using ``int`` as -#: type. -INT = IntParamType() - -#: A floating point value parameter. This can also be selected by using -#: ``float`` as type. -FLOAT = FloatParamType() - -#: A boolean parameter. This is the default for boolean flags. This can -#: also be selected by using ``bool`` as a type. -BOOL = BoolParamType() - -#: A UUID parameter. -UUID = UUIDParameterType() diff --git a/venv/Lib/site-packages/click/utils.py b/venv/Lib/site-packages/click/utils.py deleted file mode 100644 index 836c6f2..0000000 --- a/venv/Lib/site-packages/click/utils.py +++ /dev/null @@ -1,624 +0,0 @@ -import os -import re -import sys -import typing as t -from functools import update_wrapper -from types import ModuleType -from types import TracebackType - -from ._compat import _default_text_stderr -from ._compat import _default_text_stdout -from ._compat import _find_binary_writer -from ._compat import auto_wrap_for_ansi -from ._compat import binary_streams -from ._compat import open_stream -from ._compat import should_strip_ansi -from ._compat import strip_ansi -from ._compat import text_streams -from ._compat import WIN -from .globals import resolve_color_default - -if t.TYPE_CHECKING: - import typing_extensions as te - - P = te.ParamSpec("P") - -R = t.TypeVar("R") - - -def _posixify(name: str) -> str: - return "-".join(name.split()).lower() - - -def safecall(func: "t.Callable[P, R]") -> "t.Callable[P, t.Optional[R]]": - """Wraps a function so that it swallows exceptions.""" - - def wrapper(*args: "P.args", **kwargs: "P.kwargs") -> t.Optional[R]: - try: - return func(*args, **kwargs) - except Exception: - pass - return None - - return update_wrapper(wrapper, func) - - -def make_str(value: t.Any) -> str: - """Converts a value into a valid string.""" - if isinstance(value, bytes): - try: - return value.decode(sys.getfilesystemencoding()) - except UnicodeError: - return value.decode("utf-8", "replace") - return str(value) - - -def make_default_short_help(help: str, max_length: int = 45) -> str: - """Returns a condensed version of help string.""" - # Consider only the first paragraph. - paragraph_end = help.find("\n\n") - - if paragraph_end != -1: - help = help[:paragraph_end] - - # Collapse newlines, tabs, and spaces. - words = help.split() - - if not words: - return "" - - # The first paragraph started with a "no rewrap" marker, ignore it. - if words[0] == "\b": - words = words[1:] - - total_length = 0 - last_index = len(words) - 1 - - for i, word in enumerate(words): - total_length += len(word) + (i > 0) - - if total_length > max_length: # too long, truncate - break - - if word[-1] == ".": # sentence end, truncate without "..." - return " ".join(words[: i + 1]) - - if total_length == max_length and i != last_index: - break # not at sentence end, truncate with "..." - else: - return " ".join(words) # no truncation needed - - # Account for the length of the suffix. - total_length += len("...") - - # remove words until the length is short enough - while i > 0: - total_length -= len(words[i]) + (i > 0) - - if total_length <= max_length: - break - - i -= 1 - - return " ".join(words[:i]) + "..." - - -class LazyFile: - """A lazy file works like a regular file but it does not fully open - the file but it does perform some basic checks early to see if the - filename parameter does make sense. This is useful for safely opening - files for writing. - """ - - def __init__( - self, - filename: t.Union[str, "os.PathLike[str]"], - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - atomic: bool = False, - ): - self.name: str = os.fspath(filename) - self.mode = mode - self.encoding = encoding - self.errors = errors - self.atomic = atomic - self._f: t.Optional[t.IO[t.Any]] - self.should_close: bool - - if self.name == "-": - self._f, self.should_close = open_stream(filename, mode, encoding, errors) - else: - if "r" in mode: - # Open and close the file in case we're opening it for - # reading so that we can catch at least some errors in - # some cases early. - open(filename, mode).close() - self._f = None - self.should_close = True - - def __getattr__(self, name: str) -> t.Any: - return getattr(self.open(), name) - - def __repr__(self) -> str: - if self._f is not None: - return repr(self._f) - return f"" - - def open(self) -> t.IO[t.Any]: - """Opens the file if it's not yet open. This call might fail with - a :exc:`FileError`. Not handling this error will produce an error - that Click shows. - """ - if self._f is not None: - return self._f - try: - rv, self.should_close = open_stream( - self.name, self.mode, self.encoding, self.errors, atomic=self.atomic - ) - except OSError as e: - from .exceptions import FileError - - raise FileError(self.name, hint=e.strerror) from e - self._f = rv - return rv - - def close(self) -> None: - """Closes the underlying file, no matter what.""" - if self._f is not None: - self._f.close() - - def close_intelligently(self) -> None: - """This function only closes the file if it was opened by the lazy - file wrapper. For instance this will never close stdin. - """ - if self.should_close: - self.close() - - def __enter__(self) -> "LazyFile": - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - self.close_intelligently() - - def __iter__(self) -> t.Iterator[t.AnyStr]: - self.open() - return iter(self._f) # type: ignore - - -class KeepOpenFile: - def __init__(self, file: t.IO[t.Any]) -> None: - self._file: t.IO[t.Any] = file - - def __getattr__(self, name: str) -> t.Any: - return getattr(self._file, name) - - def __enter__(self) -> "KeepOpenFile": - return self - - def __exit__( - self, - exc_type: t.Optional[t.Type[BaseException]], - exc_value: t.Optional[BaseException], - tb: t.Optional[TracebackType], - ) -> None: - pass - - def __repr__(self) -> str: - return repr(self._file) - - def __iter__(self) -> t.Iterator[t.AnyStr]: - return iter(self._file) - - -def echo( - message: t.Optional[t.Any] = None, - file: t.Optional[t.IO[t.Any]] = None, - nl: bool = True, - err: bool = False, - color: t.Optional[bool] = None, -) -> None: - """Print a message and newline to stdout or a file. This should be - used instead of :func:`print` because it provides better support - for different data, files, and environments. - - Compared to :func:`print`, this does the following: - - - Ensures that the output encoding is not misconfigured on Linux. - - Supports Unicode in the Windows console. - - Supports writing to binary outputs, and supports writing bytes - to text outputs. - - Supports colors and styles on Windows. - - Removes ANSI color and style codes if the output does not look - like an interactive terminal. - - Always flushes the output. - - :param message: The string or bytes to output. Other objects are - converted to strings. - :param file: The file to write to. Defaults to ``stdout``. - :param err: Write to ``stderr`` instead of ``stdout``. - :param nl: Print a newline after the message. Enabled by default. - :param color: Force showing or hiding colors and other styles. By - default Click will remove color if the output does not look like - an interactive terminal. - - .. versionchanged:: 6.0 - Support Unicode output on the Windows console. Click does not - modify ``sys.stdout``, so ``sys.stdout.write()`` and ``print()`` - will still not support Unicode. - - .. versionchanged:: 4.0 - Added the ``color`` parameter. - - .. versionadded:: 3.0 - Added the ``err`` parameter. - - .. versionchanged:: 2.0 - Support colors on Windows if colorama is installed. - """ - if file is None: - if err: - file = _default_text_stderr() - else: - file = _default_text_stdout() - - # There are no standard streams attached to write to. For example, - # pythonw on Windows. - if file is None: - return - - # Convert non bytes/text into the native string type. - if message is not None and not isinstance(message, (str, bytes, bytearray)): - out: t.Optional[t.Union[str, bytes]] = str(message) - else: - out = message - - if nl: - out = out or "" - if isinstance(out, str): - out += "\n" - else: - out += b"\n" - - if not out: - file.flush() - return - - # If there is a message and the value looks like bytes, we manually - # need to find the binary stream and write the message in there. - # This is done separately so that most stream types will work as you - # would expect. Eg: you can write to StringIO for other cases. - if isinstance(out, (bytes, bytearray)): - binary_file = _find_binary_writer(file) - - if binary_file is not None: - file.flush() - binary_file.write(out) - binary_file.flush() - return - - # ANSI style code support. For no message or bytes, nothing happens. - # When outputting to a file instead of a terminal, strip codes. - else: - color = resolve_color_default(color) - - if should_strip_ansi(file, color): - out = strip_ansi(out) - elif WIN: - if auto_wrap_for_ansi is not None: - file = auto_wrap_for_ansi(file, color) # type: ignore - elif not color: - out = strip_ansi(out) - - file.write(out) # type: ignore - file.flush() - - -def get_binary_stream(name: "te.Literal['stdin', 'stdout', 'stderr']") -> t.BinaryIO: - """Returns a system stream for byte processing. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - """ - opener = binary_streams.get(name) - if opener is None: - raise TypeError(f"Unknown standard stream '{name}'") - return opener() - - -def get_text_stream( - name: "te.Literal['stdin', 'stdout', 'stderr']", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", -) -> t.TextIO: - """Returns a system stream for text processing. This usually returns - a wrapped stream around a binary stream returned from - :func:`get_binary_stream` but it also can take shortcuts for already - correctly configured streams. - - :param name: the name of the stream to open. Valid names are ``'stdin'``, - ``'stdout'`` and ``'stderr'`` - :param encoding: overrides the detected default encoding. - :param errors: overrides the default error mode. - """ - opener = text_streams.get(name) - if opener is None: - raise TypeError(f"Unknown standard stream '{name}'") - return opener(encoding, errors) - - -def open_file( - filename: t.Union[str, "os.PathLike[str]"], - mode: str = "r", - encoding: t.Optional[str] = None, - errors: t.Optional[str] = "strict", - lazy: bool = False, - atomic: bool = False, -) -> t.IO[t.Any]: - """Open a file, with extra behavior to handle ``'-'`` to indicate - a standard stream, lazy open on write, and atomic write. Similar to - the behavior of the :class:`~click.File` param type. - - If ``'-'`` is given to open ``stdout`` or ``stdin``, the stream is - wrapped so that using it in a context manager will not close it. - This makes it possible to use the function without accidentally - closing a standard stream: - - .. code-block:: python - - with open_file(filename) as f: - ... - - :param filename: The name or Path of the file to open, or ``'-'`` for - ``stdin``/``stdout``. - :param mode: The mode in which to open the file. - :param encoding: The encoding to decode or encode a file opened in - text mode. - :param errors: The error handling mode. - :param lazy: Wait to open the file until it is accessed. For read - mode, the file is temporarily opened to raise access errors - early, then closed until it is read again. - :param atomic: Write to a temporary file and replace the given file - on close. - - .. versionadded:: 3.0 - """ - if lazy: - return t.cast( - t.IO[t.Any], LazyFile(filename, mode, encoding, errors, atomic=atomic) - ) - - f, should_close = open_stream(filename, mode, encoding, errors, atomic=atomic) - - if not should_close: - f = t.cast(t.IO[t.Any], KeepOpenFile(f)) - - return f - - -def format_filename( - filename: "t.Union[str, bytes, os.PathLike[str], os.PathLike[bytes]]", - shorten: bool = False, -) -> str: - """Format a filename as a string for display. Ensures the filename can be - displayed by replacing any invalid bytes or surrogate escapes in the name - with the replacement character ``�``. - - Invalid bytes or surrogate escapes will raise an error when written to a - stream with ``errors="strict"``. This will typically happen with ``stdout`` - when the locale is something like ``en_GB.UTF-8``. - - Many scenarios *are* safe to write surrogates though, due to PEP 538 and - PEP 540, including: - - - Writing to ``stderr``, which uses ``errors="backslashreplace"``. - - The system has ``LANG=C.UTF-8``, ``C``, or ``POSIX``. Python opens - stdout and stderr with ``errors="surrogateescape"``. - - None of ``LANG/LC_*`` are set. Python assumes ``LANG=C.UTF-8``. - - Python is started in UTF-8 mode with ``PYTHONUTF8=1`` or ``-X utf8``. - Python opens stdout and stderr with ``errors="surrogateescape"``. - - :param filename: formats a filename for UI display. This will also convert - the filename into unicode without failing. - :param shorten: this optionally shortens the filename to strip of the - path that leads up to it. - """ - if shorten: - filename = os.path.basename(filename) - else: - filename = os.fspath(filename) - - if isinstance(filename, bytes): - filename = filename.decode(sys.getfilesystemencoding(), "replace") - else: - filename = filename.encode("utf-8", "surrogateescape").decode( - "utf-8", "replace" - ) - - return filename - - -def get_app_dir(app_name: str, roaming: bool = True, force_posix: bool = False) -> str: - r"""Returns the config folder for the application. The default behavior - is to return whatever is most appropriate for the operating system. - - To give you an idea, for an app called ``"Foo Bar"``, something like - the following folders could be returned: - - Mac OS X: - ``~/Library/Application Support/Foo Bar`` - Mac OS X (POSIX): - ``~/.foo-bar`` - Unix: - ``~/.config/foo-bar`` - Unix (POSIX): - ``~/.foo-bar`` - Windows (roaming): - ``C:\Users\\AppData\Roaming\Foo Bar`` - Windows (not roaming): - ``C:\Users\\AppData\Local\Foo Bar`` - - .. versionadded:: 2.0 - - :param app_name: the application name. This should be properly capitalized - and can contain whitespace. - :param roaming: controls if the folder should be roaming or not on Windows. - Has no effect otherwise. - :param force_posix: if this is set to `True` then on any POSIX system the - folder will be stored in the home folder with a leading - dot instead of the XDG config home or darwin's - application support folder. - """ - if WIN: - key = "APPDATA" if roaming else "LOCALAPPDATA" - folder = os.environ.get(key) - if folder is None: - folder = os.path.expanduser("~") - return os.path.join(folder, app_name) - if force_posix: - return os.path.join(os.path.expanduser(f"~/.{_posixify(app_name)}")) - if sys.platform == "darwin": - return os.path.join( - os.path.expanduser("~/Library/Application Support"), app_name - ) - return os.path.join( - os.environ.get("XDG_CONFIG_HOME", os.path.expanduser("~/.config")), - _posixify(app_name), - ) - - -class PacifyFlushWrapper: - """This wrapper is used to catch and suppress BrokenPipeErrors resulting - from ``.flush()`` being called on broken pipe during the shutdown/final-GC - of the Python interpreter. Notably ``.flush()`` is always called on - ``sys.stdout`` and ``sys.stderr``. So as to have minimal impact on any - other cleanup code, and the case where the underlying file is not a broken - pipe, all calls and attributes are proxied. - """ - - def __init__(self, wrapped: t.IO[t.Any]) -> None: - self.wrapped = wrapped - - def flush(self) -> None: - try: - self.wrapped.flush() - except OSError as e: - import errno - - if e.errno != errno.EPIPE: - raise - - def __getattr__(self, attr: str) -> t.Any: - return getattr(self.wrapped, attr) - - -def _detect_program_name( - path: t.Optional[str] = None, _main: t.Optional[ModuleType] = None -) -> str: - """Determine the command used to run the program, for use in help - text. If a file or entry point was executed, the file name is - returned. If ``python -m`` was used to execute a module or package, - ``python -m name`` is returned. - - This doesn't try to be too precise, the goal is to give a concise - name for help text. Files are only shown as their name without the - path. ``python`` is only shown for modules, and the full path to - ``sys.executable`` is not shown. - - :param path: The Python file being executed. Python puts this in - ``sys.argv[0]``, which is used by default. - :param _main: The ``__main__`` module. This should only be passed - during internal testing. - - .. versionadded:: 8.0 - Based on command args detection in the Werkzeug reloader. - - :meta private: - """ - if _main is None: - _main = sys.modules["__main__"] - - if not path: - path = sys.argv[0] - - # The value of __package__ indicates how Python was called. It may - # not exist if a setuptools script is installed as an egg. It may be - # set incorrectly for entry points created with pip on Windows. - # It is set to "" inside a Shiv or PEX zipapp. - if getattr(_main, "__package__", None) in {None, ""} or ( - os.name == "nt" - and _main.__package__ == "" - and not os.path.exists(path) - and os.path.exists(f"{path}.exe") - ): - # Executed a file, like "python app.py". - return os.path.basename(path) - - # Executed a module, like "python -m example". - # Rewritten by Python from "-m script" to "/path/to/script.py". - # Need to look at main module to determine how it was executed. - py_module = t.cast(str, _main.__package__) - name = os.path.splitext(os.path.basename(path))[0] - - # A submodule like "example.cli". - if name != "__main__": - py_module = f"{py_module}.{name}" - - return f"python -m {py_module.lstrip('.')}" - - -def _expand_args( - args: t.Iterable[str], - *, - user: bool = True, - env: bool = True, - glob_recursive: bool = True, -) -> t.List[str]: - """Simulate Unix shell expansion with Python functions. - - See :func:`glob.glob`, :func:`os.path.expanduser`, and - :func:`os.path.expandvars`. - - This is intended for use on Windows, where the shell does not do any - expansion. It may not exactly match what a Unix shell would do. - - :param args: List of command line arguments to expand. - :param user: Expand user home directory. - :param env: Expand environment variables. - :param glob_recursive: ``**`` matches directories recursively. - - .. versionchanged:: 8.1 - Invalid glob patterns are treated as empty expansions rather - than raising an error. - - .. versionadded:: 8.0 - - :meta private: - """ - from glob import glob - - out = [] - - for arg in args: - if user: - arg = os.path.expanduser(arg) - - if env: - arg = os.path.expandvars(arg) - - try: - matches = glob(arg, recursive=glob_recursive) - except re.error: - matches = [] - - if not matches: - out.append(arg) - else: - out.extend(matches) - - return out diff --git a/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER b/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/colorama-0.4.6.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA b/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA deleted file mode 100644 index a1b5c57..0000000 --- a/venv/Lib/site-packages/colorama-0.4.6.dist-info/METADATA +++ /dev/null @@ -1,441 +0,0 @@ -Metadata-Version: 2.1 -Name: colorama -Version: 0.4.6 -Summary: Cross-platform colored terminal text. -Project-URL: Homepage, https://github.com/tartley/colorama -Author-email: Jonathan Hartley -License-File: LICENSE.txt -Keywords: ansi,color,colour,crossplatform,terminal,text,windows,xplatform -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Topic :: Terminals -Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7 -Description-Content-Type: text/x-rst - -.. image:: https://img.shields.io/pypi/v/colorama.svg - :target: https://pypi.org/project/colorama/ - :alt: Latest Version - -.. image:: https://img.shields.io/pypi/pyversions/colorama.svg - :target: https://pypi.org/project/colorama/ - :alt: Supported Python versions - -.. image:: https://github.com/tartley/colorama/actions/workflows/test.yml/badge.svg - :target: https://github.com/tartley/colorama/actions/workflows/test.yml - :alt: Build Status - -Colorama -======== - -Makes ANSI escape character sequences (for producing colored terminal text and -cursor positioning) work under MS Windows. - -.. |donate| image:: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif - :target: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2MZ9D2GMLYCUJ&item_name=Colorama¤cy_code=USD - :alt: Donate with Paypal - -`PyPI for releases `_ | -`Github for source `_ | -`Colorama for enterprise on Tidelift `_ - -If you find Colorama useful, please |donate| to the authors. Thank you! - -Installation ------------- - -Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8. - -No requirements other than the standard library. - -.. code-block:: bash - - pip install colorama - # or - conda install -c anaconda colorama - -Description ------------ - -ANSI escape character sequences have long been used to produce colored terminal -text and cursor positioning on Unix and Macs. Colorama makes this work on -Windows, too, by wrapping ``stdout``, stripping ANSI sequences it finds (which -would appear as gobbledygook in the output), and converting them into the -appropriate win32 calls to modify the state of the terminal. On other platforms, -Colorama does nothing. - -This has the upshot of providing a simple cross-platform API for printing -colored terminal text from Python, and has the happy side-effect that existing -applications or libraries which use ANSI sequences to produce colored output on -Linux or Macs can now also work on Windows, simply by calling -``colorama.just_fix_windows_console()`` (since v0.4.6) or ``colorama.init()`` -(all versions, but may have other side-effects – see below). - -An alternative approach is to install ``ansi.sys`` on Windows machines, which -provides the same behaviour for all applications running in terminals. Colorama -is intended for situations where that isn't easy (e.g., maybe your app doesn't -have an installer.) - -Demo scripts in the source code repository print some colored text using -ANSI sequences. Compare their output under Gnome-terminal's built in ANSI -handling, versus on Windows Command-Prompt using Colorama: - -.. image:: https://github.com/tartley/colorama/raw/master/screenshots/ubuntu-demo.png - :width: 661 - :height: 357 - :alt: ANSI sequences on Ubuntu under gnome-terminal. - -.. image:: https://github.com/tartley/colorama/raw/master/screenshots/windows-demo.png - :width: 668 - :height: 325 - :alt: Same ANSI sequences on Windows, using Colorama. - -These screenshots show that, on Windows, Colorama does not support ANSI 'dim -text'; it looks the same as 'normal text'. - -Usage ------ - -Initialisation -.............. - -If the only thing you want from Colorama is to get ANSI escapes to work on -Windows, then run: - -.. code-block:: python - - from colorama import just_fix_windows_console - just_fix_windows_console() - -If you're on a recent version of Windows 10 or better, and your stdout/stderr -are pointing to a Windows console, then this will flip the magic configuration -switch to enable Windows' built-in ANSI support. - -If you're on an older version of Windows, and your stdout/stderr are pointing to -a Windows console, then this will wrap ``sys.stdout`` and/or ``sys.stderr`` in a -magic file object that intercepts ANSI escape sequences and issues the -appropriate Win32 calls to emulate them. - -In all other circumstances, it does nothing whatsoever. Basically the idea is -that this makes Windows act like Unix with respect to ANSI escape handling. - -It's safe to call this function multiple times. It's safe to call this function -on non-Windows platforms, but it won't do anything. It's safe to call this -function when one or both of your stdout/stderr are redirected to a file – it -won't do anything to those streams. - -Alternatively, you can use the older interface with more features (but also more -potential footguns): - -.. code-block:: python - - from colorama import init - init() - -This does the same thing as ``just_fix_windows_console``, except for the -following differences: - -- It's not safe to call ``init`` multiple times; you can end up with multiple - layers of wrapping and broken ANSI support. - -- Colorama will apply a heuristic to guess whether stdout/stderr support ANSI, - and if it thinks they don't, then it will wrap ``sys.stdout`` and - ``sys.stderr`` in a magic file object that strips out ANSI escape sequences - before printing them. This happens on all platforms, and can be convenient if - you want to write your code to emit ANSI escape sequences unconditionally, and - let Colorama decide whether they should actually be output. But note that - Colorama's heuristic is not particularly clever. - -- ``init`` also accepts explicit keyword args to enable/disable various - functionality – see below. - -To stop using Colorama before your program exits, simply call ``deinit()``. -This will restore ``stdout`` and ``stderr`` to their original values, so that -Colorama is disabled. To resume using Colorama again, call ``reinit()``; it is -cheaper than calling ``init()`` again (but does the same thing). - -Most users should depend on ``colorama >= 0.4.6``, and use -``just_fix_windows_console``. The old ``init`` interface will be supported -indefinitely for backwards compatibility, but we don't plan to fix any issues -with it, also for backwards compatibility. - -Colored Output -.............. - -Cross-platform printing of colored text can then be done using Colorama's -constant shorthand for ANSI escape sequences. These are deliberately -rudimentary, see below. - -.. code-block:: python - - from colorama import Fore, Back, Style - print(Fore.RED + 'some red text') - print(Back.GREEN + 'and with a green background') - print(Style.DIM + 'and in dim text') - print(Style.RESET_ALL) - print('back to normal now') - -...or simply by manually printing ANSI sequences from your own code: - -.. code-block:: python - - print('\033[31m' + 'some red text') - print('\033[39m') # and reset to default color - -...or, Colorama can be used in conjunction with existing ANSI libraries -such as the venerable `Termcolor `_ -the fabulous `Blessings `_, -or the incredible `_Rich `_. - -If you wish Colorama's Fore, Back and Style constants were more capable, -then consider using one of the above highly capable libraries to generate -colors, etc, and use Colorama just for its primary purpose: to convert -those ANSI sequences to also work on Windows: - -SIMILARLY, do not send PRs adding the generation of new ANSI types to Colorama. -We are only interested in converting ANSI codes to win32 API calls, not -shortcuts like the above to generate ANSI characters. - -.. code-block:: python - - from colorama import just_fix_windows_console - from termcolor import colored - - # use Colorama to make Termcolor work on Windows too - just_fix_windows_console() - - # then use Termcolor for all colored text output - print(colored('Hello, World!', 'green', 'on_red')) - -Available formatting constants are:: - - Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. - Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET. - Style: DIM, NORMAL, BRIGHT, RESET_ALL - -``Style.RESET_ALL`` resets foreground, background, and brightness. Colorama will -perform this reset automatically on program exit. - -These are fairly well supported, but not part of the standard:: - - Fore: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX - Back: LIGHTBLACK_EX, LIGHTRED_EX, LIGHTGREEN_EX, LIGHTYELLOW_EX, LIGHTBLUE_EX, LIGHTMAGENTA_EX, LIGHTCYAN_EX, LIGHTWHITE_EX - -Cursor Positioning -.................. - -ANSI codes to reposition the cursor are supported. See ``demos/demo06.py`` for -an example of how to generate them. - -Init Keyword Args -................. - -``init()`` accepts some ``**kwargs`` to override default behaviour. - -init(autoreset=False): - If you find yourself repeatedly sending reset sequences to turn off color - changes at the end of every print, then ``init(autoreset=True)`` will - automate that: - - .. code-block:: python - - from colorama import init - init(autoreset=True) - print(Fore.RED + 'some red text') - print('automatically back to default color again') - -init(strip=None): - Pass ``True`` or ``False`` to override whether ANSI codes should be - stripped from the output. The default behaviour is to strip if on Windows - or if output is redirected (not a tty). - -init(convert=None): - Pass ``True`` or ``False`` to override whether to convert ANSI codes in the - output into win32 calls. The default behaviour is to convert if on Windows - and output is to a tty (terminal). - -init(wrap=True): - On Windows, Colorama works by replacing ``sys.stdout`` and ``sys.stderr`` - with proxy objects, which override the ``.write()`` method to do their work. - If this wrapping causes you problems, then this can be disabled by passing - ``init(wrap=False)``. The default behaviour is to wrap if ``autoreset`` or - ``strip`` or ``convert`` are True. - - When wrapping is disabled, colored printing on non-Windows platforms will - continue to work as normal. To do cross-platform colored output, you can - use Colorama's ``AnsiToWin32`` proxy directly: - - .. code-block:: python - - import sys - from colorama import init, AnsiToWin32 - init(wrap=False) - stream = AnsiToWin32(sys.stderr).stream - - # Python 2 - print >>stream, Fore.BLUE + 'blue text on stderr' - - # Python 3 - print(Fore.BLUE + 'blue text on stderr', file=stream) - -Recognised ANSI Sequences -......................... - -ANSI sequences generally take the form:: - - ESC [ ; ... - -Where ```` is an integer, and ```` is a single letter. Zero or -more params are passed to a ````. If no params are passed, it is -generally synonymous with passing a single zero. No spaces exist in the -sequence; they have been inserted here simply to read more easily. - -The only ANSI sequences that Colorama converts into win32 calls are:: - - ESC [ 0 m # reset all (colors and brightness) - ESC [ 1 m # bright - ESC [ 2 m # dim (looks same as normal brightness) - ESC [ 22 m # normal brightness - - # FOREGROUND: - ESC [ 30 m # black - ESC [ 31 m # red - ESC [ 32 m # green - ESC [ 33 m # yellow - ESC [ 34 m # blue - ESC [ 35 m # magenta - ESC [ 36 m # cyan - ESC [ 37 m # white - ESC [ 39 m # reset - - # BACKGROUND - ESC [ 40 m # black - ESC [ 41 m # red - ESC [ 42 m # green - ESC [ 43 m # yellow - ESC [ 44 m # blue - ESC [ 45 m # magenta - ESC [ 46 m # cyan - ESC [ 47 m # white - ESC [ 49 m # reset - - # cursor positioning - ESC [ y;x H # position cursor at x across, y down - ESC [ y;x f # position cursor at x across, y down - ESC [ n A # move cursor n lines up - ESC [ n B # move cursor n lines down - ESC [ n C # move cursor n characters forward - ESC [ n D # move cursor n characters backward - - # clear the screen - ESC [ mode J # clear the screen - - # clear the line - ESC [ mode K # clear the line - -Multiple numeric params to the ``'m'`` command can be combined into a single -sequence:: - - ESC [ 36 ; 45 ; 1 m # bright cyan text on magenta background - -All other ANSI sequences of the form ``ESC [ ; ... `` -are silently stripped from the output on Windows. - -Any other form of ANSI sequence, such as single-character codes or alternative -initial characters, are not recognised or stripped. It would be cool to add -them though. Let me know if it would be useful for you, via the Issues on -GitHub. - -Status & Known Problems ------------------------ - -I've personally only tested it on Windows XP (CMD, Console2), Ubuntu -(gnome-terminal, xterm), and OS X. - -Some valid ANSI sequences aren't recognised. - -If you're hacking on the code, see `README-hacking.md`_. ESPECIALLY, see the -explanation there of why we do not want PRs that allow Colorama to generate new -types of ANSI codes. - -See outstanding issues and wish-list: -https://github.com/tartley/colorama/issues - -If anything doesn't work for you, or doesn't do what you expected or hoped for, -I'd love to hear about it on that issues list, would be delighted by patches, -and would be happy to grant commit access to anyone who submits a working patch -or two. - -.. _README-hacking.md: README-hacking.md - -License -------- - -Copyright Jonathan Hartley & Arnon Yaari, 2013-2020. BSD 3-Clause license; see -LICENSE file. - -Professional support --------------------- - -.. |tideliftlogo| image:: https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png - :alt: Tidelift - :target: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme - -.. list-table:: - :widths: 10 100 - - * - |tideliftlogo| - - Professional support for colorama is available as part of the - `Tidelift Subscription`_. - Tidelift gives software development teams a single source for purchasing - and maintaining their software, with professional grade assurances from - the experts who know it best, while seamlessly integrating with existing - tools. - -.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-colorama?utm_source=pypi-colorama&utm_medium=referral&utm_campaign=readme - -Thanks ------- - -See the CHANGELOG for more thanks! - -* Marc Schlaich (schlamar) for a ``setup.py`` fix for Python2.5. -* Marc Abramowitz, reported & fixed a crash on exit with closed ``stdout``, - providing a solution to issue #7's setuptools/distutils debate, - and other fixes. -* User 'eryksun', for guidance on correctly instantiating ``ctypes.windll``. -* Matthew McCormick for politely pointing out a longstanding crash on non-Win. -* Ben Hoyt, for a magnificent fix under 64-bit Windows. -* Jesse at Empty Square for submitting a fix for examples in the README. -* User 'jamessp', an observant documentation fix for cursor positioning. -* User 'vaal1239', Dave Mckee & Lackner Kristof for a tiny but much-needed Win7 - fix. -* Julien Stuyck, for wisely suggesting Python3 compatible updates to README. -* Daniel Griffith for multiple fabulous patches. -* Oscar Lesta for a valuable fix to stop ANSI chars being sent to non-tty - output. -* Roger Binns, for many suggestions, valuable feedback, & bug reports. -* Tim Golden for thought and much appreciated feedback on the initial idea. -* User 'Zearin' for updates to the README file. -* John Szakmeister for adding support for light colors -* Charles Merriam for adding documentation to demos -* Jurko for a fix on 64-bit Windows CPython2.5 w/o ctypes -* Florian Bruhin for a fix when stdout or stderr are None -* Thomas Weininger for fixing ValueError on Windows -* Remi Rampin for better Github integration and fixes to the README file -* Simeon Visser for closing a file handle using 'with' and updating classifiers - to include Python 3.3 and 3.4 -* Andy Neff for fixing RESET of LIGHT_EX colors. -* Jonathan Hartley for the initial idea and implementation. diff --git a/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD b/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD deleted file mode 100644 index 8c5f12d..0000000 --- a/venv/Lib/site-packages/colorama-0.4.6.dist-info/RECORD +++ /dev/null @@ -1,31 +0,0 @@ -colorama-0.4.6.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -colorama-0.4.6.dist-info/METADATA,sha256=e67SnrUMOym9sz_4TjF3vxvAV4T3aF7NyqRHHH3YEMw,17158 -colorama-0.4.6.dist-info/RECORD,, -colorama-0.4.6.dist-info/WHEEL,sha256=cdcF4Fbd0FPtw2EMIOwH-3rSOTUdTCeOSXRMD1iLUb8,105 -colorama-0.4.6.dist-info/licenses/LICENSE.txt,sha256=ysNcAmhuXQSlpxQL-zs25zrtSWZW6JEQLkKIhteTAxg,1491 -colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266 -colorama/__pycache__/__init__.cpython-310.pyc,, -colorama/__pycache__/ansi.cpython-310.pyc,, -colorama/__pycache__/ansitowin32.cpython-310.pyc,, -colorama/__pycache__/initialise.cpython-310.pyc,, -colorama/__pycache__/win32.cpython-310.pyc,, -colorama/__pycache__/winterm.cpython-310.pyc,, -colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 -colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128 -colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325 -colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75 -colorama/tests/__pycache__/__init__.cpython-310.pyc,, -colorama/tests/__pycache__/ansi_test.cpython-310.pyc,, -colorama/tests/__pycache__/ansitowin32_test.cpython-310.pyc,, -colorama/tests/__pycache__/initialise_test.cpython-310.pyc,, -colorama/tests/__pycache__/isatty_test.cpython-310.pyc,, -colorama/tests/__pycache__/utils.cpython-310.pyc,, -colorama/tests/__pycache__/winterm_test.cpython-310.pyc,, -colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839 -colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678 -colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741 -colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866 -colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079 -colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709 -colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181 -colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134 diff --git a/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL b/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL deleted file mode 100644 index d79189f..0000000 --- a/venv/Lib/site-packages/colorama-0.4.6.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.11.1 -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any diff --git a/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt b/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt deleted file mode 100644 index 3105888..0000000 --- a/venv/Lib/site-packages/colorama-0.4.6.dist-info/licenses/LICENSE.txt +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2010 Jonathan Hartley -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* 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. - -* Neither the name of the copyright holders, nor those 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. diff --git a/venv/Lib/site-packages/colorama/__init__.py b/venv/Lib/site-packages/colorama/__init__.py deleted file mode 100644 index 383101c..0000000 --- a/venv/Lib/site-packages/colorama/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from .initialise import init, deinit, reinit, colorama_text, just_fix_windows_console -from .ansi import Fore, Back, Style, Cursor -from .ansitowin32 import AnsiToWin32 - -__version__ = '0.4.6' - diff --git a/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/colorama/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 49004078b02d274a724debad295d7502ca2cb3eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 452 zcmYk2Pfx-y6u{Tfjj;h|4*CIh5Dgd)#uybenh-B&OqwOlWECszO4>2NZ{%0%#e*lm zf+zbzOngayukXF~{ZpMz>^T{J?!U&!^S;3NFTOJ_+%dNfg;yZqNkowJi7y+ZAu+)+ zAOV7yFGATQO&O6$wn$6H#HDophDct#65 ziSyWm(wb?*RY~cGr@QbJ@N+jh%^qD9lP%{;vTV%EqEgFjGQO^Jk=3lMvk8CBTt0TN mbTj00X0pHO4=IICDeW(}Hae54SP6Cxn={bT9_pbsiu_;f+<9&Q diff --git a/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-310.pyc b/venv/Lib/site-packages/colorama/__pycache__/ansi.cpython-310.pyc deleted file mode 100644 index de2b1038a1522c7576f89c326c4acb418731571c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2978 zcma)8-ER{|5Wl@U+vl^-HYOy{LhF9xwmAJzTL~%@e-ToQ6WNJU7SrqDU7RD1ZT2ou zq97reKZHK!U%Hn*^y!{?L#ou7z1T7NkT`39-r4cZ&d&U1)F zn0<5*mSA|V0hmG+Mkrw_RhdRLrnA^9h3YKM67U^k7g>^-uLzC9EXC3=ODrqQVwqP8 z%Wz|?(Im)OmIFB_WfSCcEDv&?CqbVA`8=Bgc}~h{kT0-#kmsdr@zhwM8J-5ratkoW zO~7+(p{*1z?Y%VDw_LBVGi1AcUg+@w7mm-pLb=&qDRj3S;dFg23f&=tMSoZr33uST zgC4B(he9rae#ad+eXnG;Ilo@m^8L~E#YH|SJ#)9+5ofMb8j9W`N{eXM=3dtsaT|@A zd+LYxVLW(C5?ul@n>;wzU{qne$pQF^Pxh5DS%8o(DB!%>49L!b8few_N}zeZD3U-& zn+J+8;DxvK>h;cs$A#A!^@cmVQ{&#YKOA)$wfa-1-+9UhPdg3wVaIcQer@D*x1ApM zI`Ux7jwT`I6R6Vv-zDU+Vwu<)^l8OBMM+}h9xraNENXFa0!No88?(Pkt-(xj!|2}pWOtQ2HaxM zoS^k+(0H&x5ol1BY*7SSl*J5|lr1X5OqRkH#nO z^<}b`nF%7OnnfZoc|}!zMRP-Z0!!jkgwGJZM)($?gzz20PY6c|JEHmLpui!E%21%F zRQzOAfva5@?>tD#B^Ynk0H$*G|3EVvLsD0lcrgUS}aX7 z%%WMAp*fa?J2OY~>>NGM@=yTh0|O6yYbbd55o{2Cj8H(pGlqD^5YHH*b0LNzM8<^_ z;XXnK;Q_)Q2sXl>2o6B=VD4D3XsptJeYMYCXH?0URkdPu~xlZU#C`MW%>5HG-20&rzt6dDHI}|G>KwH>LSx9rw?D< zsH2pX(&1J|YTOc~$d=q1#8VUb3!LwJ7;i8%hN6=bA8mHUAOhbwGrR diff --git a/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-310.pyc b/venv/Lib/site-packages/colorama/__pycache__/ansitowin32.cpython-310.pyc deleted file mode 100644 index dce73bd3e3e3234ea344a832b65b6796cb705042..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8490 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 DE}={iC+gQ0jKnKVVJ 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 diff --git a/venv/Lib/site-packages/colorama/ansi.py b/venv/Lib/site-packages/colorama/ansi.py deleted file mode 100644 index 11ec695..0000000 --- a/venv/Lib/site-packages/colorama/ansi.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -''' -This module generates ANSI character codes to printing colors to terminals. -See: http://en.wikipedia.org/wiki/ANSI_escape_code -''' - -CSI = '\033[' -OSC = '\033]' -BEL = '\a' - - -def code_to_chars(code): - return CSI + str(code) + 'm' - -def set_title(title): - return OSC + '2;' + title + BEL - -def clear_screen(mode=2): - return CSI + str(mode) + 'J' - -def clear_line(mode=2): - return CSI + str(mode) + 'K' - - -class AnsiCodes(object): - def __init__(self): - # the subclasses declare class attributes which are numbers. - # Upon instantiation we define instance attributes, which are the same - # as the class attributes but wrapped with the ANSI escape sequence - for name in dir(self): - if not name.startswith('_'): - value = getattr(self, name) - setattr(self, name, code_to_chars(value)) - - -class AnsiCursor(object): - def UP(self, n=1): - return CSI + str(n) + 'A' - def DOWN(self, n=1): - return CSI + str(n) + 'B' - def FORWARD(self, n=1): - return CSI + str(n) + 'C' - def BACK(self, n=1): - return CSI + str(n) + 'D' - def POS(self, x=1, y=1): - return CSI + str(y) + ';' + str(x) + 'H' - - -class AnsiFore(AnsiCodes): - BLACK = 30 - RED = 31 - GREEN = 32 - YELLOW = 33 - BLUE = 34 - MAGENTA = 35 - CYAN = 36 - WHITE = 37 - RESET = 39 - - # These are fairly well supported, but not part of the standard. - LIGHTBLACK_EX = 90 - LIGHTRED_EX = 91 - LIGHTGREEN_EX = 92 - LIGHTYELLOW_EX = 93 - LIGHTBLUE_EX = 94 - LIGHTMAGENTA_EX = 95 - LIGHTCYAN_EX = 96 - LIGHTWHITE_EX = 97 - - -class AnsiBack(AnsiCodes): - BLACK = 40 - RED = 41 - GREEN = 42 - YELLOW = 43 - BLUE = 44 - MAGENTA = 45 - CYAN = 46 - WHITE = 47 - RESET = 49 - - # These are fairly well supported, but not part of the standard. - LIGHTBLACK_EX = 100 - LIGHTRED_EX = 101 - LIGHTGREEN_EX = 102 - LIGHTYELLOW_EX = 103 - LIGHTBLUE_EX = 104 - LIGHTMAGENTA_EX = 105 - LIGHTCYAN_EX = 106 - LIGHTWHITE_EX = 107 - - -class AnsiStyle(AnsiCodes): - BRIGHT = 1 - DIM = 2 - NORMAL = 22 - RESET_ALL = 0 - -Fore = AnsiFore() -Back = AnsiBack() -Style = AnsiStyle() -Cursor = AnsiCursor() diff --git a/venv/Lib/site-packages/colorama/ansitowin32.py b/venv/Lib/site-packages/colorama/ansitowin32.py deleted file mode 100644 index abf209e..0000000 --- a/venv/Lib/site-packages/colorama/ansitowin32.py +++ /dev/null @@ -1,277 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import re -import sys -import os - -from .ansi import AnsiFore, AnsiBack, AnsiStyle, Style, BEL -from .winterm import enable_vt_processing, WinTerm, WinColor, WinStyle -from .win32 import windll, winapi_test - - -winterm = None -if windll is not None: - winterm = WinTerm() - - -class StreamWrapper(object): - ''' - Wraps a stream (such as stdout), acting as a transparent proxy for all - attribute access apart from method 'write()', which is delegated to our - Converter instance. - ''' - def __init__(self, wrapped, converter): - # double-underscore everything to prevent clashes with names of - # attributes on the wrapped stream object. - self.__wrapped = wrapped - self.__convertor = converter - - def __getattr__(self, name): - return getattr(self.__wrapped, name) - - def __enter__(self, *args, **kwargs): - # special method lookup bypasses __getattr__/__getattribute__, see - # https://stackoverflow.com/questions/12632894/why-doesnt-getattr-work-with-exit - # thus, contextlib magic methods are not proxied via __getattr__ - return self.__wrapped.__enter__(*args, **kwargs) - - def __exit__(self, *args, **kwargs): - return self.__wrapped.__exit__(*args, **kwargs) - - def __setstate__(self, state): - self.__dict__ = state - - def __getstate__(self): - return self.__dict__ - - def write(self, text): - self.__convertor.write(text) - - def isatty(self): - stream = self.__wrapped - if 'PYCHARM_HOSTED' in os.environ: - if stream is not None and (stream is sys.__stdout__ or stream is sys.__stderr__): - return True - try: - stream_isatty = stream.isatty - except AttributeError: - return False - else: - return stream_isatty() - - @property - def closed(self): - stream = self.__wrapped - try: - return stream.closed - # AttributeError in the case that the stream doesn't support being closed - # ValueError for the case that the stream has already been detached when atexit runs - except (AttributeError, ValueError): - return True - - -class AnsiToWin32(object): - ''' - Implements a 'write()' method which, on Windows, will strip ANSI character - sequences from the text, and if outputting to a tty, will convert them into - win32 function calls. - ''' - ANSI_CSI_RE = re.compile('\001?\033\\[((?:\\d|;)*)([a-zA-Z])\002?') # Control Sequence Introducer - ANSI_OSC_RE = re.compile('\001?\033\\]([^\a]*)(\a)\002?') # Operating System Command - - def __init__(self, wrapped, convert=None, strip=None, autoreset=False): - # The wrapped stream (normally sys.stdout or sys.stderr) - self.wrapped = wrapped - - # should we reset colors to defaults after every .write() - self.autoreset = autoreset - - # create the proxy wrapping our output stream - self.stream = StreamWrapper(wrapped, self) - - on_windows = os.name == 'nt' - # We test if the WinAPI works, because even if we are on Windows - # we may be using a terminal that doesn't support the WinAPI - # (e.g. Cygwin Terminal). In this case it's up to the terminal - # to support the ANSI codes. - conversion_supported = on_windows and winapi_test() - try: - fd = wrapped.fileno() - except Exception: - fd = -1 - system_has_native_ansi = not on_windows or enable_vt_processing(fd) - have_tty = not self.stream.closed and self.stream.isatty() - need_conversion = conversion_supported and not system_has_native_ansi - - # should we strip ANSI sequences from our output? - if strip is None: - strip = need_conversion or not have_tty - self.strip = strip - - # should we should convert ANSI sequences into win32 calls? - if convert is None: - convert = need_conversion and have_tty - self.convert = convert - - # dict of ansi codes to win32 functions and parameters - self.win32_calls = self.get_win32_calls() - - # are we wrapping stderr? - self.on_stderr = self.wrapped is sys.stderr - - def should_wrap(self): - ''' - True if this class is actually needed. If false, then the output - stream will not be affected, nor will win32 calls be issued, so - wrapping stdout is not actually required. This will generally be - False on non-Windows platforms, unless optional functionality like - autoreset has been requested using kwargs to init() - ''' - return self.convert or self.strip or self.autoreset - - def get_win32_calls(self): - if self.convert and winterm: - return { - AnsiStyle.RESET_ALL: (winterm.reset_all, ), - AnsiStyle.BRIGHT: (winterm.style, WinStyle.BRIGHT), - AnsiStyle.DIM: (winterm.style, WinStyle.NORMAL), - AnsiStyle.NORMAL: (winterm.style, WinStyle.NORMAL), - AnsiFore.BLACK: (winterm.fore, WinColor.BLACK), - AnsiFore.RED: (winterm.fore, WinColor.RED), - AnsiFore.GREEN: (winterm.fore, WinColor.GREEN), - AnsiFore.YELLOW: (winterm.fore, WinColor.YELLOW), - AnsiFore.BLUE: (winterm.fore, WinColor.BLUE), - AnsiFore.MAGENTA: (winterm.fore, WinColor.MAGENTA), - AnsiFore.CYAN: (winterm.fore, WinColor.CYAN), - AnsiFore.WHITE: (winterm.fore, WinColor.GREY), - AnsiFore.RESET: (winterm.fore, ), - AnsiFore.LIGHTBLACK_EX: (winterm.fore, WinColor.BLACK, True), - AnsiFore.LIGHTRED_EX: (winterm.fore, WinColor.RED, True), - AnsiFore.LIGHTGREEN_EX: (winterm.fore, WinColor.GREEN, True), - AnsiFore.LIGHTYELLOW_EX: (winterm.fore, WinColor.YELLOW, True), - AnsiFore.LIGHTBLUE_EX: (winterm.fore, WinColor.BLUE, True), - AnsiFore.LIGHTMAGENTA_EX: (winterm.fore, WinColor.MAGENTA, True), - AnsiFore.LIGHTCYAN_EX: (winterm.fore, WinColor.CYAN, True), - AnsiFore.LIGHTWHITE_EX: (winterm.fore, WinColor.GREY, True), - AnsiBack.BLACK: (winterm.back, WinColor.BLACK), - AnsiBack.RED: (winterm.back, WinColor.RED), - AnsiBack.GREEN: (winterm.back, WinColor.GREEN), - AnsiBack.YELLOW: (winterm.back, WinColor.YELLOW), - AnsiBack.BLUE: (winterm.back, WinColor.BLUE), - AnsiBack.MAGENTA: (winterm.back, WinColor.MAGENTA), - AnsiBack.CYAN: (winterm.back, WinColor.CYAN), - AnsiBack.WHITE: (winterm.back, WinColor.GREY), - AnsiBack.RESET: (winterm.back, ), - AnsiBack.LIGHTBLACK_EX: (winterm.back, WinColor.BLACK, True), - AnsiBack.LIGHTRED_EX: (winterm.back, WinColor.RED, True), - AnsiBack.LIGHTGREEN_EX: (winterm.back, WinColor.GREEN, True), - AnsiBack.LIGHTYELLOW_EX: (winterm.back, WinColor.YELLOW, True), - AnsiBack.LIGHTBLUE_EX: (winterm.back, WinColor.BLUE, True), - AnsiBack.LIGHTMAGENTA_EX: (winterm.back, WinColor.MAGENTA, True), - AnsiBack.LIGHTCYAN_EX: (winterm.back, WinColor.CYAN, True), - AnsiBack.LIGHTWHITE_EX: (winterm.back, WinColor.GREY, True), - } - return dict() - - def write(self, text): - if self.strip or self.convert: - self.write_and_convert(text) - else: - self.wrapped.write(text) - self.wrapped.flush() - if self.autoreset: - self.reset_all() - - - def reset_all(self): - if self.convert: - self.call_win32('m', (0,)) - elif not self.strip and not self.stream.closed: - self.wrapped.write(Style.RESET_ALL) - - - def write_and_convert(self, text): - ''' - Write the given text to our wrapped stream, stripping any ANSI - sequences from the text, and optionally converting them into win32 - calls. - ''' - cursor = 0 - text = self.convert_osc(text) - for match in self.ANSI_CSI_RE.finditer(text): - start, end = match.span() - self.write_plain_text(text, cursor, start) - self.convert_ansi(*match.groups()) - cursor = end - self.write_plain_text(text, cursor, len(text)) - - - def write_plain_text(self, text, start, end): - if start < end: - self.wrapped.write(text[start:end]) - self.wrapped.flush() - - - def convert_ansi(self, paramstring, command): - if self.convert: - params = self.extract_params(command, paramstring) - self.call_win32(command, params) - - - def extract_params(self, command, paramstring): - if command in 'Hf': - params = tuple(int(p) if len(p) != 0 else 1 for p in paramstring.split(';')) - while len(params) < 2: - # defaults: - params = params + (1,) - else: - params = tuple(int(p) for p in paramstring.split(';') if len(p) != 0) - if len(params) == 0: - # defaults: - if command in 'JKm': - params = (0,) - elif command in 'ABCD': - params = (1,) - - return params - - - def call_win32(self, command, params): - if command == 'm': - for param in params: - if param in self.win32_calls: - func_args = self.win32_calls[param] - func = func_args[0] - args = func_args[1:] - kwargs = dict(on_stderr=self.on_stderr) - func(*args, **kwargs) - elif command in 'J': - winterm.erase_screen(params[0], on_stderr=self.on_stderr) - elif command in 'K': - winterm.erase_line(params[0], on_stderr=self.on_stderr) - elif command in 'Hf': # cursor position - absolute - winterm.set_cursor_position(params, on_stderr=self.on_stderr) - elif command in 'ABCD': # cursor position - relative - n = params[0] - # A - up, B - down, C - forward, D - back - x, y = {'A': (0, -n), 'B': (0, n), 'C': (n, 0), 'D': (-n, 0)}[command] - winterm.cursor_adjust(x, y, on_stderr=self.on_stderr) - - - def convert_osc(self, text): - for match in self.ANSI_OSC_RE.finditer(text): - start, end = match.span() - text = text[:start] + text[end:] - paramstring, command = match.groups() - if command == BEL: - if paramstring.count(";") == 1: - params = paramstring.split(";") - # 0 - change title and icon (we will only change title) - # 1 - change icon (we don't support this) - # 2 - change title - if params[0] in '02': - winterm.set_title(params[1]) - return text - - - def flush(self): - self.wrapped.flush() diff --git a/venv/Lib/site-packages/colorama/initialise.py b/venv/Lib/site-packages/colorama/initialise.py deleted file mode 100644 index d5fd4b7..0000000 --- a/venv/Lib/site-packages/colorama/initialise.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -import atexit -import contextlib -import sys - -from .ansitowin32 import AnsiToWin32 - - -def _wipe_internal_state_for_tests(): - global orig_stdout, orig_stderr - orig_stdout = None - orig_stderr = None - - global wrapped_stdout, wrapped_stderr - wrapped_stdout = None - wrapped_stderr = None - - global atexit_done - atexit_done = False - - global fixed_windows_console - fixed_windows_console = False - - try: - # no-op if it wasn't registered - atexit.unregister(reset_all) - except AttributeError: - # python 2: no atexit.unregister. Oh well, we did our best. - pass - - -def reset_all(): - if AnsiToWin32 is not None: # Issue #74: objects might become None at exit - AnsiToWin32(orig_stdout).reset_all() - - -def init(autoreset=False, convert=None, strip=None, wrap=True): - - if not wrap and any([autoreset, convert, strip]): - raise ValueError('wrap=False conflicts with any other arg=True') - - global wrapped_stdout, wrapped_stderr - global orig_stdout, orig_stderr - - orig_stdout = sys.stdout - orig_stderr = sys.stderr - - if sys.stdout is None: - wrapped_stdout = None - else: - sys.stdout = wrapped_stdout = \ - wrap_stream(orig_stdout, convert, strip, autoreset, wrap) - if sys.stderr is None: - wrapped_stderr = None - else: - sys.stderr = wrapped_stderr = \ - wrap_stream(orig_stderr, convert, strip, autoreset, wrap) - - global atexit_done - if not atexit_done: - atexit.register(reset_all) - atexit_done = True - - -def deinit(): - if orig_stdout is not None: - sys.stdout = orig_stdout - if orig_stderr is not None: - sys.stderr = orig_stderr - - -def just_fix_windows_console(): - global fixed_windows_console - - if sys.platform != "win32": - return - if fixed_windows_console: - return - if wrapped_stdout is not None or wrapped_stderr is not None: - # Someone already ran init() and it did stuff, so we won't second-guess them - return - - # On newer versions of Windows, AnsiToWin32.__init__ will implicitly enable the - # native ANSI support in the console as a side-effect. We only need to actually - # replace sys.stdout/stderr if we're in the old-style conversion mode. - new_stdout = AnsiToWin32(sys.stdout, convert=None, strip=None, autoreset=False) - if new_stdout.convert: - sys.stdout = new_stdout - new_stderr = AnsiToWin32(sys.stderr, convert=None, strip=None, autoreset=False) - if new_stderr.convert: - sys.stderr = new_stderr - - fixed_windows_console = True - -@contextlib.contextmanager -def colorama_text(*args, **kwargs): - init(*args, **kwargs) - try: - yield - finally: - deinit() - - -def reinit(): - if wrapped_stdout is not None: - sys.stdout = wrapped_stdout - if wrapped_stderr is not None: - sys.stderr = wrapped_stderr - - -def wrap_stream(stream, convert, strip, autoreset, wrap): - if wrap: - wrapper = AnsiToWin32(stream, - convert=convert, strip=strip, autoreset=autoreset) - if wrapper.should_wrap(): - stream = wrapper.stream - return stream - - -# Use this for initial setup as well, to reduce code duplication -_wipe_internal_state_for_tests() diff --git a/venv/Lib/site-packages/colorama/tests/__init__.py b/venv/Lib/site-packages/colorama/tests/__init__.py deleted file mode 100644 index 8c5661e..0000000 --- a/venv/Lib/site-packages/colorama/tests/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. diff --git a/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/colorama/tests/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 635fe7841ef72fc491d0bb4e3f8e33cf03d8c4ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 172 zcmd1j<>g`k0^|F#8QwtpF^Gc<7=auIATDMB5-AM944RC7D;bJF!U*D*zq3_LXmM&$ zaZEvaer{@vOKNd;Nq#|$kBe(rVopq1YF=54Pi9g~ab`)XZb4#lc4B&JaZGZ4PJU5h qZlZokYH>-ietdjpUS>&ryk0@&Ee@O9{FKt1R6CGG#Y{kgg#iEnPb+-@ diff --git a/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-310.pyc b/venv/Lib/site-packages/colorama/tests/__pycache__/ansi_test.cpython-310.pyc deleted file mode 100644 index 3431f10a49d7c563fe1c2660429aafc65200ddc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2264 zcma)7TT|Oc6yDX%@)cuJ(w3z6o7x5fsLi<3X=6YoOpVh4Gc>|88iiGxyd z?!!MF05HPnkoYLIA&oU(i*;Y8gz3x}8nNk{vE^HF!7s=;b7;p!zeq_$1|`1?Sn;dt zgjuZcl(0gio#}opnqu~$#+M`gjDQy1mVc-C9QGp}M-z58O0(54jf4@0{n2v`<{e!a zE8+g3FuqH8B+TvXWEeSAlv|^;-%WP=qvfT2G?0H#@jm=h7a$@&WyIGQW!h8X>*xYV zgPF_%X|e*dL0YWHN+1iYyiJ^nu;m7DpnVEPE*>0XpjP3Zegg0-`Hf^W(+2t(&5YkQ zI+-yqW*FHf&uGW7{92f%5zjhF=KXRM4uz4Oj3c3^C#kT~j3q}Ix520+5$DgSFw$uF z(=)=SVfybMR=?`)fPu6(K1kxIw-%*`Su*am*SzC!*gK9!$Gvv{aWCy>(Va0wEj)HZ8F-T}gb=s@hx6kTVWv^GGp?aG=vG6YrKhzE&*$ah75_21(*HUPGVngo zG9A!BKRFheV~VnJCrEhzfLCCSR{`WSIHsm?TRw$=-YIC{TXq(Od@Xr0x&cfc%%UZF zI{n|lF4nJ{?IJfX{sK*vn*n5gl9z$bv>Y>-o?|AH6pKnMDY2}C ztHc*de5u4eC7Mz+m3mXDHizVdh=fF%!sloZduvf!aSNQ?bhn|Lf`V% zgt@-uc^zRr^4jf(yYNxBcRW$pY^{5pZc7-ek6ImJ?mpP)dcxfDw!N;Xwl~%vbft;F z`%#o71ye}Wnly>DCfAf{~f(0qTgp^=IN-!cNSdkJF%U_3sa1#NY=5Hd*A>2Z^jqn!2+X(L< zyo-Rr;qN1Sfbb#0M+hGyVDsb-!gU=$1|0kTB;X79?q>j(!uj%BuMB58532vaBgn7G z=$smJdn(#XAb>2!j;R7t0DHc^wz273orhbSt+sEiY+=P->(C5Vki5Jm9(iCP#SaC` z1j7u3O zv*Zb0&+?Vn>m=d$g;h9lgbV_vR1oUp%EE`EcTZi=clt$?4Ii5ma> E3pGgqcK`qY diff --git a/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-310.pyc b/venv/Lib/site-packages/colorama/tests/__pycache__/ansitowin32_test.cpython-310.pyc deleted file mode 100644 index 1183caf120cbf0b4006340b6ec714097885c202b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11575 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 diff --git a/venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-310.pyc b/venv/Lib/site-packages/colorama/tests/__pycache__/isatty_test.cpython-310.pyc deleted file mode 100644 index e7ca3cbc4a0ce84db5b967e3c1afc609f3fb14aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2663 zcmaJ@TW{P%6rS;Iz1~ZfrUXiEB|zJiN&`d{5}>Lm0aO%)hy>p9=~=GaNCW)XOn{+QkQwnWIE zsN^3Fl;==51K|;mhQ!8N32CI*N~GE5~hJQ}nddIc)E^EJ`ircS5)A zJFgDY$w50|!FCY4A$FFt%{Dh*rq!&umc*d7ai_t9Z57Hg6kZ1*$Pqx&S5D~}*&yc> ztYtd%r$)eCAr6}~HMq3$oUjHA{Pq3vXRRN&&v>h|okV_X#pin>>9kf?zS?)g*1jL_ zw^oB!EglH}!;ahDbGLooYA0dB+{j%NfCOL6Hg`~Y(m71cfIF@O$Cc48M5j*K9jMw+ zMjjk{4u!9P@QF=5Vk;i?6o`w8v4mQ~7(%UI$IHl~WtY5)SA~Alt9f;(%ihEWX*N>p zg>)5TGy)c$WkNx)F4sT^(kH*tBXUZGazy*|j8Y;X<|hpbFy?!=08|a$J~9k|{h09k z2QVAom&g(5V>Q^asj&)FspWFORBW=YFCAxi@VSy|+z)?BRe(mKpNThcg^A!f5MT`B zCEf&s)~QJwbm6KuIdtjCVBU?svAeK%U`-YGu4LAH?S^0!#^Kr=_7=45Qk=vXtfEB~ zc@hkQQF6<7V0Le+Xi7F=#2TdK0BODo3L<@SZ-A;$ceM=d3}w*uOdo^u{CJ!V=>mHb zHkTfyDnI1NZO>;+)=5{KQ|V#Rv4(W)AP_t2*=(Dkd{gIhq!ExZvQ_8y)tuZhl(m^nMA zQI*u3!B)Y}xuTs}E*zNpJ}&tHM6Y>^iKA;qtVF`%mBT3V-$6*iu0#AFA@%9W5=K(C z<_D2P4HE`X7~(4Q{!lkSFAem3>|zrlx0sLI$SCsQ*-fK2@ZiV%{2>p_9JJ^d8{#X0 zm-hxU6?+#&0q&VGaQg$Wo3MZ*nM`^YG8A5znSYeu=1BcY!Cdw5_7J?@=YIisoiUDK za~XiA!;FD&?rNv{8My}C5K0E}NH1h^VeXa-bF*G6-VFTzt9}i_EmuUP=J7MU&m0$ELT@ND)KnX)`Pib`)qm|;GdBPL diff --git a/venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-310.pyc b/venv/Lib/site-packages/colorama/tests/__pycache__/utils.cpython-310.pyc deleted file mode 100644 index 9d998fb824a4e50c535211b02575572d6d20c37d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1572 zcmaJ>OK%iM5bnq9?Ck8=*zr%m2FB~{=_AQrC)x+A073fjb)T6uWtE%p<7ZySSnelSq(0i9d~CP_jCNtmF59g&2)eLdTO-?rhn~bMdMN38OAfT3Y)H4zyctbTtFh~ET1f)!WzV$jT#{Ry82wj zl#jDn|3MQKoRV$IP-?TMw%iGxZg$v0kn6opZ3QUu&Gx!<`WdJMfuL zeHv2rHK-rK;OIvq(8*0;GZ+Ad?Xw1q<7^(%lmRfX42W8SMKQNrPqg*55%sQdf2q_l zM+uLv?IO^$aVMt=%sCG}RB~KoBbjbb5bOzNF-riGaA{lt<0sQlm%#f0mbwfw9=#@V za|}U-z-g+MapGC;uvT_y79RoURaO9yYdG&JvhRRlsZIypKfDBJ)CSlqxP{nA!R`>l z4#_?-dnoHP&q-Z;kg&bK!{3ANkW*3xw}`&_H#}VUZT+8jb>7>=xC=YLo#%Z^ zZzYSrZmm7~`M1aEqbGyS`|EK_;hSRHaIY{DkGz*rtd^5Ivwh-t(9jQsx77kQV8CK5#DN diff --git a/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-310.pyc b/venv/Lib/site-packages/colorama/tests/__pycache__/winterm_test.cpython-310.pyc deleted file mode 100644 index fc1cd1b900a4955bf9a728e92be20fa48c4dccb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3165 zcma)8%WvB@7$+rJmi&sFCT-VkSXW>V18WO38}>jkG)c2GK#~rzi>`tJK{c7wjvg*4 zH;a*;((88GACMe#-(SPa4mbnV9<}4e zBus>^)zjUOt332IxQJRf?a9Z2#$71#Zvaj_%7|xhlhJ+33}(J0`_!{|j@zC5fy1mr z%5wWgwgr&5LrsUdTC*^rSztviDNaaAtgI!a2}y-bX-RoFdzD?#?aHt{%`WQp6q~7& z+N>%LH-}91FST&%K@{BFX~!vS8NYM4TS(66!A)aXgd*<)q-3AGFc{r4d?eR{F4CoEy&zOMe=`vr zK2HKLzwJvj@{y%1$-_<0jld~@leycTgH`;gvXF}-BCf(@|J4_NYCeSNWV5@KM7(*A z%k4DjHdpU0!7rQ7dHlS&+J4fM?Udi>!ass7E}J7}Z^80Yd27h8kFA^CUFBe9C2prv z@CykMM{L8U4z+0o-f7yOfi4j~=uglBwl0M9Qew3hO&-8Q50EAcp%xiS^%meojG8^z*&~Y@19Bk#Y z$QjBUmP6Kutz4(bY;0?8^Xr2etYGj4o&mBfFv0|STBBCd(It>~aRFf(A&VLbT(`0) zJ7o;d1$RSBgkfeEy9HIw#AO_P7S$W5KOcs-KtZCy$iE#;IQY6zG0@j%=p@CX!4r-> zN<^>j!iZ^`Nt2319a%#s#C+4J|qQ+HtRSY7ZBp-pm<0&jW(2VoEVw;-xU%zvW>eDCJ^A_<`7x%C0x=J$Tp}UFG$eZ4I7ToPL7YHZdfmS|!PD`; z(+BmKtY1HnEIh24`9~Hn?;~vJ4viXIW|9~VQpSaN2Yq4=2^e!HzQyKu03I^5w6SqM zLzmuW=s{f9KNB$c6jP;RrmmmQ)M$eBT2(o|9|sZleO2)NC}F)2>m}dE>p~_GNTm1# z0aK1L<*rmtHw;op2NB#W(?Fzhr=30(pQF-O2;U%Jz7w|*zDM{0;W%CB8lFd@2vCNi zk0A#vU!YaDK> 4) & 7 - self._style = value & (WinStyle.BRIGHT | WinStyle.BRIGHT_BACKGROUND) - - def reset_all(self, on_stderr=None): - self.set_attrs(self._default) - self.set_console(attrs=self._default) - self._light = 0 - - def fore(self, fore=None, light=False, on_stderr=False): - if fore is None: - fore = self._default_fore - self._fore = fore - # Emulate LIGHT_EX with BRIGHT Style - if light: - self._light |= WinStyle.BRIGHT - else: - self._light &= ~WinStyle.BRIGHT - self.set_console(on_stderr=on_stderr) - - def back(self, back=None, light=False, on_stderr=False): - if back is None: - back = self._default_back - self._back = back - # Emulate LIGHT_EX with BRIGHT_BACKGROUND Style - if light: - self._light |= WinStyle.BRIGHT_BACKGROUND - else: - self._light &= ~WinStyle.BRIGHT_BACKGROUND - self.set_console(on_stderr=on_stderr) - - def style(self, style=None, on_stderr=False): - if style is None: - style = self._default_style - self._style = style - self.set_console(on_stderr=on_stderr) - - def set_console(self, attrs=None, on_stderr=False): - if attrs is None: - attrs = self.get_attrs() - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleTextAttribute(handle, attrs) - - def get_position(self, handle): - position = win32.GetConsoleScreenBufferInfo(handle).dwCursorPosition - # Because Windows coordinates are 0-based, - # and win32.SetConsoleCursorPosition expects 1-based. - position.X += 1 - position.Y += 1 - return position - - def set_cursor_position(self, position=None, on_stderr=False): - if position is None: - # I'm not currently tracking the position, so there is no default. - # position = self.get_position() - return - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - win32.SetConsoleCursorPosition(handle, position) - - def cursor_adjust(self, x, y, on_stderr=False): - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - position = self.get_position(handle) - adjusted_position = (position.Y + y, position.X + x) - win32.SetConsoleCursorPosition(handle, adjusted_position, adjust=False) - - def erase_screen(self, mode=0, on_stderr=False): - # 0 should clear from the cursor to the end of the screen. - # 1 should clear from the cursor to the beginning of the screen. - # 2 should clear the entire screen, and move cursor to (1,1) - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - csbi = win32.GetConsoleScreenBufferInfo(handle) - # get the number of character cells in the current buffer - cells_in_screen = csbi.dwSize.X * csbi.dwSize.Y - # get number of character cells before current cursor position - cells_before_cursor = csbi.dwSize.X * csbi.dwCursorPosition.Y + csbi.dwCursorPosition.X - if mode == 0: - from_coord = csbi.dwCursorPosition - cells_to_erase = cells_in_screen - cells_before_cursor - elif mode == 1: - from_coord = win32.COORD(0, 0) - cells_to_erase = cells_before_cursor - elif mode == 2: - from_coord = win32.COORD(0, 0) - cells_to_erase = cells_in_screen - else: - # invalid mode - return - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) - if mode == 2: - # put the cursor where needed - win32.SetConsoleCursorPosition(handle, (1, 1)) - - def erase_line(self, mode=0, on_stderr=False): - # 0 should clear from the cursor to the end of the line. - # 1 should clear from the cursor to the beginning of the line. - # 2 should clear the entire line. - handle = win32.STDOUT - if on_stderr: - handle = win32.STDERR - csbi = win32.GetConsoleScreenBufferInfo(handle) - if mode == 0: - from_coord = csbi.dwCursorPosition - cells_to_erase = csbi.dwSize.X - csbi.dwCursorPosition.X - elif mode == 1: - from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) - cells_to_erase = csbi.dwCursorPosition.X - elif mode == 2: - from_coord = win32.COORD(0, csbi.dwCursorPosition.Y) - cells_to_erase = csbi.dwSize.X - else: - # invalid mode - return - # fill the entire screen with blanks - win32.FillConsoleOutputCharacter(handle, ' ', cells_to_erase, from_coord) - # now set the buffer's attributes accordingly - win32.FillConsoleOutputAttribute(handle, self.get_attrs(), cells_to_erase, from_coord) - - def set_title(self, title): - win32.SetConsoleTitle(title) - - -def enable_vt_processing(fd): - if win32.windll is None or not win32.winapi_test(): - return False - - try: - handle = get_osfhandle(fd) - mode = win32.GetConsoleMode(handle) - win32.SetConsoleMode( - handle, - mode | win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING, - ) - - mode = win32.GetConsoleMode(handle) - if mode & win32.ENABLE_VIRTUAL_TERMINAL_PROCESSING: - return True - # Can get TypeError in testsuite where 'fd' is a Mock() - except (OSError, TypeError): - return False diff --git a/venv/Lib/site-packages/distutils-precedence.pth b/venv/Lib/site-packages/distutils-precedence.pth deleted file mode 100644 index 7f009fe..0000000 --- a/venv/Lib/site-packages/distutils-precedence.pth +++ /dev/null @@ -1 +0,0 @@ -import os; var = 'SETUPTOOLS_USE_DISTUTILS'; enabled = os.environ.get(var, 'local') == 'local'; enabled and __import__('_distutils_hack').add_shim(); diff --git a/venv/Lib/site-packages/dns/__init__.py b/venv/Lib/site-packages/dns/__init__.py deleted file mode 100644 index a4249b9..0000000 --- a/venv/Lib/site-packages/dns/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009, 2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""dnspython DNS toolkit""" - -__all__ = [ - "asyncbackend", - "asyncquery", - "asyncresolver", - "dnssec", - "dnssecalgs", - "dnssectypes", - "e164", - "edns", - "entropy", - "exception", - "flags", - "immutable", - "inet", - "ipv4", - "ipv6", - "message", - "name", - "namedict", - "node", - "opcode", - "query", - "quic", - "rcode", - "rdata", - "rdataclass", - "rdataset", - "rdatatype", - "renderer", - "resolver", - "reversename", - "rrset", - "serial", - "set", - "tokenizer", - "transaction", - "tsig", - "tsigkeyring", - "ttl", - "rdtypes", - "update", - "version", - "versioned", - "wire", - "xfr", - "zone", - "zonetypes", - "zonefile", -] - -from dns.version import version as __version__ # noqa diff --git a/venv/Lib/site-packages/dns/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index cb2ebbb68808afb980ad60c3c7463ba2d655c7e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 689 zcmYjPv2NQi5T$I%mhHM|fplwutR9-6MUkN>iUM)BAWP7N5J1r4Ss_f33Q4Pxm;Ot( z{t}lCo%#!%dZay+fZn}3=#F>yXqL-4!E^TO&HaxFA-|*Z{~4k41wZ#1K@dtBBC@B9 zW@049YSfNto)MAXkyUYcCA8}Xe{b~p`u6VJ8>4p8uP*5`?gm|Nc)bHH=sbB3d$0pt zCT_tQ)q|xItl*%g^P}aeaddIye(1o_9Nt}hK*SiGg7(&QLzuy14V{-phhnQZ=FDW< z?mgcqpt;oG5xXAq5U;|t1?PAJA=kVGT1FJI_UIb{VPd*E+Tz$@{;-!dEo_XT5!`b+ zPo`GfIa(&}@QztxvCmLi926|r$WF5@EZ~R^(xrt(=EKB+m0X2!%J&BMBM-QTg|}Qg zUdNee?wxEfgt&vjO5KF9_li!fNJ|NmeTQv9n8x}sV|F4SX#QPVpyS7_4f(-nptFd_ zWtNd{rGh`GEm>vuIhxy55vGg@Q!^F`SBkMD!o{g-`YkLNJNbg+)Ld4nP4FD1)7Vsi2GDq7pTXr`wM3Xh!KCIkC$J zLh?i4=--ilF&7S;IQu{qC%)G`qkU4LRo&|S_4oQ)dg4Z7!JxGM=Z%M*s$u+v#&~k5 zu|-*SsQAWU1~Z>ierC1NvY1URn_4Ed99E)MiJQ;twngnSt5Cb5+BUUaR;6~8W;@hc zU^Qyhs8wS1J)_wO2w@`G)Y_sfKcRvfZIc;oi`5mX*|s%a+tE0*i`u_k);qT=%*3u~ ztu+Y4?Kn#KlcW_`v{jx^N8Y9^LBpAOW_Tpyo^fur&ds#WX_fEcpyN@ zxgpB*_wVlZ=baxV7qZhojC;JZ!{t#D_d5@E?j8GK=a@&wod@0hj_fA9`6;{u0wW~A2>=1Tv97Dy2Hl&)}6enDzIBmIKs z`I&GlSPD6;Ux|QAlLX|G<}v`#3&{MGG;^E-0ZOMOB*J|y!8+DyL=tj}@@$SGwCO@C zBEQEyFQp^*Vm1g-uY2C3fgkD-0l5YAS1h4`Kw=HW=*m?M_bzaCsK`1MF6o$S<5#!U zNI;zv3CG-`EL&6zZP4U4v$%cWFtWnu4%uLdm7g1AgB9k|f0;GCV@RZeT9}u!=&NmSS|CYL$X8mi#6r;-XLM z+2*RdP2ofi4!4H5s~PUtU?IA= zK9md06rxDFE}*Jzd zwQ-(J8t0r#Q#NyZh_RAUH*yj)_75F^OcHktr}Mklk)ai;UP-#&5v*$(YOO;*OvAhr;h^F=i+$QiCjDIFBFt zNm^rECf&$Sx^X0w5sjP}tT!!7ikC_JG1awwZA`*$>hT#TQh-t_I z_>gIvI`f2jfvmY_e4D1s6}1BH{4o3i6O{8>AIDMD((tQtE1KA6B)7Uh2V`vx0ahje zFgAz8O-#Qtx!H(B*zH{met-h4Li&`o&Z;q~uahOS>6u725p!BRzS+6d#o4?UkTdOpf&7HUBpMLbBnB*+_%F400M%@(Xnc)PAvW02iQ8CR))vh}Ek772WyGe$wqkAcf?&U1HSF-5tGKZL4 zPAgyQSM6NCyiI5qaCz!^Zne_NAUcZT$B~w0j&n{OgdChw-~n)2&$i!0_utfGv;r*4 z6Y52`Rn@m;`3I?sc%>ewrM`%hm^@27Ks-^w?IvxK)}#zQx&?eXq)YV7Kc=q%Tr`l! zxL1l@>-k6A!=^m>o>pgm-Km|f~|A?KP(6b81)Wf0fW+_F6Zd^P_ryPqtO;p zvpQ|KDvoSn^;alh5CZlp?xPsF%aKJR*zHo5c;6ySSQX36e+&P(jqC-Fc`X8m_6x*w m6-<;%R6ancs5u8Ab?@qLi!ZTMeHtv57dMu#EW3;DYUw{7g#DQS diff --git a/venv/Lib/site-packages/dns/__pycache__/_asyncio_backend.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/_asyncio_backend.cpython-310.pyc deleted file mode 100644 index b74a972c27f38cf7d3dd6efcd9ac3921cf9fc4aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8945 zcmb7KTaOz@cJ3RS&FgS3lE$)RQMQr|_ab{Q$zm^ANFK?ycI~m_(XQg&ae7nv3~Um>*@s2)k_6BIdC?!pOMoPR{zC%vOCIvH&jNDUAeek#RX1nI;V4NH zUEN)mQ>UuV`Oc|R>{lv94cE%QT-^TY8=Cg7{5XDD__&5Us_U8-Xs#CMfzi=jT|N!h zkWbS!<i-8s7KG)pRyINoe`Omc=zi+tZzzGV-tsu7; zl#p8rbM0z-Vc&EYkXH^W$g9Y_8uDs*TYS0{R1b9VSoXQ>F3abNyCR=w(&t(CY`D@s z=dL1srM=uf@4kxih0cZUMfYO&HTSjdCHIo9p^sXyh&~p>RnV{Fdns7P_i}i)eHl5g z_bl1_8}92UTM5pf?2OF0g3>F2v7t52jxPGqZm-$u*E_Ad!WX;s2g49)G#m{2BK{Sp zc0I}Mw0htCMw1`MF9#oMxTD`hGRno;Q~f}@qitxG78|=uy2c-J%>&KWK0*GD_Do-I zSV=zZG^yPSV^0iwy;kp@*Xj2MN%eXhi`Ly?9NrY7FOn*2gb%}BEX$v1g1yS**YB@= zck{+WXMio>rB{N{cCUKni#z35FZ zWx%_O+^`p19qcBH-YheV92>>W(2IH*KjTpF^Tb3L$h?L-`aY6SgRp5z&>$dYU!!lNEK|{@MHg;@Vg(0e%x>NJ55OP0V@=EE(~?>^HLD+)VXM{_6&sGT^T*Xp%m&wB-5 z5mm^>h)3s7uyQr4*d!0x#rFwMoS?C;c*?lZMH#sbLoDDS-)A{kX!d)(uo<`dJ+JEr z;YC!8NE2*aKFP*R?Iy>ZU3}*dCt%qSy2dT(LQqxy-=Wz7K z$>E%6b7FcqC^?|t!iyYGZ89J=Gz{ovgAq$;m{d5H@KG}yaHi7*NlfI-j-wh<{U(FB zg4XFEY8*uU*49~x@m__m|(NSaU0le5q;)?M@Fhwn5jxvFX+9Arp<5$C{8x~^gs z?};AH&c$)z?DV6UYY?pR+M0->MWHe z$u-eD6s$GFqoBfk6Sq{Fsy;e*a)D&y^+ti}-t)Vm=OsnY>-K|Thwo+2doc7nszeZ4 z1OZT-WkO&O7nrc4W1UMhCWwd<5>8-5_8iU89m_FsTji20o015sHk&?YgZGeprb`*n z#idb^hGYy7IWTTvrQgd;iq`D2yDpA(OgfU186NO0fX({p3XB+=+Clr@K;@FTSWG(=vcJGE>M)=zt z2q(>W44HtYSMf6ri>9EoG;vQ|)CgWL-ba#IjGt>;(oOl?`TtmrpbG0z_&G4oEn@r& zNi{Pd8+{nJxXBsFF23_-|1auDVr`$Zt;a^&JbIl{z_ zB;lmE@!{H!yc_R+eEkC@pUxmPS{y7mBK^1 zZ{vQUfKr;DbJOEEvOV(#Bn64$2SJiZPkiTqVgTd5o>?MOF=|IJ`f)!oJ7F*5)!Nzi z?sWe6C$Dy}1jE5o= zoO=a-6vxC)?OD1^R@54$VoozLBkQsqvi9lW5j;pdUako*Cc_W7AbT?j(o#HE~t!%R`=wzw^ zd<}0&Ny6gB?T>F>|A3kXcUC0!j=(NNWME_XTjE1D`-q7gfE>yM3`6GAppVWRXXpq7 zGrmzpqB*~x~+;`D< zE_0~WeAq*2DvqoAXmN@!mY+~YdL?8^e2)p)go`X!=%tACfVH{x8!b)s@p3GZ8ZUl; zW>7EL2_<))!V4-w%)&J!qt&TS{?FhdZjb`eb8a8hvmF-B@8eV`;VeC8I|3NIF9oJl za@E%lSte!sNWiJiBj(TVi>Ue%l(@~7KVdQlB?JxCvHp&*;R6%|xQ}B4JyeAaEQQzA z-)@*m)ob><1B4(vx{*8K(yhzGtt%x9-g+4C^u_(RRm`H9Q?zBucS8Z~DDnKdxgxS!dNwzv*}Cj5aj#M|kL#5VS#oC&Lg0?xOphhd{$6?{2>z zM<6`#xQh;>D9L-Nvv>;(G;+#;MCc-IQana!@kDF!78=dN(LY7L+^ZFJJN?l=H+1XJ zIvlOe%;^MP*PBGN?4tQ6GC#*1!KVaZ-P87LfR?$hZyI~~Jtx-NhT46KGh_RyrI5Gx z6~G$&=%Fqy%UpbMm)^S++hb>6-=mwC-z$tQ@s_0EjI9G5-&(uSE@I6JV-tHEQ|)f{ zisRzb5*$W*Y~Rp6{oY<_^j2IB3{W!m%Ai;##klgcIyMjVUo6AHXR zHb(pb>-?07hs3S=TT%|Md%L$jRN$HvZe~%E#MzGHK@;U}c}+#Bq*K(WrokYNB(XR)X^N7H zlGJPzRYE7iE`1quiNqEe(ml6$1S)DC^N82&AexErsN&vTN-^db{$TSZ{gY!5Cw+!( zQ2le<5e*95FO%`gGNO1@-7#$4!aL=^dMz79l z#j&Ys(r{-N-w7Ag3&Bm1w3*^Pyk(A#HSptYWup76Fl`Bv<&5;O*LvisnfhDQ%e+Vv z;j(GiyE>=E3ICQbNTyz#MMCd_TigR(snPU?gF=hlZ6^!|5NNu&^lZ>c5X~?v9-{E? zaKGTVjmIn4_{}mW=_t>^nd{|FE@)Q@L(Y@aFhZ4|0_!x9vYjXo0Epc2IAW=cZBrYS-4ml07U794?^NDlbiYXnt5Oqqj-z3Eb@uowT`xzALr@XaibfX`&!!?=UUp>{u}+zfI4vw zHVIqxv9%AY)V966v_ponLk-7WM2P09v_zRHa4S=viSu!4BaRG@oT4NLyVLKuH4nf- z!1xrrI0>%FtZn-MQWdV^Q zvtSmi>=!J^Qwca9>8V66J(aN2Q;B>~k?|!buple7B%e7SRQv4WJMT5zQa1wZtKkaD z*qc(Kc^hbpyWD?f8+tC-FqTu|SLODX6xW*sx9lR3BJSt7qklv~&ED5wE)5#b`-b>x zY>IO*b`-yJF+zk-ZR&lXZy9^mxX{kWFt89ebDRr|FLDYGV8DxerMQ6n;<&Vrn2MxV z1id?`M_S*BO94#%6Fn}&q*jruzoH?vkme;lYwQHMFY;qMi`9T?d9M;LptKBw3aW99 z=Z9nCFSWlm&S|99a8fZhrFJDb89z%h+etGp`qHt0R9%D*hAn|J1v+BN5Y!cDM!({G zHFAj=MIA{^>?0#dtu09<3y2-V`;s=9Q#@K8_R@nskW_T)ILF%^g!RUvj3Wukskll? z1rMfK9t0}2Xd=@s!mui1yp^n`A*Uca0fFrv^jp1HhJWSmTdYf-e&TnA>U>W|M^%h= zp$}sZ&pSH@5_HMMEhMR>6~D*E4*4XDYJ7-A4!K$QHY;Cdg%T!!Wa1FC~ zh3dbR%LdKs;b=J%>0{JSwN_$?F0*YX5ms89%qlsUNvxmWnc-YkDq!`+BQzORvL2-= zngBM6q>fTbsHfsF66okVr|aj1$wD423S4+4fn|311T;ohvJPKX{Zu|8jx(N|Tj~*N*W$B+KrTDRVU$h)s|8! zwp*da^|lZ`M&vkBpOYgJoKvHet~xgQ9X|#Tbp;(21s6O7lJn+PrYX}aks9q5j!0YE zKJbVhn7EI`UCli0tC^{W>6e~+jwO%W~r+ z+8Ne`VO@0Xz;2fMWnm7uJMj?{maso#!hT}76_FG9&zL(Y98o}B6-7}(Jtg=OtC#iSXz`_rE2s5u#^sI?QwIbU}D22qVahkSe=qXDD4yN2Mxz|N*Hg@qb- z5INMg$O{K`PL%c8+|7#u&YnmM-qQVRKe^diiyHRW?$kE$UBjo&qeytdJeC+Jd19h8 z5(}j%*b;lr7wc9!wHigSilyK6d?9dmm0I0M#;LOrskq~}gS14Y3M6<^bvw0G&{~sp zl+00)r@}$;oJrE*iw~|{S-A&#wbEUW+QG^~pf=;EyK-yc`i|dP*$Fy3E4RYc6&1$8 zI}p*PzaFR+i0-n78_ae0QpfYcP8fUMIqaus?;NMM$RXnq=W`>X2C+PPEHp^QS_E@w zBwX+_Y=M1RT`_t_&rA$qY#MTg#L;Bb0%pu5wq*$mvbFbb-VbEBwpWWc{1`=0J3R3% zRU68v7OGm<(X)*}#+XpstIePh&$r@5NUQet()?mQtsEcSFW$UUo6n@Y{9&DIA=WKf zz%^5gHcBlmaT{{l4zx70qC^z0VWrpD2pXFn(S~bb!;gb+U`mnPtHv}$WIVF?{u_r^ zo_pn*1_%AH-h1g}8wzf3w><(CX6mMv zf`sX_)NI5LPcmO^`e-3icj7{`*e@k;Ap_1C zM#=-G>j~_d!|s(NH{cH-Wx*`GPvEAG_mfwr+})ZrLY!t-`Se9pRpWW)5v~IH&<4DL}X-Z7M^MSYaoK-HN~FtwnMa z4>Fuw0C8Gcx_#|qZ)y4N_4!Z6od35lrvW0#8I7x7zDdjSqhkpI@)8wqQSmCxpE|BI z&B_%Jt8b$)9+9aZ0)QKMi@LP<^uLY5EatxZul)=E4+46(%z-%+WXRci9$@XYBeC70 zcG>f`w*6K%Bg=G6f^#M@@;UN5R2<<|x5z(Bf)-hxqE!xX>g1ffldF{V%rT!!^oK6! z3n&k$VLcwh@51c>6RNZhov)Mkg%j%A1BzgO>6sX@5|fYzTBixzHA@3dn9{htv^5=< z6T3O_gac1zv(lWT+~RZI%L~?XPOPjRuH?>~wX_#3T0 z2m8Z01Gr>F_p+w^>yYxxW0dEKQgG0MAI{kwiA_uX4OTuIU(9yGsGbMEh=KLW z;&Pq4m8gv*Wi9OZEl(heqA0rYo}#Simp?{$?1e854h~-M%i*7);(cc$j=Sp0<;ySl z6-8jdn(!VP!_HP_#c#MpLSN?9Gv`|ev0Dt)$Ru4`BHxVNYF9=Lq-^lVUL-{z(;PBU zzpYXeR`2Gei1)gIavinPSY7p1;5v6`{^MZJwdQZ#Sw!SUY%oKi(p>CIy(o@6ircPr z=l0!YZRKu$;r5L?^UF766&FbzxD~Y<#v5r)1dT`ph!$8J>oG|}NOOL-OU`FvA-b`6 z$V^(e{;&~r$@$aF^3e=+e|FSO%~sISR#Puwua4Rcq;^B89U|vN+>lbIoT;t(b#1@Z zMLJ?p4AfUf66@oFCUWyJTh(dQMGxFbzY%NmALg~*nvB{WiRlyEU;P3_PRALGR}gJx z;8@7jjM_Qwm@^nP5P!%aIhw{W96n2{4CB9!Nn?8T!KhtD%qn9Y$>oLwaTz$$-n z|85X(%TCR&wL%rwqO}^*uy>GSh5`wjsEz(uYDc(JwV{wOO`@s!of;+H#TuSWA#-(G zGa<<mB4ev;7>7GpOzGQb+As$fO9Kc zozuUY+S2e>ieJw0fS=_64h`#Qu3IEp{Lo_TNXTx1`Z|GkXQ(;!7IPzKAt!OLThNxF zJ;IFFiW=~BBfMyhX*11$Knjs`=`jgtS!g9YKg@#cRrtc}@6@podu&R!LG_!^q}9lA$|A%9+WJ@r+ z$j zBPUps6Nfp>eTE9>IROiITr0?ltG&W~3Og`*jP`3T(*DtPjLh$QXu496rx4@8>8Rmt zmAF}=SK=@+5oixh9EQLGY4ik-V4{Jy8l?1rZE~Blw3Bp7Zpz-@%ZBXp?WR`R_Kh(|jIE!ekS}>THH>#zl@>l@wPco5~HF%BG zSr)6Zrs*C(7zm)jr+Lm(RyrcpW$oT!#B*&}@vQ%bCk++tz`UZHQ>j(E29~qo>2!PE z0?^GR?}PGg>=XQ8?3snFS?yh4U2j z19#BIG3cl8_K>_`R+$Todt?5M3iW`8XQB#w!?-8nn6s~fAcSlCwe@7EbhyjItY^3O zGMP*ajq#NB*2Xj&tcNjaZEW4&ZuoN1U{DiDo=F{x-Ljf+O&QhH(jw2pvc(BZFB#Ly z)L&UiL@JVDGNG@gyHo#d7|xcANY9W|pV@Sy0gv_!{OTR(>NNtiREZB1%|lQAtCFfE z&BgMHd8^-zDC{XKQ`x>kl+lj^%@Xw^3^Y2y1v05zV1|cS&J~b|kj9f)QV^I$@-ibD z(hW)p0r(vtkwDT1K#yY*TU}%1*uf~p`&SERVp#xD4R`!EkhC@pWi6y5Dq^}D^HX{R zaLAQbq3DG)j>F6Mx{{zjPVWlz|o^5NF8KY}g+(C)9pt zOPUIIcDCh^@9daY8QsjhKnSOCUAO*?r=6Yqkik=Pp+m4rGaW({uzkin%-Ri!Pzowf z(>@rrxbmtY!|8KfE_BZ*R9TiFmESe%9@L&8FXzu1lqB1;0(w1h-2ol(+ptX;-$7tf zH306b#I=cPo?Q&->VOtLH0~=rHDI&I6sp-}#-|!EvMcbETXRg1@vrwY8F7n{(op%7 zNtTxs>dfTN+SK#f6yxmy-~*@(GG>sTW?nIvP0?w>JK5oiFU$PHCFd!%rojQ>%kEGqy za4vIz=CYl3+ob_^$-kt_4m<6#OK$@P?Dr(caWZ5C_((pAd_Vr)htkEx3PW4{{pPD* z%Z&X&i}_|_@g=$@5wn;l%r8dnbIJBZEMhCRe-gg+g2hhk9&d$KdI?Q!;dtKQx4JTWe;~=wkrOC?Qyy?qlN~J1ua9ApQ6KHAZf*@#E znXP5g&g@>;m65h>P`eC#m?n>Q?d-~y=dm?kN(SM^TN@~P}3sL1Bza~btb4oYn;6(zT zoHd#ggE@IdCcavTNSIWB7MXm&e{di=n;8L^H>~thnxsJW+!~i12Lwg zvYOG^K^o~cV(J#Uehfhe#>m`{aOhBsmX8s`9X95_@t?u>_p~n%zf}N@AcG4ArjA-2K=2==GHxcG7`HAoBLPBQnuzlixMDaES}PBG$#|#$1F^ z@^3sz(kM*y=0>lLt4p1p?jwV;GNnmq21*javjuWMs84XAqE{BiZqkf+&XzA-ejCbZ z7*su*D_Z}DZwfi0PPZWpJ7#-)$ke(Km{}7r9$3ac28|P;YPr_Qwazg+gfF()i^5AN zheuv)(G3&(5a;$>c*@0C!dSxSVMK@L>?Va6*wn~u1Y88u7aD~#HT@i7zUaxK>J}bU+v`2}~dAvXj5keS<<@c2ShD|`s zm?M5f5kGm&<4yP@PfsLLQOr-RA~)A@O5GrFDM9Z+w~79qqP-?Y^(#=Jv=lcg3ZpCG zsZX)1?m|qVUG*A;*bm$F*_>)sM%OkT55__Q~@Ex60cZ7)VTMLdH^Mi5%C!cPFJNUCbzN5&8W|5 zM)(UjITFHzH-AA|I$os1eVXOzP@X;T5pS9sMz=O{sIwZFV&4+R~G@eo`1RW3wn z&&UHa43$=O=(5VwLi1gyilR*T3RrZeut@JMX1Q7KNl`~Pse))K(Vpw^C9!0Awd&%( DHct8a7hjE%+@)`F$YZEvg>&v-7zV9Q>2gV~~q+8R~$v^0`R z&dQ#i(N;$cZb!fi@U%}0L3acZFuwvK{4eT-2cCFkf`A|hH{Z#u>Xy1&u%*bXOI}Xq z$#cGQQCzRP2CkLgJiC4QnqmBwUZyV#FV|6$6=oQr;Ta(d`G9#$-MPor-OTTnS5ohG zelO>D$16ppe&xUo%|n*F992VWpMA)}QfPlzSxvWNvV%ge? zcSd0=7A+aat#}Z2!RF(Oo=udSD9Ke+DUM)=iHbB1SZW-ybwl#Ld0-tH>&6q-X_o{? zFRwm~A4GmU@`EiIiOdW~NmlpO0`CUh`_U-$s-2y|;AT9M(L?!!Wo6kLM)8h(Vh9H_ z{Q1qBU)lU-5{YDUd@mkGo42CmzKqA4Z{526AQ)^uh(-@K-|F4nOnNf<+!%8P_o8GI zbYAgkYkp24 z`^fRk&BE`%Z~5&Mm_2KnY|SZdxJ-r zohS;KyZ+A2Z}_*~c<;vBZJt?4G}uCoHZZ>8``tm1B)+d0FDjT*)KNhhjfB>+1U^kJ z&Mtbbpw*=w#YN9_dLN@C64m#ZG*WY){rJ;ZH;3pL;+fRwvjd*8L-r1)RO2FKmP zZ{K9tm1;M!OMb}D@9_mAS=(jIpx=L?NULA!+o>6{A3~>}@Q$G4ZI{*2iUmB=o<|}0 zfm+6b)|pkJhuvr_d+{hMZ)o9bTVhf5-rWvlRt=*>_C^795oLVW45AHcE?vaaODM?- zD*o7I4r{XJCreiAFLsGD`)IOyiffvFw~#IjQzu>U?CIC>LGg@(XN%z3-{BQFae0Ol zkdb}~oK~C=tC+5BPqD!fQTM@?h=+;=;u6}$WmHeheB()P5}mu(XVL2wl&7RFwAUtU z9X0qFxhM#nff15yB^OORd=E0*hg=`x^iCw1>$56#2XPWTVQNXIc}`OKWfUcu{BeU# zR!;F)jh;*XX>Eplp+q_9>b*#gqezT`VI-bM&(q{z#J7Jzc}gNgY?wTAiu}|Ja~C0A zps7g;+Eau{A?FhQG&+BUMv=gsN3m}5 z;cX#e@q}x>pCj;D!Jcj;{SS76fo@Td zBS@nJiJG8u7Q}5qI~Sit1q-5~sv8Xk1zag@BuLjPS;bQeB_Szuj2d$+$8}1M>6lGZ zP-_=u=Ax6NE9syrpgwFWu;-!qQ3YTRm{(wLhh^MLp%Yecw?j9q;$9AGVI6lTY=jHA zpMd>hR$G@MDxm&Ow;)CY>6r@2LDE81U_F^sh4dUqZ>1*c(utPXf<##JOJQ48q5JyA zd$(`A4Tw|pGE)wc9L_|8`hStCFHxnqb%J7q^{=BSo7iMFq5bOgs!y<u9OiRXxx;>s~=GK}J%nlS>or^W30{@AU zW6cViEX^$7?*JXamtKLWk{y8;nmcOhEq~5^2rU_ENlht&Q9>T0pD0;UsH}By9wcti zGKp{evCSH+#wV9%miqq!#ec>4Gs_YGMqf$JH4vP)0zwFndJsUKr92lI3-MK&pR?*E z31BB-RG!Uqlz?KkkJ(X zMAbRaD#)}?EkHqp@&rGRh8rk3pf(u5lzygTH*G4TB)Q)zNUG<}f zX~qv zo#3)^w##s~tJ#9ziR5l9?!T_%j&2Ea78gBp6e5_A6lnw|uOubxg_lacwnAVlwdUe* zR`myQHyHS&HSnlKl*EGvaLJeayKyX`M#0z*!Vuq+tn6#=9I=veHsO=yz1^uv7S9aS zFs@GK7@^eBN?JY1m<#Zx9{~K)scj!)c&AHlKylFm=$Jo7NiH!0jC;nOt)2EwzE|FJ zB!J@p?l?l-)zm()=!qGl&qCf|ln@JEQ(y6>zJE&Esk6`aV6^(>y-I3{&#M`n)H-B% zH~N*n3$|92yKZXT+H+I)pn3?(seQ}%?w!5ruDo35AB?8Q!b^={_;Mf zAcTSs%aALNeo%xKAH2S6$kqOZ4_Vvlz*Qqn^qfI&E23CZfM3Qv6uPdrFA5S@9a~tv zQ6xQ=cOP)<`;$=jktT&Hp5cxB~W zoU`f>NCJaKk)(#nFHrk}e=`=*1|ngN!y0}nw~s>}XIsi~7k#`Mg78t)mCE~TFXn;3 zcAUt}B6(I8I;(5hEVk3o6#ZBQP>J|D5oNyTp6I;hRvETr7h!x>E{5`8ivrUf0ld0` zVct@X2~&6>me4STMW-U&Zze=KeL~qU*SfZlNaVKW@^M42cMQfi+ZYk4wagLk``v`*mHzuPhf|1!61sp z5N8EH@U^h4FgdkY@m+NNIf|fgXR>;FVQLO-t(|l2&9`Z+vdT2md;{|uS`#XyT;#EH z$35aN;fzXx+PWw+R{`J&8O_2vQ1UJ05yIcl{E4M(1=$DJD=AxG!xq@EP+!~Fcz2_4 zZw2`bJp=vwcB9d2YDn(Wp1g}2xnmO;~ zmSQRbAQojM7@m0GHGQBC*}5Y8)pm3&cg_YgD-idR%)Y-%ckK+HV_SYnTPB7yD-L)0 z67@W()_tBlpK86mIj}LRG&?Hfd(|_p?e!VgwwiQgx$pEVsU4b>V|(8i)nF>!N8iz=5;Mbm zGvh;J7oHPVQM=DYBa!ef_Q6B>yvYArD%`0PVWg)ox?nsuS5B+Eayv(DT*}yaZq-K(pwT>psg^W)*C3DS{ z_zrEyq-qmYVUL_1b|sMGKhGfjo_Z^TR4+&=L-e;bRvzcdnSzn?qU~%MF)IE#C_-PA z6aNE|+d?(DQjj~R*W5IOLZ#z$ZXF6ZC*_S;a&=na$oK7=vuRvQr*X+1o#buvObUF& z-JmCfyAaYcb(lT%%%N8DGyjCfJf0+Hs09Z|<*A#+_KJ=OT@^%iaKVb4!t{t}kSHlH zL3}_@WW%TEo`@VF>aS1|$~HUr*M*k})b-E(qw|Vm)=Y)F?H3Uo`C;5ea*q^H|Cdyy z|8v%~nrb6C^GA|WL9b56)8C2$xdZE|Uyt+qNX(&Cx#X3TKGt^dAj+!9f5ORC&adY1 z8=&l69K^f+AbJoD3J>1b7|^42ku#u_TdVIoYDD2suNBreS)-MEC2Dx+E#IKO=VpUZ z?~-!U&ugh1&*HgLZv5LsszTdQ|Ly6JgCYVQQ@lpaOKQGZSBI>pSEs++PTU_lnDb67 wb6(Xs+OLubB$O0__e?+d*C^xx(A{*LmD0+!+ROTz&0V&_n|$TV&gv!euS3URL;wH) diff --git a/venv/Lib/site-packages/dns/__pycache__/asyncbackend.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/asyncbackend.cpython-310.pyc deleted file mode 100644 index 451e7cd427aaef2520fb572a906f58779d166425..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2621 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 O-GlR*+AY$#cm5wc@amEP diff --git a/venv/Lib/site-packages/dns/__pycache__/asyncresolver.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/asyncresolver.cpython-310.pyc deleted file mode 100644 index 862cdadc091330a3337413e91d40ccdf8d847fda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13198 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/dnssec.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/dnssec.cpython-310.pyc deleted file mode 100644 index efee7134472dce22fb0436af540d2a9c91bab85f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32767 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 WZ5Fb{Bzr zL{So3_Rw{m-eJnaAmdr}Kqo-qq=iX9VlL_g4T2`YHo*?TUj%;>{DUx}MVBAN z)Oy(dpyfe!rCVjV_!r|_=~m9wQ7F<6u~)#K=e_T|XM(4~n~jr*do~v@vt;HCZ09Bj zy&E3ic!TNBo|tC*a2AYS24gNfh{adf1Rs?u&tB!G9|gZoqwDC9wx<86Df8CquOBVb z!-EfStRDvv_x-%)`%wbdA;opy|K&Oe%M8;m-R@6zhbi_2Q*F1)RHxTt2D0u&_n6g@ z8e+L06}_E1`Ylr}nUl^p>@MsapD+X0IDg_^v2CY^3p~X%&Zj|l#G}WjNFd@+`=rx3 z{+3l7`}FiNGy6lkf9dqDSncU$|9SVyLBFlyCw)8L8ij!n5zi(Gq#rL8eyer*5pkpp z1>#EtQ_|%3{S>7s7qd2-_-kD1eJ1AB@&chT(a31bT5j5|J;icn^Mms4ST+y&ILM}W zo80L*=BZT%6MMbv|h1B|<`1=U+-Q~H~ zOtY0fp!_EUpCaUj??W;|+i1gQgF&v54|4skni>_k=wT^SizaO>$Y+>6!6sS=MM0Eh zNebyHzgc<ivDj29Xw1aVQaPD znuf+Z8m6Dq_%8@7f{hYA#OxV1LGMy2Q6UZS2WGJhzLK#x;_-EaZ)hxXjl$gM$C-mc j;op>$Oli*AomhDwH-9K!f*;9Y#ZKC;S!t{7{r%>DkRe9r diff --git a/venv/Lib/site-packages/dns/__pycache__/e164.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/e164.cpython-310.pyc deleted file mode 100644 index 6748352a72811221b7e77214e626924c72b452f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3491 zcmai0&u`qu73K`NTx#{hlB^^)S{GB-g}ky%M?sVVg<-_79l(IIDI^<7w=!1T<*dXN zmt4dgz (u|-w<3=Fy&+eUl>{ZgS?-(n-n=*SzHeSS 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/entropy.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/entropy.cpython-310.pyc deleted file mode 100644 index b022e21cc8ed61c50df52668b9ed2c8fbca967c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3381 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≷Z|@WK?+rHs(^qCQ$S%# zkIe#&bzPvLjGPom4DdRIzy;FL^cRF`4L2_#P-B%>LxpUC5+D${6NT7x8}mR!zbn`D zTO^X)?xx*FX>O;y0u~f2xpmYB!1y2tCgy&buXcIOh$Pi7@el;9w)2!OVt>xoP zw%H`OO;B$Df2*EXl;U`=dEN(rfMP~cZqbk}>9~dZH$2Zz05iI7Qb1!ekB%Ejx{&$+ zgsK_{Bn6B1$fU7Zp6=Y`#MNe?!Vt4!5C_S+#)d9{UmLTJUD;z9R|0WrI2bolM#6{RT;M7aj#Sf|%}0Y~>(RWw4{jgMcoX$R-sPKV z`bKy#{KidGW2Y3KrMQ%Y2an_U3V8fx#*wH8INBJbM<DIh2Ck|tB+a6{QXQw_Tgmh<>o8WL%`r}MOqMj(>nP2%)h^&Q7`=%d8Jt>B4K|B>6BtEW| z`c4=oC~!l7)uZF|$Kd&=nFK^VQG)gBA_)b5WAI)Yg~0%6P}B5p21G5HtE(p-$CmQo z=QFlMJ;0Vc^>sA$ZFKWsZ?#LD!qm;{v;P3RFa0j=3IXjhedwLq zH8kz0BV=1oUr^)^F@|DwV^;DP*=L$XuV8w?@t-D=V(KoMj;X3S+&;~G7FA~*Xet~k(kk?2F15PV*e{h%@P&Jg@>@5EDLDs=|k_-G|%GNfoq(p zuN`!$Gsl+N92s}b%%Tg(Jrs{0p)R3vu=Qrcme1l_sdYewRm0ID<}Q@wk&EXQdV{a! zWj(ZaN>x-sh!gs6(BJX7B2d{vqQ(Iprn6#Y3w6$^1WO8+uTgiEx;YNbQ{GQ7@fS2* z*-)x=?V2rVwAHBV44s!DG0N4VP_Z$SugtWl3kIE?b-I+4wY}T7@nD({m91oavY~15PJd)Bt39JfKZ~iMM!NbQV`P0Xub7Jj1zm;nOR4q z+DMh!ACesVC-@4COgpe-vENdL{P!{G^TKO`fT9D4kh0c!G-&Z2v^c0{?dtEhh<_dNL?C^! zARQ6P;LsC`qVkHz3t~wI*HIs$%VGthpHQzz)GlpNlr#- z|N060@xZX%UBiCbGwh%V9mczG-)p`mY8}30;mz*e*R7wmRJt|n<^$PkN_|}9!`7qb zgVVI%I+fXJ>rwAnOZN)7HB39lV1#aoOy57WZVbeha93ELY7xM&=98(2@u-FmHvqPwYkV&t@cS4sypX>aCY0G| zkaYT~*2Yt^7^$oSHcy%hBkX(7^=ANrp0ko%kV|szluncU8lLl#m9*p+^pd#tzY1y&_JBFGUque8{?1H4JecRFKOF>g63_r?y8AwAeR$3e)=VYvp z9vgZ(FD*!l+zR^!-q95R4x%bFr0hjV)h7_>pn*3H$5>dX>L2u>ASEg2OZ1vP@9yQ< zsZ>RjMjDDzZfQA8Ra!_9^?SOA^1}$ZM93WVb}{?f6gWJKV(jV*tJuunMiZ)mq)H Q2i2e&;^kF5I=w>gU(*uY_W%F@ diff --git a/venv/Lib/site-packages/dns/__pycache__/grange.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/grange.cpython-310.pyc deleted file mode 100644 index 7861052d7e2f1effc7a4e2fcfa83a0fd9c8398c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1149 zcmY*ZUvJws5a&P1ijxlMu(eHr4jizDxkys%X+x0}YaL@iQRJcN_7Hfm6!Gk6wkegQ zjKq*JpzXIP3bc>=O2U9W^eJDVFWpgAwvGaiJl^qlKi-kbuU+dBY+w9+=PZs0dGD1^ zTL+b&u-hL{C~`s+RcuD*?1WK2=QDo7l>ngvU=a9k%y-CGs8DrYiIY(AW73P3UmYGD z%by2FgQpLl4Wvo*1Z0})1sI#dw&IGfgc7TuBIZ^_l-MCEm@;$Ak>BZCrowmh1+B;-`R%(^ScQ#kuL_hv zpFPJb@zP^?47LiM-$suPTJExvo<*j%}OurIU_&r&P=eOGk8&&w4ykSk8HSVvi zrQ5DCL>yfq>Mll)rp&@)@`ARjyyA*Y1DpG`iXywfmg{-Nro#NuB5pQ_v|<$>`y_8I z|LQjxb<&-I^cj@n+{|S@mPwoPOye|;zqzVJ982pG2XoN4E0>AxN^F^SFafjQZM3@{ z>h5l{(>fE!yZ;6#li7dB|Ht*ATY#rc87%@hUtUkhof!aRf{~EJBAJz7QT-O#7`Kb0 z^1@3fdU3qpu(9PAZII!z{EhsfvNq_ct xhwh@t^u+jlnoSfn$NOMD^Q!l4PV$Mk>0P3Od9KPCJn%KM_>UptI>up={{x5EHCX@v diff --git a/venv/Lib/site-packages/dns/__pycache__/immutable.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/immutable.cpython-310.pyc deleted file mode 100644 index d4489cb531297ab8de15fcb026eb3cc05936e393..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2432 zcmZ`4U2hvjaCh&+=d+WBv_w?U>Oe@Xqt*o~A%vo+G${zF4N_A;Sgy90+jVlz`Oev0 zr*Y&+Am@jqZ{#oS3qm~c+&5G{X3mb27IjZIyE{8O-!ogx&4mQUmEW%I{9YmC58PZF z9&GNxuO9;tM9_@1D9kKlJ*VaL+?Gob?_^%jZ~2r+{~ID);T;p) zBP!DAxFQhMW49Fwx=9-0pTL)FG?;b1%7->si?b}=%4CDuYTD}!3~mynxj3q@xd*>~ z0zj4;wV0s5oe3sg;Yd%o(%&W$#nDX`Pzm8rnJaoHMEty;7QRR+FCE}^G=+YLJboabT}KhcHm!wUw;8$ z#MGQ2BWh@ub)7NnMs!5Dn};K3OmH*716mm zQAZWM$n3~S_hpiHQYkK+Hp4KQj&D2B@>KKXDAm!kCu$&{-NLJRw0zERIeMOES+pgi z=PK^^fnAzwBV#e+RCFS+9|Sd{=({`{Mp_zR13c4CG%N;DtU#Lq0N@Sqj9*?v^1w)y z$JvaRk{uw)6R9IplxCc3(wtFkG%7YsH7XJVt*s?R1_^-?(bkE#56 zJ};1w^#^?s8)-eh6YHIZYh5j~j`ATW3NoFj0Kh3x@4)oegS9W)-)pIKyT4uZWP4re zT~qYi57!^;$60${=KJl3=~i2(M&9nn$!@$Ybz9{6&MY!b$cupUG*1oZHDIc-vKH$B z4OpFq^l)w+)M}nlBn(c^2CipmQ-=*C1v#OZ6r1FfLV2h;z}gz;+tPpzJ#hN*T}d|4;QAQXO|Pmt=T}ySm$NZ-iHNB7i2)xbwQ6Hbz#p=oEKzF z*U8i1h(S8LBQ~ZR9a`Rn`f)ZCicpsTG%Dp}eO)Lc#l#dB)YjI; z*jT^V>OxG>JV>b67zO4z6Z7bfT0%w`rgIC?(|DEh4*{>yWg&IxBAtiNXER?t$E)U)+P+?Tg z#JCVhRmxEjqW^Cq5^#PS4?hAhGi!q1Xk0=+47%~C#cpPg_M>S)>qODRQ{S{uvuaemU;IpEHDy=LX)f-HiB&1oM5nR-aM>8 z&H)ZH>_@UmTw=W84NCAcj-Y}a!^t{OjHyq40*dF8+dka>94MTN6jRO>ID2d=W60wX zISF3C{ik7@9kC~3=B1Y*geRmd1?xlb;Qc7;q^ywEBJ}qrpM{bq=0KrK%c`-J>4Q^hJJI{x cIkQr+!OEm6SF!JujVfRZw9c5bM3-*-2Zr1#*#H0l diff --git a/venv/Lib/site-packages/dns/__pycache__/inet.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/inet.cpython-310.pyc deleted file mode 100644 index 40ce2a3afe00b72272ff16cb6f493c300b4da149..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4569 zcmd5<&2JmW72nw}E-6Zu6@A1hl5UKo4h36HQ^NBY1;c3NY$7)&~yJ>fvro)Op zw^`9TUb7f9Bxq01}Wdt^7~w6rQ_A+1AN<1>(6DD`GSo7ed) zB=e=@A|!MC0wfDll6ig+l9#F`e}yjytRZGX^OC_|5?B*YS6G;PkuN=Rnu~myuRJoE zOXc`FW_+1n!uVxw-ZvWG7_7c85+S3uzn&-|6QTTob1AaS-xG0HNI&c)Z55?Sw)O-z zF*X`jZrw`yx%Xk0#6g@po4sx{!WwxvadDQYBe99)ndb|ew6t^;%{$5cYFJ)o_J)0LS;07 zmMheuohdoe9&Mu>RjS_$qD*Aa+(^}W2PWzW*qGmyGQ~(g3eQ=|&$^-=g^}R2t0Yx= zr_p5eXl`v?>>JbX^p(iAx7W1lW}}ib6J0d$!X?N>`J9iI*c>je2C zWNm;m{?Pv!{4~-V_%o;~W1l@XhsFtGhO!Sfk4-ROP)tR9Yadcuj#0A2A`1==umJ~^Y7me1fK+PPrR7_ z?H~c`{T<=+(LT8*b|}-1-f@(4d+KZ$7>BP>6!0d%NiwJgGq2u#*cLi&7w8d=d2O<- zFPUciSrF%fumxkZN=NBTB)2iZ9L{h&+{|7S2$v`^D`6znC@<;fqZ`74^uC(qC}+_TUxL0aHVpn1*|`l)%o6 zfz|YV0P2o)N{W9#0K{=gXrwqRN zUc>q4)?LAY&)TyFdzQ308e7ww(8hx`y@EEcp+B$fMZ0?~r7J2k2v4O!oiCxJgX35D zGc>l$WAj*7Nj*a%6b{WV7?DXa)KH5#;SEgMV1xomrtSUdXWltVnNlS-^+v_C4QE+4^SPqgE-F0=(~=BGx1l0aMe#yjY_Pd>&T5X5mex1 zJ{CNTxZv2M(q(3r^*X5Spsg1wH%s$VIXgLHaWoo&(kkLuhx>a0#j*e~DqQn@T0GQ~ zK#6KhT2q%4FxRPY?H@&POc{mtE_h+8ji>C*B76{M8w}wf4tBGrE4}0(Nsll`c?~G4 z9luf6VZEpcblR}PDB*b}%6POJsoX;KoV$gU^0_E%B|%516guKzK6gujqdPrSWIw#G zw>Cch@!fmtw}1HI{mp!4S14LAN?>taQq<%(u`lUULv=-N6P`JXnjR^31H3p{JM9Vx zqL$u#&RV$zpE%3G6@cB+t}~)yL9m}=-fR_(H{*eX#kYoM-K?AQc+MlUErOsfdj)Ui z*K>}12kOs-JPSfiN}7yn(|w{JE{6I#W9$?8<|u?IkY{L&UEChryr(0LM*m8X^sh|p z4%Z`}n1s30h^!4NZ?Ea^z`S`=zJZk+wtNeZ2}Xq}Sz*O9fxd>-iliR?7K3zURx@qn zaT_6CeiyRm&NgrfjOH^ZIz}(LhL@ zyD9KX%H8su6eF*r<9GOF#1qq_{A}uMt;?~mb$^3xG*ZXf%9VBv_iWEuJfuy9SNuxbV z?`4Xf+9&lr!TVk(<-J&ZpTbc_cRc%|XD%|&^qA|oY}r~~T3A|GURX94?PoP)Oqa5z LS^K;9#&Y!^X!eu4 diff --git a/venv/Lib/site-packages/dns/__pycache__/ipv4.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/ipv4.cpython-310.pyc deleted file mode 100644 index 5c4c5e4d427bc2f1f7de284e9f1262abd86a9379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1860 zcmb_c&u=3&6t+E+$z+l&EGjFyv}nW+t+HCe9(q|+sugVyNGpW4+C_@8Y9?bRbu#s2 zZ6`EQBB3p35LZquH!l1^zHs2w69+Dc3p_hXoA$6=@Wd};`}vLE`#yhpwHhI4YrkzC z{Z&HfcRN^ZJ`5g1S3NKkH4w#=WVnIh-^<9c*YNOs&TkZ`&jMOt#g0z{TKvv$gfwIx zE3%+N))A}(uu`HCtdwr7*ga)hft84o15~R{?tJmpXe&Nq*?`HoGZd-jxlr{BI0yQ& zhE3s_fC*DfD3wep6G*0qQl!{AESh}}pzlIgTVOPrqEk3~-;(cj zzOw~qgLTyL?;to!aq`1%E=El1I1#Zs*5acv7jc`5M2_Q5E{|iK$C{mJH>gKZ4DJ5H z_5Oo6iCeAqSTogXJ&5%YdtIo-?x!v%<+dsN!uHxEqB zH(ths@u*Oy#7!_kCr|!Hz&6pW08$= zif6u#dSx1R@znnrKSkf8uYm_X(v|UZjO?@A`3l+*qN?k{xz^K@Ep* zoXh`WiQO_xvQ?6;(qzG~IZ^(!jHpXnV`-sqG%@($H3TeSETImdt2HoPK;T6%!+-=n z#Xpjla3dW*;M#dy=o&Gk{?Pb?L~1ubH@9G`iMBJYbebOzc0RN5Z16QS*>to>bS~=K zS)L}D+JTp)XT$#-TCHj#uDDP-5h*hTmx&3ONOKB9HORP@AW}$L&5~tnDqu{JE6TfE z8!wmC1W?Ffs_pU8zA5c5d0#8YH^IA6Xxj>!f<3*GZ`%O4eKU z7<3`gSE3Pfd-vh$aeAdJ*L5QiG@eUe%(ZgzkR~D*9EyCk=YQr~!WC0MRJi%|OJS+6 z=t`><^NtfacLN{|k?VOPb7t0jhhoFG!r`>R)eiK?f^-v(%4JG?!dxjGuOj&YIM>Ri zcz8(j^zcw_!q^0QJm8`$txuzR?TmBkykosQ;K|j8U8I%IS~--C(c$)SPKO!Wu}~^I R<=+kouzT&*3tj~ diff --git a/venv/Lib/site-packages/dns/__pycache__/ipv6.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/ipv6.cpython-310.pyc deleted file mode 100644 index 290caaae211907f5bc23fc82dc3a1f442f53d3f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3917 zcmb_fJ!~Au72cWMz1!RS;g2Yiier0?C@_zb7$z1J_#!I`^y3I1gg}xV;7sGVyqP1H zT<)G`<|vZbGXm4@QmAm62my|On;>;6cL@+zDUxzhq(~94RuRC3nfGSz_#+!ilReDr z%zN|R%$t4hd+*X})wkf8`sb_bzrA2t|H8@XrwEgq(Bz+>V^-5*gwdEZiFwl|g|{8s zTTav2a+@y6`GscD@V#b{(?N+j2c+pUmzPn{!)VNm$}k#d z)2zx}Ug6~qypbpq5p;SwcYTXDO0OyYD4H-m5NNn)_h!%G=?U&WD%k zx)?GhxRkmexax_dO;Bq1jKRAA?G`lo8E}-9S^IENo3`*3T-!eRm?%21GwXo#$(q%t z%ceOI}ILgs>0AuBMqN5orMVNhfRptu;YgCFb>gRbr)ma@+dw4Ol}n8!pv{v#n*m=wx=koRzcE ztkth%mCW081j|bOVpaipkbS(A`EmsJ%X#{1Q*s{D=eppsc^g1LAP2V}9r0eJQ{(37-wz*J2m;}Zbh95PEl3+DTLa`fkQn3}NG*Em; znaP6h2k^`fm(E`f!eC`(bysn@vT`|4>-=S^hSCqhNOB2s?}u@Z-w`4eD=R_NG2+LE zkja}W_~Es{C=cQ^Sz9oBKQJCA&BjuJWKKRD2Y1^$vpeh&3Vv3HKuO6!blgK1x~9{CXOA`-d&Ncr$Bn}Z(7z&$dQICgPqcq>e(m9n$#xX!;yT}n zqt31_Fy2lX*VR_cLlz}#tvxPM?QVsty{_Fgk@mW}5O%vfVcHd8vc|Q|5~-c2yM0xc zqJ*nfqS8=18)=l(#{?c*+n`?;+Uvb!Q)&`v5^LAYG}&tUt6Zvt%o)A1yaK=Ozx`KD2ou&idap(7zcoXftd8@Jfp5#Ia@ zO_g?+mu}zL4&&u*o@_5KMXSp)Qv6CcY;T5ZTrPthKL9hXEp&IqcR|f-&}0l0`)#*1%=KPDqqXpv7S>lw&zoLX5O;P$aJ#vcv zkweVR@;k8W+`@dlF}KVvEiatu>K7$mYNN3*FY&7{%r_br?`j7fURR>EBo(|R+i91# zDX>RR6$T|}2I6i42O&<8eJcIT8c={Ln$QgTjEFe^CYuomJX-;{8HjTjg@6wLr~rIm zt(PIi5p&AjC~OozCJ@*TtXMpm4?G6oCT<|iA>hdyr+6j9TLNCm@Rm+^06$bb0O+I2 zACxm{pweX?faj;MssbS54r&bOzyWZDF=V2_*n#y7U=d&z;j#S8fl(n!-qWp z=-DLf@$ZqmncLzyJI5xo%B(eIWj?^JkJ1@rXOR8^zF2M3dP;X}s}YS`RJ9Qs*~j)NF@7CA+T^3x6Y-CsutbyaaIc5=1_RV8r87@H|3f zchZo%7V9j^;k%53kcm!5?M#p0P zg7zaBC4ihsn`_tXtqVLcknYNE94Ub*M=*w{BSo>;f_gb+5?Q0Pa?Ih zeS^Wnaclc(3pkJy#5C%7#pp1AAF4DFGf135;$*9xLhc*(Mu#3hLjyemDppI(V)rU` zlPFp0C8JE_=7%Xg+U@4)wq6x=TsRM1(_J-a=XN1!Nbv^JzlRFQs(2mwzT`Y<@vW}f z)uncrq)F5cV@=wcv^0&|CQans918ygx^-w$LFd;1?5RTyz~?Xzkd45fHw1D_0h8o9 zbqM|1FM6a#d{|L2^b@GZmDr|%LytTgIUX5@**Ls?LfwkdN{`G5Bqr;V=jiB6jf&2L zZg2~lL@xl?1^_=GP#TlHU*D6a7Lfq^Q77Uo7*!=RKz`x|JvCIx*$I3zrX7gB-5=3z~+J;Ctfd@cM@RnD31J=xEB? zAOmW8Qd=wK`SU8 zTo=@C7XiW`9Qtardgi?O0X(Fcda>9}x4Kcx#d+NPE$FljnIJ!018LW>dj}cLDma)q zv3M7W=pW`Vr`*ZdfB~(&>su-7#ry_Fjl@dMnZOu^xP#uOleT{cOSr&xKA5y$EB_aq C8vsxM diff --git a/venv/Lib/site-packages/dns/__pycache__/message.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/message.cpython-310.pyc deleted file mode 100644 index 61a0028b470efb5de6327a400dd7e824f6f4603d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52897 zcmeIbdw3jIb|2VX{cbdxAP7E1N-gR^0-~VzW2hG)5Fja$AO(PW^hncab`{8O0^MMB zLlk-%GqR|$G@c#L*s;Bd$H@ZT$SWa zC$Vfx8rj4B{m#9&s=5JC(#-7l?PdpL-LAUt$GPX8d(OG%Hv0Rs5&RAP{((y`WuuXQ z&5!Wk0el?8)BLG;Bw|O35j$#I3(;a!eyyS`}>I|RSHy$ycb{IrMRH(+mv-*(?`7=DBH4*2cx{YKz7 zWbcIEPT%h?`0cWH!*93mcLaWW?7i^YD}HyQexvZ)XWsb%!&CdX3w6 z+K1kZ6p!17?P2^*AbiBW3*mPm_GHG&9Ld}b*MjT+vn%$fbHcs{wL`7!d+~b$zxO#O z?fa$1Xb-+0z&l6iRP7mYpJkol{~+Q$gy&&AkKlO}&u8!)b;joR*^k+eznLhWMm?Ue zpF};LL_N+(`BvtsjAh&QG3P0JOqVl-{FqO;+^6w99;yfP&D+QA3FLd0IoXaq=_EJg z!FXx=gnbh6&Y{MS)Sj~~`))k`Klo19X6)#EpM6T&#*ur9?XsVdZ;qb&epbFYrt15& z^ak3ld*KXfIR(E5k@l?qJ*R)4!!O5lwsu~6EZo{@9cRXQ(4NI})ES@OZ=biHN3EYn zuf1Tuh+ccqv1%`1d|$+2;3Q~R!Pf2o7wU|TBFQPW=hXK26 zUqFs8Irr9z#Uk9#7C#I3<>Je5Un#y~TQia2i|yR;shPqVr`arDbeiuHi%kuuyx3TM z#fu-WR$5;CbhX*?(r1@i)keL%;3a04mlhl^alVdkFJ37(TNNe?|3&d}49|N5aGVGb zUxY{x2#t zYq{k@4T%cnR-uIsbLw`XF<+>nGu%F89yCzBZKvN3IQR2q(0qMt4F}KHFV`Da>uPW& ztImSmexCKbB%@WBr%!?XTeymf)f=sX>r@&S>(w>}?dm0`UZ^zcuR3lEt&|Zgv{3tO z0e{sx2DMx;-FSnF523yf`xWQc$5uS`blIK&7`0E2)eC3O%}TXgbW)|V?7FC16N8QV zxlW;h4s_9r<+@ah-C4HnssiwWU2c^NO{c=o8+GnZ)ao(6j{N#Wb)20!b)x;kSb@Kv zsE(oG{%)$f3l%)(SC?NOTiv{d1y=Q0XQh2u*ZOL;b*WIU7XXd~mBM9bMSuZ-;8b6A z>>KskZWKJ>SA$<0su6=H|C*d&-Pq$&v>1OYG7oaej=z~MChUZr#G;pcD-w?sQ@|}L zFEi^d*DK|gW4HGaZd>NFFuzc~NIcSXTBBY{Lt%xu%KWipPUvlTn(U%h6P+5iyhL+($#IE?s`YBCRKoO*H=TufFJ5*pHofHKtNeW@>Sao$ z$^wvDsT7);`;q%O7GuHL6>Sgt)gCn&c2$klWYlpy?-BcSA~n#2dr_TXt9@atSy)`I zTp~&!IP1n0FheViWlY!$PGQMyRDi%RJXwJw&d6z}wd~fLg>qqT4j69KOwBV2)6LC| z`cd7zD0DdL-h!WZqAqFN5Y7>F!x%Goq)pjGdwb9(o$+wm%`ss=oje_Ob+Hd!xl~de z=CWs`Ft1;CT*X;fFr6oOyuc_@oZ>WRZB;UXSYGQT$TL=2wC@HCIW>BcbFjKzRg;>Dz$D5jjW z+R$8!7BhAlQ!V4=HHgfp6{0<0Kt?YaO_%L@R~$~*cUjnmsm$PUJWZk-I|`g)O}VU% z%&Fn17pp8Zd*&BV&0_hr>f-WZ6A|BI=5edNySqN4CeGAwcC)$WrJp-LF*AGW?39-r zo0@rHV%p1$ou55Cq9q<2X2oOx1+z4UQV}f!gU+2mvLUJI6{hg z$;SLVP7=lmv}BK-D5jl^oy1Lzi+{>azZnNu=dnxK zW&^n2jL27SJnqvOZ@?Kqyc~D!^3@x!-_A?C?ap?@+lDX3+rFV(?%kQ+pfiYggWSpU z%iduRVIkjP@3eQ}cL=+k-S*q|9<-ycwzIYiyPCbuZhN1z$Jy)bll@xK*^AxYP4<55 za&EE@*f%5He)|@?fZqf5tu}ZO&TfDc_s;R+&Gzj<`w@~t$Q|~b2)V^R=4~?r{YFtoa1;xXr#x)yO`A-`i_<*mp~;JF%l?>^rfmW}Oj&I^T;r--qXZ z-Ht=>V<<*pe#m~neh_s(Ea|@YrRZ`n+C%n3_QNP?Sn99Z{)qi3+CCyZVcDOtkK*et z{ly)8ym$m-@I+<=?nq|D{&Lq?Jc%BA3hg?EcI`u(#_;|$p6>Cv8@teP`#4G-b?&hz z>`58xd(odK@H}CkM9c51-9MkiUVI<+-$~~I_+Yd#vWnC2EXp|zf55VR2JchO-Pmh) z#R7u1P|i8~Ih6CDz?%;hXk?N{E60-7H~+r*EpMC(2$ElU9!RjW#9$sC@tZrKI= za&CevB;0}u!q}=jcqI;6^`w-VLaFoiMJe@h-{+ED6`!Y^r!b#t_~Lwe$`8M6FG%jFg#Qx@w?_6wTHFyIr9jpP% z5x1`eqJGU<2Mt|{)nl?ofESCe_(hNo@-L3Bgv}U92}y~Y7N3l`S(~d$pB;mn6Q6!@ z^VlpzO4}~d9k7|tcJUwN`ZJuE68hjh)^U<#iu?`l@M569L2zK1Xe_N1Gj6$VgZpvc z!|oG^;U&0vX?kfxWO%X0Qp?-sI-p3Kta|iHt%BPbgLJubuZ2EQl<5pm#Efl=QS_saFJ~yVRg~*;$*#GtrSw9wb*QF{89Kf zZ-2C24OQ#{0{8iISy0Qh?Kp=7KIBxDiIN0IrBxNd%#kSnvo=ab1H!{YU zx6$cdS-rGL^0yHvBvUpP)WQUAfSMR$v-J14MXK0wGxcbUCe=fwP_nNWs~CXGKw@~yPn{qe%Qyi zBq(LGmb`?#|335oL@kjm*j5Z7MWk=po@|irANUO#^c&=JnQq)7_im<@LN;qo5uyLX zmd!D++a%M^j<$e@YFL$aM{H|1F;Hx(z5Q|WTQ%Z5QaE+I@U7^RU}?l%XUP?Wv*}=g z)xij*(mzJdP0rB4t|_eow}g~t8Yw!FwaB_ph)2Ctt5G6@aMJ?8ziqZq-fx=n($V%d z)0sMK*5&@+%eu}&xmA4?Y)H?#e6?#=K;|pUewNuxWAe5lYti+{YP=I)16vyX6WbM8 z2XjZhtya92SWBX!iFNpXBVxz?ddv@vBQzzUsZBx?2u(AzmhMU!sexX;oNzBl2`PkU zLit8&S%k*iqJ*X;k3Pi7cICmkX5gFCb&b^ek4IkVUrk7=YzK8-j|911aS#`@{o25K z1n~~NY^^3&QxdnYlMLdao!dL9^(f*Dt)>~?N!OCVdDgszl`KZKm*0Bnhbv#XvVwSn z>msrH5@;GgRlfa8?$yE12I7hIZjVwD_EGD12idt!Q33+n_JgV(P3^E;3~}BYA369;SM|7 zPBoT<{ozHk?WE#_w3D*<76k3L6Al*YLObOs&vu_)drfMxjWL}bn|k*;{;;rH)rOaz zX>mn9b=FH<1$uPU9D9m@n^Xn5pW{bDN_3C$JG|TN%$koHv&<&g zWqRQ#IrZg5uMc7oXYm3A9gvG8Q0QXQ+hJmeXa%tl?4>U{El56=o#BjH>p7v^IXY!l zB-(VJ=5L%_e>C7ywQ>nHb@l;P-7DL_$1t$_y9VKwxZXpCJ3?_qBg4&ty!2n+w?ccxmpb0yZPM$ z`Bh6?BXHk_31F=UbV)Dn}o5l3O1bQ{<-WQEf$UYOfa;OvcLt+Sd(hqs?%6=um zYJX$)YQrE<1&^S_$_s_6@LyL7m&&h#^$fslQc?nmNDF`q0SNtkfL0=vBR*Nf2|x~; zo(N`TG;3*d3sAn$Xe@+bd2$wPlWetFtv6fcdc|=cN53hEJBBxa6b9aL!6FyB349Au zcwR!pB3`uWr8JZj`^C$El^3n|jJKC8m7FW3()&m+L|`@*$FQnr5QCkTf7bQ1#W(A^ zbv+&n$P|^hYrMIr_zPGLA6zdwKtQ=*&2U%YZ|G98W;Ur+9m2poFujmpxoEgd2Dwbu zRWJ)p;33u5O&d1YtRb0Y`I767{Hae_N!doar)prC%|ZdhlSVx$8!Kv zlyGH|-+mb4A?$NHY?f(<G2N7u? zZC%e=*0=Y?tiOyWLi?4!$Y{ze_*P$e@mxs+R2tHAMh5Xun5 z(!(FhWV&2!BEsC<^ISNDH;WZlVL!h<)n@%rtDqS6n?Oz-$-x#4qptQgBU9A18IHST zjH(S@9dBMXC=r3OH{~F>Z8*ig#bwg6^sF_ONuaxmXjzcG@hoP7ob-G0bR3EsZv^55UHvx z8NCDRPeWCW&@hZB9~sKB-|xz^Ae~zPOfXYYVFZvx4yqqD$QjF2DBthJ@M3h?#PIN9 zw#pdB7t5FR;-lH`KZstG$<#Ay?iB=_;81Z=<#OO5+|)ZrAzEhAZ6TVMa%~Y_fV*I~ zR+bzuS!qBe0sIr&S#YSC03X*uw|hDCNyRBG*Q;O#VAZti{?$Zj?{5{fn$s>(BG>uKP-W-LbjylJm*c zzD~ON1=J@maToZuwyo2Ln7K|){4RHLGm-jWhosUr`mPNGIjkq#)lN?1sd^{Xe51Af zjVMYST-y=!ip-xWr3#PPhbaE`O)Ax9UWems4KM1OB5|~KFG8j2=+OX2QZ~Q10{UI_vPS38StTL3 z4~KjWu}HG~NI`=ONV{Dm$LM%7VK*cG@ z9;+uK4i5ijfue0^zP!AET>{rtc8p6^B$hrpb#`ikh&1R!gUGr{J`!}Ebi)(?du~qk zq)E_K4L?8Cx0}>MWf3k}Ax@Ty(lqH;D4d$d7xX=(JQXE0y+IgMrD0U6P`U$t(QLX( zVC!u>I-tC?1PwQ=ikK|^^bXe|jJ9u37hx%k=qj^kg$VX*>Q_S7xLl|^S9L91=VIBl z7cd1mX3!kNly=eR#d5212}_8M2J))e3Ml3B0@f9K1yg&&kWQj(bdLm~Cio9xZGL${ zYt3;zLbiUDj*~}sUZ`9{fHl$SsErG?Nmc_JxTX+&sM%t;bAnY&ca1;IP92{b8|U&y zu;{{E-~vvK`Gq@mE`shoh{<2nSq8WppcJ?=UE%(F?|lF|iCu~O%v4LeI5CENgj!h- z@u=4Wty?ItB7>+$2ug>3zH@V?OM{6K=JCiJBAa4VW!kt<16B_cBoH0^FqZYH;hpYP z{JKZ!kmT@USSl2;k`eksc$8maFt;;`%*gl?)XPkBuFhhvx^FRgR)Q1}l9jM=s(`s< zL3%MTT#8wY`~s9U08C!mbc6dU!xK_nFR3QMaDRx(C3)k%P3OyWeu&Oj==>*izDkD; za#>R^MnMpB>>;YK{qh%-=Sf=~L!9h`+_q=&z{Rd-07NnWkvJZ}mYyML>UCUC#|C9H zPfZWY>HTy!Olbyjvsuf+? zPxcF0GppH`#P=#T|K%EJh!bG>0rd4m{H{m{KzEQ6;MK=dM+$^_PF7b0RbA?HK4!wa z{Ew3G0HA)a=#C&OPD?}Cd}m}wkk|LA4lKK}iQYgueV^+1KGgx>FiWJ~t^EI*>gdsS zmK{|OZJ?%+p?Vc@UMN7{+x-TXEcZW!Gu-zbEXbQJ!x(8a0%XG$?0w`5g>V+5=UFeGdoVtf;f?c-1| zx&}4`SQqJ92CVCGZ11yn3`~fl9q4X85)6C-+ zox1bdlKZ5Ef`sd5y}m!vK5VGVu11bNzR;*(TlM6qpG;}B4Ci_XdiU!nR|tCdNBE`) zp!=qhk zyLz}whVTqB#B_=@6YNdfTGiS}d!f|2 z?7T}N{$18_IH9_15$~eNLD9PmuzQ@rsuyu8hDsTbb5l(1P9dbXABVtll{%FWiQ*c^ zebvcw{Heo|q(-?lkVr=dpU~@j$ZZdQd|$~quIXv%8i-N}KCT1DOFg{;8Oo`%?%$#p!QOS@Xu+iyo$u|1oql6P zFHd*F0d_+c36qemre%B9KCq$r;S^F8FOA7olAcd2f~!<@2}oWZ2P()}DM6NYv31GY zj_-NLE$LHI7@$fD@ys7j=TLj*Sv<`V)C8~;h3twPUF^t!;N=Z{XxSE)f}7xvWdc&r zy?k4>>XscNgxc}TQ024Z@JZq;b~)}IW=PAb#nwbfkN60|D8!+K5?O&a~W}ldgAQtiL?4bq<#x_t5$7SZTHI0sU2%4>Ar)K_ejY*(f*(5 zq~mBMzLT}RXK_%Wl&nYJh`bc3N3TZEhJEY6nkeli>Dga}&whU4Inc>;vg>h#rq^!P zv2KxA*OA*TYX$hK0ZBk?Jq7t=Zk1T!mbE)gE^CK0 zzdpUD`e-M^*R4=lG52~0sY-`cDXaNT9$&+q#Mh(lj@C#ge=WLp7mwntTb=yw2*ZJC zQsu8F%wk_C7r;*;DxoR_jy3U>>%ZOya@8lhi)a9F&-1^;B|fKzf~#^^i)hT(q~qyB zstG|U=u@c&`FU?p6AHAG$l>%^XJHO?m=C6OnaHTbAv?pj^mB(dHJY@V69^tKw41%` zH0nKtdxJ-Q!B9{+`&s#-2*kxHV9lkNn+sJ20^b&TZef9S0e3OXa~m-Tp@(HG1*>yK z1z8TXxPk*962r1Oy<5OvW4VQ;~7uF;7OaZc$qdh*QJ`0Pye;+z&z5H2L(#LSHG7yhEK+x-UP z*j|IcF3W`I0ln5bB15CtzQ|f8Lz`SC9P);;7r46N3Uy=bPuC;htd|!S9M`YT)iU+x zLSs}=3jq(>1swNqc(uhttpU^8&q_0|F*Qwp@@OrzoG5B7%#NQsQkXqGQ#gFQF*__{ z{M`9dI1#&IZb2+8pDX*=CTYSOZ6 zg2hsuE^lJCp&JxM6(|53IpYz(%b0j}yl^2jNy(iKajy+uoY3VTbsNRu(5D6RQ1xIM z7kB_)Rl94VoBb8B*9FobVUD*_Uawxij`L+aD(BvXrQM5Ns9qdCBAT==H;zhYC+$)O z1Cp+op4M-H8kzeuh*wN$D#iU-rh1NEIrIRGFyL4M$vt6M3$I$Z*3>C4W*9>@-!3&| zT&icg5741zv!cZx!CNt@8ZL?fo;5pO8~`45%1y`6h_(=*#S}9H=_q7pF()dPC8b>_ z1Q|)ti}fNE9YsCVonSe_>_5Y|6L7pl1zEdZ40#Eyq$pL=Z8#{=C`nHaZ&O?UQ%ptm ze)sRtA!+6QmvsIsI%POs)P*)mK+P6&T_hUW0mU?gO(lBcv}fzJ%_w7`9Z7dJ*^h%q zK>n(I1oY|n9*^$QK3OmgviQnEvC=&8>jNN`^H8_6Ubn3H>()okPm*;{ zhC}+pY$k`8%#%4YdX}>;D%688f20k$9U#m!ABDq{H8s+7F}%fV7Tg52=E6LF z@b}a3Pp&}^8rs+Cb+889StQ2kaM2Zm`Ua(*O_(8>ddZ6ub-F)>aQ8>)h=@cfkcp55 zXL5Psg$t{fDKA{)`GZS~#Xg>40Reom?$|g!vus~NkiN!Y*aOdOoSoCnrHQ{k&=*KRf<*5g!KToCl9>w3{W9Nvh0cEq z$IA*(NFBVaQnsWV$>m{%4IRx*fOPb);zevxKxNfI#+ii%;1YG*>0lbAo!O1CnyZKofG3fi$4pia7#MT#eo!ov0lYT-~5 zkFgvOe^5-3jlc;Ii#h1hMxeGxttSxQI2IMNV@y@srhN8BhM-zcRg`t6wS+AYFMk~( zoEK;?1gi$OnUpBYGRZ+J!!Q9!7(*x;S*1;S&qt^ML4aA?g#*;o4Jv_n z7~!NKu!` z5d~C13&>G}y1xOTQ7C|vO0RmwA9ewBzaI_U`H+O&0N@4NBt5_c8(32kMTf2PFhu{e zL?z4%qsjjl>!AO-c3ZOI5Ci#wVO6v=g=<1o4EeOzur_ls=t{MH}SEfZ`#G!Uy?!UJS#o zR6o*YE-Ah;S;{yc107p0&f`5^LOMpR`A;Cw{fBh8ti!Hjxgw0Yra5o331#5^8sq=> zCXxG-eCwf2(rC9(CTpZjNJ;1KAxTFjVb-Fy1|Mp2D1wfJo}ybo5X!&o2fv5G8t6Q5qy0k}mZF}7+P@8vd+O?v?)f8B^F6HjVCaI%v;xW! z!$RD!p=89DlHc2f7b%(N-#{~x_pM78x>1+T?%nhpVGbqu!1N!2YT&4f)gC&dwJgJt zwycZ$PgqE})L-4ARF?rCpfLBJ;-%eZiox)IiroLfR=E>EuKT(B$~VEx-m(zkCWF31 zCz8#rO`>>l>hh^!+++m3^rf;b(3Xq=7Eo{`YX#6_0xJmg|0p9!;2Fmw=PrWX0b~{2 zAAqb}%GptnmE14j1S4E%LW3M7-!jIX0naHD@L|qICgR`4yZei9ycn#!1zQ65ml!|* z#4*-Jqb1urh#-#9dw~wc6iQ&xGm$ciUdL`N%eJxF`>j3EK+@`myEW!N}pn%3sfK7ZrObx)WDrjY}+i?iU zvXf^bq}LH6^MR6^ zdPWX0tdPd^mnghxZG>R80_`|AclUjBJgzDHL%Si$S3pOSFZ79ty@jSjaWFTj*eq(9 z0dEh8L-ZhVCe&XQ%yL{PbX7yCr*b`{zzgcQrzbv*(jfK!vM4OBKOBE|(E%gFUFM!yh? zxR2qry$9v{WOcZwjG$Q1<^O`H?wfRoGlx@(qjp2Y+CxovLiun+x1kDh@N}S{*kNQ` zLC_vkx~c=9e-t~5bWpHbk=9}It(Qphd4%G?$sI^Eqc{Up!kHjcBdiu}O|L#u5Jn~iQ-lN(W8T(mU>!eYHxtF^Eh-6QpR7R9>1 ziDpHt>Cx|yze08l{Tj0TM0N~1Sk4E>dD2Y6 z5-RjsbX(*MrOOgS7I~|DD*$SuPJR=So?UIq>me-mGZW*$T1~Ka?L*o|YTd}~x)w22 zQ$d4U9sB_D5J9fwNjtisbw!t9*fVDRIij!=7iFoQ$Y+d3iobPJmU=0IB$7RTR%9qh zL-C0|n_x(bo*2T_2WktUNkNA}fg$t;1rC|RLTR$+i`Mb83alwD(7GG$|AzM-IP?10 zJtfR6==EI0cng5XGrNG0_5;9!8k(?+lg|RNXe+-umO!}rirbcifsjQQ^cW-zW+KrK z@%H%{eF&hp6Gp^CL+gfK5cVoTNn!~RNI@I{jDOXCe;x8M*zbVeS|aEr5d^7I>&MU( z=_R8p#+G{tAy0})M}B)jBm-zINr4>$AOi_?$^wRTe7#OT)&}rkXO82Mt#~(htdo|H zwkJYhp$v=M04{Wdvtse23o>+@FR_t5kZ~LRdT=b`y=8!6FcDZ=(6&t&-USr|9v{{Z z<3nLE4F&p33myO|8s7=-Z5PdmZ)o3$@(GQ(j&fGF&>wZ>zj4^Fa*@#t>9m*tSDJb#$oz;Vha_Jz*G1QBRw1H!Eh-GOv6QJO<|5gXUkw}rf<2J=0l zjuva*7aCnd-s*+KoGbK6=Ykv@>;fV7I;*w=Pm>siHtJr0C9Z~?4s`W}1y)H!HkB!WNcbk58Oc`j7vL z-&ys+^J2vq!ZxGcylr47O4%i0#x{S_wEpJ6>MxW8y5ejAEB3-T9)U?}fC{@uI@$F4 z?;=?BdN8g#OVX{dmEyW39BNbI`oDo1xc4G@NCR=Rcop`$`Qy8fxN`X5xpY`(jn2o# z?D3?kOk!)L`kvV~0CR^p)yJAC8UNp8wZ4d)+j|V$^+wsin(=Ey`mjU36DTXp0EkUn zv0D6ctO@%ZwFKNa!T=@EY24LHzY(qP)v>Aiey<;Uw3CoLvPe0K7DC9mCxSHhw)((s z;VFIWAlPEqUvo)aPeMgmFpLPb{~3IGHId27a{p&KJL&vAI=@JVB(d2yeV!icaJ=+V z16Nk~Iu~y<;LCJ+x^Iu}8^IKig8SY04&m!|q`>CMf~6i9NXd$U6zij0l0Gz#;7N@!BO z$|!%8&U1{C1bPJ%NGujAZIU9xUZGQ>!>;t=Q{WZ3zs+y7G@>~7#ED{iORNgHU*P98 zI$xr5g$@S@iE#uQ7ndlr0Gzl=CE>>zHRxY~pX{z+=&^Us+=Xgh+v%iXAAUwV8a2~$i=%OT!>K@YBVMWhv< z-=ojJp+gkr{%bn_JDoqE^M`c)h)w`*@s7O1|8m*$(mN6Je0kY(-M6OG5AxDwm^ zHyumItb`Sf|0My>0w`wV)?ZkO>__Q4)4K;_`|jK~klbnXFyeo1AyyKxl8BW|SRW;m z*0-`L>q9GTeSphz-p^*OKTq~$|1A00PnRZ(G=t;${rMf%Hj@&y`q0$M(&bqw&q8@w zDKGoJ<)CdlObV#me83tGqK3UG@+QSId!km7&yaow&^wUUBuy?XH?MocnaKdKAX_+00 zJV_W9PvH&ceqfL}?qqTKSD*QYF>YS|6))zDrF^;A036_HrwPr=@-Jhq&64DnPoVHYf1%*_=7^%c^^8B%JJP@<>f{y8B}h zs@1q4pahQ4W|h{#h1uEDn$gW_;0t3Q6(^$>lGI9BnK)o56_U8e7R?c<^&)jjAv~v2 zEr$=0#^uHeWTfg#mc3G536BNKLFUkYR7MlXiD2THvtv>Rroy{a#MD$aQp(DK&v#Wr zYj_j0$N`EF>^5jRb^}7d1@5k>Km~JMSZG`ozNZulT86;LI&}}P+8KIz-&epw)*G)c z)aNiOB=y)p00HzB8O9}zEH!f}0Z0XCM2VCp7O>Ld?w=u^TF?HRZ|}pwPV@lZHwg+M zUBS03-aM<3@5Q1&674 zm}M8jQ4|O{kc1RJ%a$pP<10~`X$=tTK3kL(=%r8MSdQ$8gHnv*H&lmk%glGCOS-9z-F0=pN((uHfq)B@}! zu}6h?xtPYKM)D?z&KwiJNRH zwfTU?Cc5{a7T--J{VtI%G56pA6~L9kH)Ub`2ScoIA%nV}i}9c;j345gQkbmB&8Q

    h4dZoC>F?+B?E_&9Jlb2gN*EjS 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/namedict.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/namedict.cpython-310.pyc deleted file mode 100644 index f206b395573ddcc5462a0930b93e1e61edde6e8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3012 zcmZ`*TW=dh6rPz~I~&Kjr!*lH7Kuw8rA9o!11hMfX%SLuP}3r01#LDvlX&B`*PU6X zBywIzQQ!CtDdHvK2k>9^g$JJc+&3gH-`TYtJ56ovnfsjEcjlaUdb-5$Tl(`_<8+p> zzi2S}voW}Z&#Z$;R%en+5%HF&3r>A2vg-C%Oxm*Wl*xh;Csw^6txZ-b9xZOvHr=-0 zQmzbxB#hg>K74^|ScRuE_q&O|6RG=trxUjKY5~oU{;dAMG|*A3&cR$rUbps`6utI-6VgFDAtz-Cts|#o8SSK;mNRHea#qfvos#o%0c}|>$|bbZ z&zQ~XGZ6Yp>eL|c2IM{Z150Q(UYo^G}75&*9#NXGW7}1GfAvfz(>qY z)-K`$1ep00Bw;7)ls{*jCE|qjm}f~2YG<_2W2ePL^mxd6;y3;af6f602K$McrfVw` zX~A?mN~ezJh3zo$ywoPO(m8Kn-@X`{5T*+tX|dapexe}1ZB(?I+P>a1X|ef)+B2R` zdR`Fu#(3Tt`+MW|XIqbq(q^l(7q`^bhBD10?rh!LxO3n~Td>H%*1d3N%RuWJ9Y1LL zd&+FVZ6A@_NS12nP)~sG4Sa^8pu`eF`{pVNHY^ekFH^(vW7kXc4nZS4+59?y)K?dTitMP@uJwIbC%H_VyPQ{a(WaIv04FDLWp z)fYT3x0*NfGr7-{L1y?IpW!9^?SGF}M>M*4;`O?bS)dKHTY(;DymrR*B;x%IPx~&SPD(pHi_R3RB8bQsZ9&1O`@fx@BFB%?r0tB zOuKY-1f>^^Rk1Q}=qnI2EdXm>b%`O&z!0~v%{U-4KvxO=7&FIk+n5W;6ciSjIUb@z zE;!}6!W4HI)GR=45i2mxGC|GG`U0~bNEphq=+p-LVe%NG(?U;Blsm?3@akF!6)|oT>+0%#IbNaQC1NLfC%5^LWER(Q{n;%BkKp7Ue7 z2V@;Ey+&=%USYdJATMmP#|u41`}d10?6{EkdWBtqJYf01!;^Qzw!9>3At$a;^sTue z5+o(HVR_Kcpp-=)zLM=ilkJY;HlFe%uPk1<0f{<9X6&a@y2y94R3zh;kKOTZpLx}F zYjL7*rJuNKBU?zUAnHnG@+^z&o#j=!Yan+*32H>xe109gwztPhgY9if>?#))itoZC zBj+Bdq^sK~DRAyO{JZXE4@zZw8+s_z8Ecq?K)L4qQ{Aoe^FtlDJ$h}468c14Dtxj@SDdv$!^JyWkG3*dVs3^kO^E@|0TPX2r3xv)ay3S!XcZy}fFqg{eoV|ETPz|Wy=vu*8dKh(4_zX diff --git a/venv/Lib/site-packages/dns/__pycache__/nameserver.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/nameserver.cpython-310.pyc deleted file mode 100644 index 22ef5fa771190111ff09325ae6a4e4e4bafca074..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9267 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/node.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/node.cpython-310.pyc deleted file mode 100644 index 039a86b62ce542ea59546fd85aa96dd786db08d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11615 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/opcode.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/opcode.cpython-310.pyc deleted file mode 100644 index 9614e4a4960bb9aa0787e66557d9080e8c73ffa8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2481 zcmb_ePjBNy6!+MU<2XtGq-l2-v8?$|s%{WBgiyDo4XDy8g|<0hMRMHCv~?QWVa6#X z+FSc2xWNI5@(K7XzHs2w^WHe|-q=agO~VOCex7;rX6F6g`^}p~<+7!~Q~m4d*&opQ z8#~jF4xKG{#h)Ok;wY3*wND&Xel|mn#)(b~)VkK4A}z8~rYX@fXv%bf8K5bF%_3a_%|fQJK(kCMpjpgjErDi*Rzb7O zj9$g5fLw7_Kvtb9$W><*D?SIo z6o&v_!0BjIb#$sZIjTDb%{h5yQiJBNl`G;Dpl#BEY+KZVy^4vE?!yTzb1Q|4Eez#t z4n!Aq;|JUL?!YV1gc4XpZQd?I`$oATiPr54ZbDCrf4YC z3}WCIr@W-Ovk|>n4`#1`!?hv0ZZAABJ8(8_9jwY8-r@7<<|G@M!y}b(k2< z{iD6FLErjzcl)T36y^2-i_ap;OXvm0`!39P&T|aUV|Yasgb9%v|5Vi?sP0P4|`?a)SMrm3-gVQ28`&6>_}CSOKT0g>cgmquOJeb7r>?m4`Y zL#AR9xj~}G>@rRa&f*~tXEKV6N8-K4A`mOTkXOpDNIx?AeJ2Vp7>{k7Z~I{!*2r->^Nq(-AT6bT;hxjL8X*j?6YSJ@9nYayJ=SzOwtph0&qg9! zLLw08MW+M)bUJnEMNO6APYNeI3S4xlM)+F*XDUj_LH-oPXYfk8TbAr6xs$$kD(1#T z<}OxV!J*tzsQLm&AC6v2lBu%76(0N6wZjk3%Ip7^{i*X|OQ&(}o9g zP~Iw+P&^O^phH655dI84Z-7iJ83noGCJYNST{8Lm@JVt|9)@fNE1Dn&1fBv!x(P_P z@N{dVpT{hi@c*|5kt4mvDV+r} z&0jgX@&B`beAe!hKMy$3H~t|)nA{ay68~e+wNU>K3hd3GpKt)H2=e`k#H6R5$f|*i^PI#!bS5U51xUwH)Snz^P104eoIgUB-$QX9R8sJTI~-6i zX2&opQ@dbtyiRJ5_!IazCe|7j4gu{62Ly%$Uy>k-B8UeG5*&b-0U@?XHF~;gfNu13 z4{p_9Fyk7T;!svzG$lXsk`)i)#Amr1<(zDsoRh>!l*fs4PWJemP3)X??VdQh_HM$g zH<3fhlt_`-@B436b#>1G1Su(2Y!A@4s&3u7@B6>+f4f6Ng#`Y_fBTjT|LK2EBz}hv z@xMFq@ECs1zs@BRR-&4)l9tg&YTF>4Frwn*Hk5cde;#;vW0+Zv_&G~%{d+Yz@t zihC4ypJ_c-eazZn?L^BDS-Y&=xIS*}v2MZjuyw0-8?HyJigi1#N3A=oJ8?ahzsvgb z)<>+5zLKmyVf_W`W7gfcd(xV)N3Fd(6V^S}-Z|6SXYGH*tR6?Xlh(Z`_g*{IdJ46B z+A^&B@Jm_;@XxUBx9&oSAKG}re!BI{T-ka6HJfUkv>voiSr6Hx_Orn$NqgElh~K9WH;lMPkoMDfel$q)8GDO8ZJ(Mm@Gh*`WBBfn{j_zD&VTL>>v8Mw zE9vTtbp$bITF+TW?X!4$b}nNbvz|cxKO4Py68RtJTg#ZsSx;F{%c}LPbsGKuIcwUQ!S#i_Vf`iRj6G~U zhqg+Oq2_GwS;T!7IkDgFvB&Jw_OpziD_GB4Rpj&{YHCQGjr`~2dH{L-Wy$Mo(4XP= zFQ6vu>lYC}f>J);sv$hrsxwFA|9Qlp#g$`G!|xn^b;L=1r2OHz9oDSXK)JIh)xuBr z7yAsgu)fyUW7iw+upVJKXM%dNyk1Y))*Q-d43s0SwSM6PmvcTS<3e9qV?kd}OP}tt znpO*CTGmCYjZv|!d8>o#+;vAM?AiFpfLzYANASa_SYMa%2vgte7%*2o7xb8y ztxJ|d&KE4la#62lU*8zkU%9DX30GU#>tTU->m zT5YVU73(LkYUWXc-m2l)aNYdk2d>9Mtq#iZP#$u}-R31rU(D^YR;@3fp51}6xn>P( z{R5T#lPHnUVqu__;o1%B5%$q8>m}=pDEkax;mg(Hk7nRI$El{S5l%Gf^wh0{c?So6Abw!~Tgw6xJ)O<7VaktbIwK^tknN*3TpF zRm+%8Ok7>rI#X|7thn7uy>et~y5iXCvaKfHAQ3b*k?~W9I?KL!q}g!&+{p#E+3nQZ zetKqcp>6x=GaWqpW~1)7jU>Ma{tR4G_#MX2*@wUb?X;Ls87nc3dpEJ3xSH6JSWS8u zmy1a??j~DCEA=v-Q72>SKj0Jjn=pOTZO+?%%IY|N-oDbXr4D{}2C>~mcf#-s_LYUE zs)uO?wpyNCSoRAwWzW}}oo46!0c7cv5ag0(vXso>pP5vn zh-k3I;a^|tZ$&Ix8MWR`xXJb8RrJDk#IIotUQbS;6{-1VN9B=t!cb*g)DQzULI)$b z^Y_$xZLQ69Rn5K7bZT|iwdWVygGk|I5U^Hb=v3T-F6~}u;HK}7L&HDkK?HUJ#B8E! zd^s^EMC~iNYAT+?BkK(~itR>j$WWqDNM9uJ$2vc4Pq3M|j)0`P<3`sHP($3<7t^8cAhHiIjHNRME zcN_I~ZK11NKaT-%x^2u-f2=m!?YfSu>I=2HWg*`2v$eVUe6zhgk@ii;ZqNC-D0v~4 z%jm{0Gy22VlPIFrXxAO5R_k@X+K$Q{$Il_hP)KIvUm>}&W1uG{!)i}8I2z#}2aw|{ zYhnzm<$Pi_<0ib+TJi;BHM^SQ8dy(x$*UMTFSBm)E}7`u?Il|1oyDZ8NGzTtevg~+ za%;&|^kFNzn)gg~ujG*P%&SQ}CtCSd0sWl!z?;09S}k~m_2N~O>1B>2UVLJ;7^E&D zb;&bXf^!mIl`P|8N>%0U5XYufnlrr8RbzFiV_1pRA-C+6+~L-UH?)>oExV&u3iU8n zhgZhkF|QnaSM&`1l{dVWN+#SbUU@Bf7Ly{0aW)g~`0|%DUH^RI(xXcWcWZ0g%gG57 zD?wGzNq(-~oU^%@72(Qx{P_3S#CE@2Yjo!q7G1l>*N)<7_-3x|Np9!wT>63?_u1(LJK6>aGS%a9zjc%u71A-3M4tJG3z1(R`yUMQ5`}w00 zM9W=p-Gv5TS4)R=@}o+1)x?O}!&;aZx{m9cTmb?f{2@J=!}gYS@wKkNM@Q}DN6DH7 zBNaYm>m6qapb$4f9~t#IR(nx3Y^)VDqdFGAk{FyBgh9oiF*Ucba0>Z4M-Z5)5&&W; zSxAz$F=}t6*PF$$F7c_W%7@rL`ZA)0-VyAf} z7}q7Fa|p}K)XJULt6(g>hGAI(FU}?auR^Uh-?bLoyf4*imlo@7{YD^)`ZO!@I0Ant zfI1Dk-3}p-Ab{JMgz!UcMernk8Ve;#Nh4RdX52k?P2Ow(^dU@kI2%Gh4@wAh5oj&b zO8tT+L*+ z0MLiHZ`1?q;1#7O+KJVymu)524Zx$6n_5e>OfTI`c$vSJ{As{EHx0~?1g0?82!ArQ zEV0Au#*_eqiJV^ohMo+;y41waoeq$K+J;hf*Rr?#G_XduT^*?bLJ(ioW;Mc^$jO}8 ztVOC z7#wA=AAz4gbgXt}YWmdC!@AbT_@;;WdxQT3UU>KggKwBzM`m)z+lp^C3_d6AV@ys$ zAU^nDNK#e`SlrYfhO-38Wb8QBQqf0oBlB5(26q!_-C++fmXw2DNDuL@S6%5H&gq}U z?@d`a$(3CLJrb@nfDlfqfnJdn(aW*d>1^iD;OFR>R!VMYGhaN$6rV-VYjZUPCd05& zU@}s+32{pr&m!Qm((;_avk1DZEW}F`Oy#URQs?oMvmwZ`imxQrk`ULG&~HP2%5mB< z88_5`oyQuyNjkAt1Cq5XTk+N8*?Px4ZP%>`@=v{<8tj2h8t;#8_;8)Y=&k@6I*q66 z)nrjbha2{uqnxPyI_wJHy}%g7+=6%rd8^PaN(79$#^% zu3uK6m+F_JGM>AcGKPXOrUe(@polz*(1~7;N;u0BIBwxz3OAg&C-HL#(OigK*ODMm zjH#7!r&~d370{@Jj1x&kwqPRVry6ZXoxr_%hCy!(xg`8;4Iq3FEtWl3Uu?T13D_Hd z1MdXA-agWXf9zUM~snF8UKt_IVo?iJH~JFlin-`Tp?4L@<+~ez^Q=bv8`#L zFIGN%NZ3nZt11B93*C-mR~kT(l{wX&uhcu0#ps(#K%rE+s=`j5oO*o_N`TIJhI%hyX$!I_xbW113tZPz0y#n7mQDZ$a%VQHzFr0 zOLYg8k@9V;GP~$XeMn7Ssc6EZ(v&I}D)_5kt~cBD*|vS7D$b%(|A@6a$AC{aSH)*n zrlKl7d*=9I*6`Wu)v(^|URrE6K5QLXqkqQgonyeKzBSDCo5Jrfe$HJ8w9o+}2Q7*y zktv_UYz3i#xb1SUiMM2&5BF1@?ow8HsZ*XZwa5J4u26h zUQ&&K<%0;IWvm%$#7nHFt^&4PG}Q=Kj%%)`K@vfE1U4^N?{)35~qXmFAxM+G^Ep9f=&#oYxnF?>V=wCNzmFC2aD z=+sON?9UOusPE67K0b4leE9jM*5f@7No}zo0P5&8v?f@bhHpYYT3-qc}_aBG_iPens#Q)uphTV2*0Fd?eckz)>?1nj(+?E`{_#4+Mh9XtHfx~2XNLLU!c!mSjE>|QJ>eHE;;D`n zmyR~icOY@7^)T;X7mh>5;WjRy17qKr7%Yc^6*EOSXc?Wj4L?4CmB%xd(iic1W&<>g zrq{o~Yd|XqwpKGMg>X_q6qWW66HKYp@-97{Al%yVazZP80SWI5(i=#h_0nq6LkOYO ze)O);X&uAMBBzvk665ydN>0+JJqXTL4dh+KbWJTkq4UN!21fytHKV2_B}8Oi65^{g zCOjeU=Yv?oO9iobhcw09FR-Rxn_XELjp*PB#FQmI~Re8I$$EBHKOiDFADYN7oMxP7j0P_)k3|qtc6^2 z>K>#3OieFcK=m}&_9;a9#aPkRt@0Mr$8l@3b~sgJ_Nbpk>T1fV&kfFu?eQ5=L(?EI zp(F`53JK>Cd}XFN83<)X!h=bHDPrmGXd9fhUbuQ)dCQy);A2 z19N$QFvrrwy~)JO09zQ-W01*jx4N|pXqj_?a=vb-C&$xTk{V@ll;uEX9m?P4>cor7 z=wREOg^2DV@ufN2>{xzriE?T!r_-aBZnV1&zSaxXbeAFa4u;2Rhb)5nGFqz^8T5m9 zwGVNRvAZj{p;(P*jOfjj4u&}5-Asl9fbM=zQj4r)Wouk~G8qa^{EV{QMb+6rMv;^f zKzJ)|0`iG=DwN{@4F+-?ynzJ&NhFy_Day&UgorXA2z75^giPH2HuzfrV3slI&I8zk zEfBf>4BN!P&SfZA0dxBmJT&m@`$MY4WB7@Nsh|&fUxEx;Va)(oD1E>HYjSlvgp{>X9_|;A31vL(3ul6 zm8E7IJfP4lLT}GCmE%TP2*@T|&<4d*`P}{cDhDPH?5jNRBGT4f$p}ljM~h2L4+p%# zE`KA1U?bzFYKZo;K|QJ&R<(A(H=aBY+~1G;`-A%jaQ{GT+DPXM3Hw##GRuA*!ws1} zGehXD|AAlP`{qADf@3R%dof@33+Lu1FR3-W(Nx!iyyJXTuORS8x*fZwR1K3D7tDWu zIKVGZ&@|gz2w4Xz8uYO`#1A0N2Clk|w;6PPb8cBx_)sGAQVWKo!Rm&8ci@I3piIYq zk6r>4NRr6l>RwB~kXjvC9bFysKutqo@=$=GsZx2!8v!kyzG$eAKw&`)YVa zaC&u12j7s^#`^~&3>|+DqHA?aGqF1E6_Ga>4maD%t>?Whz$sh3t*wH@o^XqhAOV{M zB_keXe~#~0iwwPSEB8nOcTlsSh7I09g){69waOO_rz>~EsKwXa5$EecSwHQLLfMjB z9byjr&iTSqka&AT>tm8<8F*@&yJdac-Rf;y-*y#}D%7gzZU?PW^tM2dDm?^@mGw$q z!OFi{1SK-!Ty=LKmz?^ByVJ|LyIQ-~4CfnYL4hp*Z?Xrx$ab1-HIu75q-M9Ep2Ks- z<;3bvdA>Dz-sO!+5B$1itnRjkR`+yrh#A_MSlx|l8P`21>EF4xtyer4k*(g++3Mcz z?e=zhyHKY+sOOLe1Fu(etGBWyLHw=O$gAe+E#57!9bCVU^rF-MhT) zYryu_=r3qEpKE;tZQbE*M|;Puu~*Zpw{>>7A6@^LxBY5z{cejRwcXpkK7m%D4z0bC z+OWpGN;8Qsw(^U!kQ17~3u`H;-tq?$Ur9O-ECGw~-}Cr+x3%uEwq0cW5xL)f(L}9I zyG5B(I~a$#wG-EUoLRwKfKeP{Ak4lOzxy~6)-IHHJ7N#4-+wjX-ClbDJ^r9~`_&}! z?zj(O1a1eY+FdU}Yj|29vjCb%cG8`7p_T@{P@e-+1z04!S*1=jR{?S%A43_7lpq280(R)^ zx@~CV_~d{nov$C1EC?=~gZJM1$njJA1H$RigO5;f^ys~hQ04Pz*o445AZWx~yIXh9 zouicL+_@=0uc%3j^RwtuAOgomMJ$I>9_A%CpH(35+owP0 z#~6>WI;>()mu3ew(cQpU7RbKum4ukd$_%+V4)mVU_Yx-SD1TRmDpbkA!u2Z4*GSlVS*Z$ z1mVWp7*522(xfW)h1m}xn4q~(<+snB3p#&BEy_4TMO?A#KpC|Gp?<_o(;5pBGXbS1Q33AO~~7 zoi!lBCy}Rbk+JlW9({}yO{dt)7A9&8YK1HI@F9q2J67BNRHZqGQjXQzP6%^45GqS% z@!Z3_Bt1YjYsr!5U@}JxBY+e7lw-)jsrOZNuGzNHK*`u@Vrr5%sp!=w6l_4;3YQu$ zIqa~IBoDf5Q^sL42pWFJDskEZ@JS_lL&7x^@=p#{D6xd2*8#=r5j#v=)v=fKV6uOg znrLY~oJ5izhfRqO6|q8l!^$d-1ea`YRlhsG^XflQxgak&Ne?=P$UG z3-!x3AV0c2EJ#*}H0((CNoX-NhC<&1uE82=KbXe-_WAQ%(GXqE3lI(P-9lXfVG?6^ zJMCrUEsN5I{Gj1-T5vFh{b)C5RUM;+YHMH-01_<{;D8K(*M6CS?n=#VPDU!`%H7OA zX#B*!%4`>%c}Uty>BJ%Yp$A}w0-P645U_;+F#u`dq==K}v56s|V3KuzPIFR3XkdJ~ zYKUO;w3D`B9EH`=vm?k?6FKM(ER9WRlS!%Pv8ffYl_AD|J9%&=AEN)ytr#yJTp5FY zE}U1vw5pbzPP50XgSZ9@p?(3u%0viWd&5F82$?=~ZyZSbnR|bTTn)!L)7;Sd}m2HV=97tk6r2{MF z@TqNg&bt?2ADO)XnIO8;&jzoAH=|V~zG5dkZ-R?Ud|J3~l=atG46PRYjI`NN)V03x zFB#l}lyC3h5`YQ}h)AzB=mFeC2Xo)DD=Q;~)1mTiwredPth|mYT(p-JM%XU~dMNPp z4fU5;&|gL{@vw+rffXCo299H!* zzZdS4Y^wST41NxQpW{-6UhslQ4AcbUGU!aJJMU*27rISaI*}*W_EDJ{N9Y03a4DOK zWyr2nGa50&p0rzA0^C$T&m#UjQxv3|uehvYu>zQ%Ni z7;w4hnJcSD1UePQ{S^k3G>e9&S^$6vM1g(^&6VjTa}D)VpFld_l-hG5`o;x_E-u_J z>qSg)e4{b1eu=MWw<(&~YTD%oJ~S)?!Xp_ihYQd7clgA3qL3_H8&4G=+b<-?lg3LX zjAW>rqhPEoHfS{5EFjLf2BDZ(r*uFs+ZlGNAJ@cBG>AlUpGm@i$u8x8JA(?r{czm}c`V>`EGp6u6jGr@!Adu6+!j!B$EIv!HGKKyI%yAOp zg>f&XZ80xFI35_!O(gx?)An*`F(-iHH<6W}(ICc8!)6-f=D;A7YI6YcHJ#>@kjaRK zg>9thkv(l1>bIDWxnM*4_v^TAu&&`>pJo$Bm9YS70(*Dt z^FV+=d17+%KO!SPv0@yosQ(GKkms{+)K4%v1x7`ElaK$L!2t$@b&wFtX!wj^|Ed2C z0d%GUCHypcwYy<)4AsCQH!jw6qQ^Nf6@0~|5dIsHK{7DCwGrkv!~CB5Z6tc*3bSIGSu(ftTss`~gq&ee|qiyjRsegbcf0!1@&*Fn;>KzD! zl#miMSQe88zo^Ze#bUV%2`(4=1AaDObhU9cCykz?oEqxa7?7k;Jsg#quU}FBigAL2 zw#IOfOtdmzJ;)#uDaR0zARVbY5m7Y{%u)kc00RK72cXBG>O{}1ItU-^BXE&I+YDf> zKHMkzhiUuYrx%I(0!aQmpsYCb`tQ!$^c;M?$Ad z$%*93pFIs)j|4JkjQV--5!!Z&Bz-{W3x#~BGNZS_RH6+tJz~DzB!3?;8ePchMHL)Q zLfY21!JSx=(d@FYBfU*06^gnv8II`*4Bfa)a>O5gJWzEVKPl)#%o(5udIZh&a~SxV z(_FDPwTsBt7Oe%)CymRmgt)^1O!k;-I;(q(DFjZ zhbJ7U=> zintrp%f5xI4+QA%R>y70GV*ciGrB8!_PjW6%vA=w80qXBnTnS zN<~AS-lU{GTE~_BKz_0_0M-2*$C5zi7dhcsM0pztAna60s_)~G@Fk&MV$j1@Tcks% z^oJIrLkR{D%1|IK7JAF^(=td6nkR*SR93PGSrY#iH!$TZ<~2o2dNc(pytrC&L6f(z zs|w2ji@_PcWVk7s0rWBy^Yk6-lxqHT7A@~f`D-@3RMB{-vB;Hg{X?)nq)KIbOM9Va3q6uj#%DJ*Q0vt zekRq4JfwPhKsd`$@=do~y$i%Y^TxGnAXw5pnj*%{zJ~-;69r*y#8g&Q5EC*BPx+yUCS~FqnHMCj= zTLD8)*+W0PI^q@79#B%I2eYfy(M}dSNr&7_D~p|^DF}^5Upufm=E5)ulvmjsS%V?7 zo5vIG#W*Sf1Fb}>=;a`c0yDW*1huvWCST*;@Q#GHrB?Ea&NHaX5Y4`vXWTM`IuI5a zpz=bY(sTksrRU?~qP#(4tqG(4E_fwPFb8un*aUSGhCCprqGfZVC8J@AOx=*1h}a<* z00*B!6oS=7y~X>Phk$*+XW_aaAuUxOz(oOz5afPc-lTIARy9&oP=CN@04Q43Xu=?l zjsw7QW3!q8{ixX047LH?g!~6!)k8l#vl`uZ06p5YCS(gYmPzpRqcf|KY7De8GOPLT zmhk%{MQ`ohAk3HyWg4KT22IrTt2kkc3DjFXH(WFIK#D?CsrQ?b@t@L$5}|oA%=Kc) zdZtMr6C({d&|)Vva_1TgZ&8nf_M-)^2BL45TSfRkfe|i@Dc>Y zx=7eJ7o=|{Lw|``2x&lNye0^QdJw8Wv`M19B{AU_X0b^RG7rFBO<4S|{AQ7XNX%0t zBKpPV(DGUfA5DQaV6M4O&_npE}8R?8<<@bzj*fdl? z?ojwc9?Uu9=inbe?)r!W5(W`*a1IaLrWQ&TwYErvCUkvMTq{ur1?Pk!5r*(Xq?60{ z29jX7m(UVP`3`y%@fMpRsF844}Xug`{3YlKvrL{g8n85o3H!XzQN&BZ2Xy zzkbXOX@3Y9Kek<822Z#6hb!v&Ahx>w!Xw?l4{fX)f}oIK)=GyDijHN03vAHvA7X}( zd)0(`M8(EY?IswRz#^U`!p73`H;s`6`I64OF*eqjYK$DIGYG4KrpWufA#A?sE(#R0 z5M^DTb|GNYrQC?-k9WoU_m)&Q>M>f*Zce|%>L;q=pqg3)5SUQ!i@Hv7C49dwF%xxN zuTcRn_5+hQl|eC$)CQ^^$iHaa))UQO*dV2ou_Ro&c@Yj-BFXgzBAg!CbN6-V9!&Gb z!bG473Iyeig}8`DrZ&1!j9~+jAv=s-Eog}z$dZn6Z#Zd>NJXTezlFsN^B;i%L#;258blQaGI=C=!F3Pv{mGv6u|jc=9r-3AgTMIF(cv3y@Zz^*m0Zf%95T$Ho6iP&oFHi>d@oO~|`0`#C%u6`QJWVo0=({S@x}5x5VE z{4hy^%ZwfkqP3qSiNAt)%vqAee!9VCYI<5o>30x2IOXzmP$sS+ev4D>RwOYql&xul zE!snjftKb!*e$+g78Q3|Uw<-D$j8Y5}RN68E#&rf=GF(l@CJz*m zE$HQ!?+zvi_Txtrgp()L$}B$|yvxSkaq>tB4t6L`V;3DX`>B<$N{?uYC{p9oK!L=i z%qxvq1=9St8FF+QM6WsZOEf4hgXdeC~)M|DDOD7!5FGPU@X}V7)LECZuR$* z?ZGiD$QaVqhW(#8h})3fOp6g@a#w8lM&41|Hyb=!aURCcVQu=1DazPq4G4hk>lo5b z0dh?Y>Uze4!Q55oXkpcuaKS=<$c z3o!b@ZhV+X!V9gJm)U66>H6mS76cz?4*uBAoV|ad^6n|)LOK+>Xo^Gx=-<4``$w&h zjuttXv>T{+`%IgN!a_Y-sG*l;g>uj6WzX12mi*hs?N5pUFYLdG$7##W-OkuR(xD&n z%~XN#0Vr}iF7(ZGeSW$vwtw4@pSBVgX`RUJ20%fi)&n%y1FYlhK%S-BVFL)^U0j)$ zc_)`u6+#BUjOdSeij=G1s&lxB=u}$llTIztZr)2#+=d^o=3MG>Lfrw(6%Z8oCPOC* z_~q$YO1?~~NwRZpar)@= zG#rkdJ$dHDk;hNK2Xi%d^w0^qA$wj>x?ceGNi+rz$&sA(M2)gmZadmiBB#b&x(27;gi>eJg==sDs_B>#G_L4`#1o3nVK3)Q zf*2Tvdb23RKpyv$iIOlV;Jyf@C)J&B@$F^TGEjEXvVPPnK-oD`gMB+}>_W$P(FFEgfWt9eoapBwg`Aq?Tf%mskp&%UtDYP&?SMLN z?0tk$Jx!b-bJ4%$nUA1#QMX0vxEm|p)DS*x9h99Th zh)H#@k0IFS2I7Ug8NieqV7o!az~xjtl>=kY!Era^cI-%*bt zExfeWhCLHflJwNd)@Dar(CPhN6#!s>RCu7vH0pHWz$+a*9K$&{T^H70HY%_FF$2hH z^afo&({vvg-iQ|+M49Fm8#nFryqy3S`2sSP-DCMrmLsu|?dMh0ZF0&Vuh5a_J2 zS{ci1*c$_#HS3Om&Klc<&g%3Tl%>R=ELFdF9j)}u&{-#@|4`_xKc)s{pZH^DQT9iN z(xSwVe)*$w1L)M`{jISga`*?)W(JwScKLex-DlM)iwcF0A?)f$2hm!z zO-D6W)1ia($a+o_5q)fkp0UE$q0+EJAe#rn@}BppKgLe3Zh~2mk>TNFLfnw*nHUu! zI>tT-(;$S(W}Jgiq!h8g5Bo6w!PtkWKAH;qb<|AtxQUx&B%noaJHJX|jP#=UX*f;U zpu#ra%9Y4WXxlzG8;0ML$cxE42HXsjfE!>ozGaMo+4uxoP4cXdc-x8yvQ8pH{3wzP zx{(m)r#RLNyAtVeb<8WS!a;Qr8JaOVqoDnM0j?x) zW}P<#LDgwlb;i*eG-9bO*>kx2&hUew(vWVnZ*I7Hfq|`A87c^ z4{@u&=7xiSZP&4}691jpuJprn!1=?Z>jHf^rDq!52Cg+X>`ovq`qAwa7}yITRf%>A zyboO`ogbo=>+RqCAVz(C84jqAKBxmuAl1MzNHAw97^0h$$rROKe0$yqL_5{|Ka0*U~m_M|HwcL zdEVgNC8Kc*Gw?tkXpe_^nRQdY6)AA^k2c?>tXkJH;6Jk8P19E7)-;EBHIXs%Jh zbm+H%6^U3WIcgSR&IsJU?*zwciB$!Op9k4A78AhoF{F2Z>Q)WD0 z&}gK|J?S>QSL!@YPMvr@EK+ZR*S4yt*yI_<#uw+#@tfG@jp&RwXAv$x!;HjEP>$#k z4gS=|<2-BVR6i|^tmdP-`zEUplZc9JbOdSDC(*O7aKtIaltUP@Jf%wF{i1uN6U`wi zpXvDrK4#i|Mmi*;X{f`Yb}l2oFG9WEf|<@v5W+m{neyuv4q?JcIht&yBfJcVR1m_g zteb1)@eXD=>LVbAv1bNGJ2S;q?)S z`e81L4Y%fN&T7drSBG!{033xlKMyZ#Fi?e7nHzI?B16JC3o{^|d+*FB($Hdr3-jGb@mR_`uzSwZQEPSyU ztsNHk@RYqmDFKo?htmYcz0&$llF(oU#-D@Y!W(bxV*S)next79dAIXA^4YU~i5j7=Ag;^RO0WSJzxd*T;#NNg+Cxqt zghx?JPLkoI^7D!|A$;~tuG8uW4R*z;X-(&^!RxC?EM^fZ%PNTjs9SIcr;Rj6`6ge} zsDQ_43vb_)Wf~6^nw0tqsoKs3fZnLx0eKOP^Y>byz*dSh#DoYHXc8;wyg) zz6r$mVq&X$gjsRg>y7K5=3|+U0!a_^^DG>jHqle+Gki(jw+bZ)x2h`~9L4v#mcB`c z+)||WQCghu8H`oaO5Bm&#yrGyW)s+qgPUUj?W zoV?;OCfh2({O2ie1iFq9Xu0?e4vUvJI4T}Yc^a!0j4zB=(>!z6D{V{Q>oIS1eG5(s z$qCDyvGRZt&mo6#GRHU>r0{AAnw719HfhnxaQi>D=C2mqZG=yNGFw--!KMZ0nLuB& z9qW53s!vKSxj4r}%;txb=k93j>=+1lt?qDl1Cs2(uD{f4yH|I*dvNZ^xVKH9+buXr zWGCPhGg^s1uk3Da#ls3tHAs;VIl zGmQ4!$3%`gAHpE!)8E$Xh)~I!MUZRq5CE63WEyq%UJ#<8$_*4dtGQ+&OVFnlx)pBn zJCF+VAozMasxumpUvBgB06M6P&Z5=L-v&6!fgAW}!>N!*4LFdSC>#qC!1@9AO8vn{zfN zSJ3>x5r-aL@e5w*ZQh9;Yy%^%z?F{GrCx!xj28Hf_TeF+?1$F=or3c#+Rb_FYAPlbLq}yiUHl8>`8p+N8yo0`Hjt3Kg-ox>{mAhrUaxZ$c{rO0w^D2{-M`9-LOFjGyqcc%MdbZs33u5X5M8)AhT{+{U(uTUoW$Z!UdsDb9x0!p^AGb znq?_`9Ek=NrC+S^tkk;es#t7 zFv}kq1Yg@xI|o1To7iHOQZKM&rUGN6w{b(l)q{0@F$Va;5&A64;%Bh}rL2se58GG* z2e_OZ$*$bo{MTPjO(c&^lm{C~fTze53&aF}P1%Voaldey_lMi?@v5F$~c%IdMhLYBp92_)5NVB2e798SgfamYQzjmi6*N0kQv(N zs3ZI&FRh;uDG~`!aq#aK#HdqrUg{{4RSR+wh(7x@Uth$zZV*5$t8;j#YzA{om6mSx zQ}A(F&5`yH3DB3=_ae}LnRojch$w23cl#LJ%Yb5$iCy~anx~lOVFph#5b@B1O!N%~ zCm1Jq?M^=SP8ASY(iGpGWWe4Qs|(bO$JXMw>u$Yw`n8CRMC#-l?tC>*EA<-5C@r1p zjkbt%DIWXhln=2U#!KTz3)|^cU7xTqp3LBQ8cK%fB_K4V;NdbONK?Wd;XB?F0h@M$ z#A6@&whOVW$Yz2AgX6AgtSU!n;J|ALX&?xJxoQXJzTjMD0BHznuoDwvlN1FhvSA2Y zim-nZ4%kI(Qi5RAXk~baJ;cF@mI#E^WgG}wXccj&`eheK#`1VtF9RXTL$H~U4MqAm zjg_tL2ndieL_jz<1#uaiG-IrmEQ4 zL#v5PaluMZ4_Hf}9=rSNah+Pc8qbk+K%QTV=gBy@clt#P7?i&jHsEQgf#@zGCP*kw zp8AEu*l@;kvyPP&16^A60ZLRT$e7eV zRVOJgzE9qlq#B5Pov#K`i64q*t7V~b3t?P zb{SF|U^wllIOLR_jSbUFE68e6G>FWwIcZO7&p60LR}cFmE0vSz2vx!9>5f+I;{aH( z#qG}~(m*n+-Z>E39#vGStl?~+L#5FGmu_xj%2JG^1=o^(wWq%#sYcs9Iwm zl0H2XQ?~+;4ysv0_FelOj~ITE%s)x8@Db#gyO(++y{D^`x>e{18fSurfa_(L zTYhgO2V+b+V#a}Xd)^v>k>)l$8`nTdET9e($(adbYHA`srT#tg)7^ON*v!<7W;hB{ zQ^$@?i6fk2xS1$SsSG{~(;@2EhB$nJT}$CtIMS-`6Uif9*3{J04D;xVn?aqvpva-A zf5PBb5%{JJ0j0WwUB`V*)oj<9E#i$H% zR_DAThow>s$RQ}8_=F-iA`A#5Fu-NCIgr{yQSE9z zs%_Qe5nt6JcEjPcOF5*px}6uC+iFkNxRQZ;Q4EgtQunjTf1eqYr)+nrt1dpS-&eQP z4kP_QWIp=5YV!MPf!1-;vUfn;$Go;OuOS}eDwGA0tekzR{tn-sLf{vV&of$7x#~|b znkEX>5)6cnUg06C5aOs88UF-Fvd+6%1`P&W+|?n;95jf|M3%AQTRP>@K6*UfeUX9i z4#FaQ1&=0Ab>bGbb^6aPxaXyIC6pD|7aI!@AjZ>(%=*=U!}7*V)? zOQ%DA@Hh_(_U~uX2JF&}x8aHYdq&RqZYFQMWfY7*Fp9=^G9}~Ng(2h3OxgIa#<21G z#)$E)%xK}iBz|(&legxLt%K#5-wtyJ(0w<9+;M2uJDFJS268VT_Y873kb7pR@Mi7+ zTCv6aKEZJrEe*ddqzmsDw+)toc6^5^=`}xW154S4QZhjsSPI)vkWvcYHs&|UC8}$f z%V1B0xy0*geE!4cl!>*v%vOIkw-v2^mu+FIS&M>M_`XpIOEBN&JGPTOvMn}NWK0w_MPsLNJm> z=fmVwh|LMkIL?W&7mXp-(F}TqbE!8zh3{n^#@kK)!93*m5idPjMz57)-)+O}z=;dr s<+#R2!@vwjU;fv!%<#guj4QpIv1Z<4ejJ4Y@(WiC=XC#UEC0d&56u$XFaQ7m diff --git a/venv/Lib/site-packages/dns/__pycache__/rcode.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/rcode.cpython-310.pyc deleted file mode 100644 index 9844529816c2b7dabccf9c2eae0dcc3c2eadfa8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3261 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/rdataset.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/rdataset.cpython-310.pyc deleted file mode 100644 index f528cc072fc4396be4be600f8ed59f166fd156f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15298 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 r&+X7mC#j%SzG(T0`JQCR`^3GFOqp?iB;Hy}it1 diff --git a/venv/Lib/site-packages/dns/__pycache__/resolver.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/resolver.cpython-310.pyc deleted file mode 100644 index 9826cb9b4708458d80660109a829ca652132aa93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52699 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 G^W-n0SwuVl diff --git a/venv/Lib/site-packages/dns/__pycache__/rrset.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/rrset.cpython-310.pyc deleted file mode 100644 index 5182c0c19fcb3e9e0d987b60572d11a9bb5d53c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7937 zcmd5>&2t+^cAx3_05Al>4^gBfOZNC!vWIV6{ya`R?sZ!0ai_H!8zzl$sV!nQ1FH7#jN(X;!a zDf&*+>AOw0?=`)?-}L*XX33`aPOsdo@OLo&o*RExo0T71(v{v5OM0r(o$uC8oaREs z!Jl7o?&rt% zOSrG8t8!uHc~LENR^*age&RL%r@ts9NvX<9a^;EJd8kpNKPQxf1M13VgEu$>L z>-xWvBkO+d+#MX{!DiCysdg48gWSCrx3j$b={`M0z1;ihfV2`z^xG#4raIV)4x^vR!cU3Hq##E)F;23&y)#?O4 zw>q{g%gU4aW{vLyIrpU8T#!{c|HNu8%9>oj_Y%KbluLNGESCX@OSo3lO2_9nm*wh{ zYV&f%mEZaA{60&lvV=8x1v;!&+{#t?w!FqVVij=ND{4hvS8M8uy2Nl?QCB);o^wOK ziaA#?$CdBM*Pu~2o_7uNW@Vh8|H^pXugf*D%(vYONsQOgFeQlw?eHt4A{Y=FxypO zCu&2&Zj=?mquyb3l!p8pSW$8~P?}|sc{cbicj-PaOVv|ZJb2W|OIo&jQJUtymf6w1 z%KdhN1*L6&2J&?8;c{@LA)3rOv7Xu^F>*%ksbgCsdt|l5$V2N$8@>|5OPg#?ib5EM z*T2!IySbMh>?@s@TdjByXRVg5K%Sf0{zshx?C`zIu31rF&Vj|L~K0A3lzH4l|Gb% z^tRT>2OIlGdI7T6aiz4x#lW`%dss8d77Dh3w#i4}jxM&utGF?iIJJ&pfvyl()8J`_*jk;!uFLNCz^C)w%hW!&i%YN){IH8elOm6p*2b{T)JJ*6Py(Lf1Qo;{(-lyV5$a^&8T|dyn6{ z^!`{3ki3qC^fMoGN+&d@v}R34m061EF>))^GonjiY#HCy)8N#?ePzu8B!Y$}OXk*@ zy?$obhvkq_sD69sy-%@xW{2qGCEmfq2lYAjeD1(ud4-cW1GF@b6NW?{@CyTBC(ZN) z@HFRIJfNl3zOFlL@ut_NIBR;6zKqo;rYB(1*jDR(vgL1~32fh96@k5CyF!SvEuP`) zKdO%Sm2ky3RZn~^d~qg9;+LW<{@t&LUx+|_C7w-zWCWh`7@2~A#2zCr!&=rU?4(!m zP`7o6uP<#@_@auXRtqa_wH{zdN!p!>%5mNJs9w&4IE@Es77f};lkUdo6b^Zr&5h{F z%lF3#w7`E$eb#CfsP_`&FntmCb%^*Gu9QM1u&Y45cvcfG?k4DGF}aJxh@`c5Xuh?| z4)oxhg^QS=5Kn&{4J}RDR|&(S>tOjySiU>5V<7f#?7yI;dM8%bpY5rO=o(d1S>QUvP?g;i)VM4mcre2bw zrf@-28)~9%wv+yTl*K5C;bEMS#Zay=iRv-e0S;VKQt5XmD)sS;X;IjC5mZ;njK$JY zC={b>Un`V=$0%mu4pKbuAgB5izaRJF>}aDt5zm>ZUea#^7MgI&2+m!yZXQhiW1#D? z0^{tVze~e!QF9?_zl**dCi{YFJOBV3$C6#8LFR5ujp=ZK#&q-Hs=Zrjr z=_>V0fqd!=v-^zt6!_TE2Y`ja(s`6JaN)BFP6*1Wylfbl35k!-U- zHpX~)h6EF02yp4F=oteT@jFS<+ulYR__zbP2Fth1JmigDkJ$Nik|D+<84D})H2ju2 z3wVYA$rPUGCAOu1jhgRM^8;!w;59_w7q}R&{wnIvGhzGBit0MHSnd*J@-k%?WS_K6 zxGX+|Pa>0y(GWKj*fSU<3g&b?pwul;I{e4yA&RBZ*5G+u-i0~-ONV2oaoD69Ky9}et$qswF4DU>n5*#J-_jC@z^!=0C6hE~-Wskb8e4VIXw+XP?n=SdYUM$z)lcL> zkM66j)@KJ%Z~O-2Q6_D4V=I;Rk}L(^FPE zxzJ={-azqoMZZap-=T(BoF=7nmm=E~3MvJf0!6<;O^Bvh-5f^{$;%y}OOv}bnN8ES zOcPzr=f|7AwgPWz&6ta$mp4qrLa*aWKSxuxT)SNHOTu=~d{A{CRNV(v_d(SIzjjuw zmHqNs)wxy{YcCo>WWM%GaT)V}6=1%=`~dTXSNmGrK<_uS0SLyu0dD|mXV)$>7v3_~ zqm6@}>|ygc+G>ow3i>PuQLCLu)t=^~e14kYT3MpM2LWx`EEXTy3sV_oR8x`yp9PmC z8lQpBg2`gXH}a(TbLZGX4-S|>+r_DUEbxTm8$3C9a;I7Ky7i3P%2@G%An0)6(%AMlX!!X!K|GQH3~2bOb*aJN@G9ZA|r^ zCmmZ`pA^i)oOm$nppzJy!qG#;WXe@2MmWWAJfg&gWXJPK@#fT;H!oDHkMA|^ZjzZP zX%$k5$g7ZE@eeAHRH^iBjG}L-~kEqo75+_wBI_PCQGyML$@BZM0(?Py4y(rd2 zb-JKe13`+SyFOD!>s&`!kLSIxt$9Zi=1R!_Odf%#L zQSFU}tTQ$TgK3E-GEV7+PQFmmaVmzglNqK^m?Xpz%>iu-OnIL%+H;wf4{JF2!Du)w z!KtlDwGC{Le~d_|FB&G#nPp1nE1YP*{yh?C>)g(Aq2)}rqC}O~COWkU+<%9@^a`5b#NP{6E3)f5FAOE-{Y{#xqTQ zbf8J+{^x8*#B9P0hIn{k4#hz}=TL7XPVnCwoT6RHeCeLpU*P=U*c}OE$}7j-$d&ei zrEg~?*dNFIxGKo0?#O)_6gd^y)#H45ok!d0dq1(hutzR@<3+bYR9@0O>f8Yx!Jd$LA)-w*(@`8ES|Fn7|6TU*&;BnVV@zmrY5|p(a|aWApBFO| zyqtW0A8Wz?YAF10Xfh3Cw%~b_;jm>wj#m*5%yqAo^dCY*-EB0s8iwPB`U4W`tNokaYG}%Jak*2W}t!oA~lQfo>-#2{y0~oV8waD|oE% Jg0F9e{|TU}&3ga< diff --git a/venv/Lib/site-packages/dns/__pycache__/serial.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/serial.cpython-310.pyc deleted file mode 100644 index 3a66ff562d585ba3d82e53780ad1161a191226e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2876 zcmcImPfr_16rY*hwHIR>3dHGq+sY-<>U}!UcEN)lI zjQvT2Y;!Ppf-kCoD7MbNVTvnp#FRJ`>s&c&tmf`7t!Wc9JJtGbcSD=%S0>&Lx;hS8 z)lJjuR=<0`QvLX|N1wE?#<}KU^aNk@6NqM5kF5)}sDyTuqn%Axxyn28)?JlT`6IUO zDPN6&=Tt$BgXdLImB4*fRukZ3YEr!eUQknN8hl*Ms9WGgRZ+9xB{iq!!OLnv-3Fgf zcVPeBB$wKMT!k5lx7Y0K>crg$;;2Rbj~eyqTfrC2feg6f12N4iY``QN2vB%{6-E76 zKt2?P^oo-=PK7%EVJss{f zR)dX36vX;rzu9Uxw{+A{Ve}FH1k{)NKPSGFK^VkR=CNW#`;~ct?@y$DEsvxv4#}ud zp8{arvEk(dw!?lyXu&zS^Sejkt?y4^x8;9!OP74GFFvfk;x&`Q3N>zMU+Ydv#xNwK zjP4sL$1#cskV@91RMw*TQKSAT!jCbCfpN?ag(=2jK;}7z;(&)GJC6)Bvje{4(0to5 z^Rc^zNbGo+^V(vK4S9W-OA0|0gi+iKTRL%qFgE14jY(3j_u_B6{f_SHFxJY(20dlsGEvgicO@mwAP|yvX-Ur(l!DjroNWXG-J&*at-l?l{vD{DP#%wBvV^$Iai8b@avfJ>P$2C~C{XTM6eiIbAn)3u zpSK(*Iz`;#d1~tUY3^>Lj zc7NfqH*gNAlCzy$ny*CLu6dWFsOrwASZg3s4XXB78Dr8vq$=a2d1~lN80OOgKY@N) zXegbM!Vh$(JTsEm+Wm73BsT|t$&Y`mV_;TD8 z3rKMvB?#rGd|H02`ngz~!)FHz-84S-F2pW~@;z*4szmM+xlpU<;&$7$;8SEuJ+{Z$Lg{t|0!11-hdpbkt3N0 zhLzOu6re+2o21)6Y<6){lY*4pp4z24m=vXax!dfd5<_Rh6o?dw%n+dpZsv*HCbCH6 zE|Dc74~S5mH6IW;%O=~SXNNs?^eTy{Liucl`>yZ!dHl-Y={HdK`?_+)l=C-A7%0O4 diff --git a/venv/Lib/site-packages/dns/__pycache__/set.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/set.cpython-310.pyc deleted file mode 100644 index 3c2b2d480a828bb01b4fd106a8a1864ab8d9013d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8740 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/tokenizer.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/tokenizer.cpython-310.pyc deleted file mode 100644 index 88e251a480626bb6f7e72675dad0eb015373f078..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17127 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 z 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 Q+h?3%W6XJMzcfDdzx|XwRR910 diff --git a/venv/Lib/site-packages/dns/__pycache__/tsigkeyring.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/tsigkeyring.cpython-310.pyc deleted file mode 100644 index 06bb6adc621f14dc2bcefb5675fd4feeb22af982..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1852 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 G75^{ud@7;< diff --git a/venv/Lib/site-packages/dns/__pycache__/version.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/version.cpython-310.pyc deleted file mode 100644 index 5da5362f75a77c604d7863cda0e2db763fc31d59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 580 zcmZ8dO;6iE5M8g=_9l%BNCRL%}L4msaJ{^!)7wpIjH zTV*vGP;W8h@S(+y8Jf_jq5!vw)-h8KeC)Arl4_IL6;R91PkdwvpNg+H3Q5&C>o{Pc-69j2XD-~p@QAA$7Tt#1VM0q zAeTG>*jx)-X^^#i}%BlzV9%I^8y({`|Q*3VtmM|iW&A6Vv6 z%L@K>IzPfoO*4h*RWify1odQ|q+xL4=g~CGG0wwa{5#a+Ietx}!6dpu9n!aaTX$=w qw@Z0AOW=BnEra^%LjtiSOu<)M@=Y!c{%^}?X}@ROd1Lm|m)Z-rZHKJ@ diff --git a/venv/Lib/site-packages/dns/__pycache__/versioned.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/versioned.cpython-310.pyc deleted file mode 100644 index f8a567b3ce547f52ff025c39bf0450d9fdf56a5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8876 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/win32util.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/win32util.cpython-310.pyc deleted file mode 100644 index 62106b3de04bbe7b2a74fb38ea579e18ab058689..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5556 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 aQ#WQs;l+Z+er}$lgQqU?g8f4O!~X!)U+zi( diff --git a/venv/Lib/site-packages/dns/__pycache__/wire.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/wire.cpython-310.pyc deleted file mode 100644 index bdeb8ffc6565553fb2b7cf15e26161a3e409092e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3314 zcma)8NpBlB6ec;N(MYysSysF>`yQo<+bm7oB4~qVX;TDh0jCQD0Rvg2ZQ0t&899ld z0BP<15Buo9#7hr7`P^GC?fW>AA}=X20-v}%lJ9+QV{2j}&FIVjd3r4~#@JsNjD8Lc z9#RXR5|K>uIxEHhyu@iN>Z0M4oQ7L+8;Mea$7^0GX?gup@*5@{>25RWZi!M#@+DSC z?9*ASSa6L0EK<4>wY2fSZ%4IOvr;#S7oB!pRlzd)C1~)FS|~VUisAB-kOe7}BOT?g zxYCu0Z4yCxG!il?{cX48$&_+w#-a7J9HW_}ye=n(a~U~Fdwk0wWL8cQN2-59PEOM( z-5=%U2^x*{M>BGkM&td_oSdi8g#1WlXl9b`Iw?=lOjdp@&!{PRcAiO3o~8M7@;u#_ zlNTU?JWVqfg7$<+$=w@EtkVuq;9q=)s4!k3d^z?egfqd z+OLft1hr-@3W9MuF9h+p$H%$L)AZ|3#)vEoxQwS&)X~i*eqr^5@rhJeN)3{6VCswx{~CiS$X8&9-u>32plPNVWl1CN3eD}4f6y;dh` zccLQ*tg0wjejTZBmbgOTGfsB!`3%qSEZJj-#*lH}`so`NnRdhye7ld`Rswwmz2ojn5AM5l?>cxu zx>F-i;JRD)KIFb<`>@W3-goEr&G+7S=k}5NhW-jG5B!yUl@sz5g9WF!ZxiMj9C{Yy zf3>~4i0o`lpW{dLy}M|<6^h$RbReSuPQ<#6n>p%OIjsGu=OB9E1p`-fHB6|lfxsz^ zU#--uh(_{Ko9k|2>5zk3gT&r)hnB5~a|cC?SBsP|bZxcP>`qY5S!h-oYN1HvfXEIV zfo4SpHW6iC3T=uQ3UW%hJrN5|qY=U3+{VR`rL2v2RE3~zi(o0ORlO3`HlavAf88a1 z{Taw1ZG5;F&bdd6A;60(2xYB71sQOd#LG3M4~h@O(X99gR-40Fm_q(uNA{i=W^bAa zT-4AwA1C6{0!=g$r-s37r5T`q9}@@V)$}f752%H3rkvv=JB{_D0k!uCxKOEz4U))j zgBp`ORAZ)wQc{h1Bf9g08WYR>6QegkTzT9LM_(Io{~W&ztXB4o;J)l@=fxTBkaojj zI|K^--u8+gW zrXyiGgyVvRqnnlt%8??r@(1*kTpIRCnSRbjEwr{dHfpoDu|*Czc=x;@cI!;ytq@cQ zMR#^Ywo%RkkDpUK&c^n-dAx1llR;q8LC|Q)P96R6Ao#UYsrOeBw&dz_kSq&=@*d~y zi|D}{bphlC$N~s*ig5^1Z8IU_S34l^e(PH%U2Rbnd==Ge%O=zBH!4kferXL)*NY&Z zgS>N1+rx86BMrhwL*VPPJkR(!C!fl=87KbboH-}wxyd|tvw3d$3u*lo_97b@FM8dk w$5ecml?|fOgPKyv@YSN>SM*fxrxkn3apD;NL5$v)cyQQ9qEGh7bI_dgA4oo=(f|Me diff --git a/venv/Lib/site-packages/dns/__pycache__/xfr.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/xfr.cpython-310.pyc deleted file mode 100644 index 6a55790d129a319afcd0351f8739c2f13a974018..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7820 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 diff --git a/venv/Lib/site-packages/dns/__pycache__/zonefile.cpython-310.pyc b/venv/Lib/site-packages/dns/__pycache__/zonefile.cpython-310.pyc deleted file mode 100644 index 02858df7fe6cf2593d72101c487d03547d190174..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17735 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 0: - infos.append(_SVCBInfo(bootstrap_address, port, host, nameservers)) - return infos - - -def _get_nameservers_sync(answer, lifetime): - """Return a list of TLS-validated resolver nameservers extracted from an SVCB - answer.""" - nameservers = [] - infos = _extract_nameservers_from_svcb(answer) - for info in infos: - try: - if info.ddr_tls_check_sync(lifetime): - nameservers.extend(info.nameservers) - except Exception: - pass - return nameservers - - -async def _get_nameservers_async(answer, lifetime): - """Return a list of TLS-validated resolver nameservers extracted from an SVCB - answer.""" - nameservers = [] - infos = _extract_nameservers_from_svcb(answer) - for info in infos: - try: - if await info.ddr_tls_check_async(lifetime): - nameservers.extend(info.nameservers) - except Exception: - pass - return nameservers diff --git a/venv/Lib/site-packages/dns/_features.py b/venv/Lib/site-packages/dns/_features.py deleted file mode 100644 index fa6d495..0000000 --- a/venv/Lib/site-packages/dns/_features.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import importlib.metadata -import itertools -import string -from typing import Dict, List, Tuple - - -def _tuple_from_text(version: str) -> Tuple: - text_parts = version.split(".") - int_parts = [] - for text_part in text_parts: - digit_prefix = "".join( - itertools.takewhile(lambda x: x in string.digits, text_part) - ) - try: - int_parts.append(int(digit_prefix)) - except Exception: - break - return tuple(int_parts) - - -def _version_check( - requirement: str, -) -> bool: - """Is the requirement fulfilled? - - The requirement must be of the form - - package>=version - """ - package, minimum = requirement.split(">=") - try: - version = importlib.metadata.version(package) - # This shouldn't happen, but it apparently can. - if version is None: - return False - except Exception: - return False - t_version = _tuple_from_text(version) - t_minimum = _tuple_from_text(minimum) - if t_version < t_minimum: - return False - return True - - -_cache: Dict[str, bool] = {} - - -def have(feature: str) -> bool: - """Is *feature* available? - - This tests if all optional packages needed for the - feature are available and recent enough. - - Returns ``True`` if the feature is available, - and ``False`` if it is not or if metadata is - missing. - """ - value = _cache.get(feature) - if value is not None: - return value - requirements = _requirements.get(feature) - if requirements is None: - # we make a cache entry here for consistency not performance - _cache[feature] = False - return False - ok = True - for requirement in requirements: - if not _version_check(requirement): - ok = False - break - _cache[feature] = ok - return ok - - -def force(feature: str, enabled: bool) -> None: - """Force the status of *feature* to be *enabled*. - - This method is provided as a workaround for any cases - where importlib.metadata is ineffective, or for testing. - """ - _cache[feature] = enabled - - -_requirements: Dict[str, List[str]] = { - ### BEGIN generated requirements - "dnssec": ["cryptography>=43"], - "doh": ["httpcore>=1.0.0", "httpx>=0.26.0", "h2>=4.1.0"], - "doq": ["aioquic>=1.0.0"], - "idna": ["idna>=3.7"], - "trio": ["trio>=0.23"], - "wmi": ["wmi>=1.5.1"], - ### END generated requirements -} diff --git a/venv/Lib/site-packages/dns/_immutable_ctx.py b/venv/Lib/site-packages/dns/_immutable_ctx.py deleted file mode 100644 index ae7a33b..0000000 --- a/venv/Lib/site-packages/dns/_immutable_ctx.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# This implementation of the immutable decorator requires python >= -# 3.7, and is significantly more storage efficient when making classes -# with slots immutable. It's also faster. - -import contextvars -import inspect - -_in__init__ = contextvars.ContextVar("_immutable_in__init__", default=False) - - -class _Immutable: - """Immutable mixin class""" - - # We set slots to the empty list to say "we don't have any attributes". - # We do this so that if we're mixed in with a class with __slots__, we - # don't cause a __dict__ to be added which would waste space. - - __slots__ = () - - def __setattr__(self, name, value): - if _in__init__.get() is not self: - raise TypeError("object doesn't support attribute assignment") - else: - super().__setattr__(name, value) - - def __delattr__(self, name): - if _in__init__.get() is not self: - raise TypeError("object doesn't support attribute assignment") - else: - super().__delattr__(name) - - -def _immutable_init(f): - def nf(*args, **kwargs): - previous = _in__init__.set(args[0]) - try: - # call the actual __init__ - f(*args, **kwargs) - finally: - _in__init__.reset(previous) - - nf.__signature__ = inspect.signature(f) - return nf - - -def immutable(cls): - if _Immutable in cls.__mro__: - # Some ancestor already has the mixin, so just make sure we keep - # following the __init__ protocol. - cls.__init__ = _immutable_init(cls.__init__) - if hasattr(cls, "__setstate__"): - cls.__setstate__ = _immutable_init(cls.__setstate__) - ncls = cls - else: - # Mixin the Immutable class and follow the __init__ protocol. - class ncls(_Immutable, cls): - # We have to do the __slots__ declaration here too! - __slots__ = () - - @_immutable_init - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - if hasattr(cls, "__setstate__"): - - @_immutable_init - def __setstate__(self, *args, **kwargs): - super().__setstate__(*args, **kwargs) - - # make ncls have the same name and module as cls - ncls.__name__ = cls.__name__ - ncls.__qualname__ = cls.__qualname__ - ncls.__module__ = cls.__module__ - return ncls diff --git a/venv/Lib/site-packages/dns/_trio_backend.py b/venv/Lib/site-packages/dns/_trio_backend.py deleted file mode 100644 index 0ed904d..0000000 --- a/venv/Lib/site-packages/dns/_trio_backend.py +++ /dev/null @@ -1,253 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -"""trio async I/O library query support""" - -import socket - -import trio -import trio.socket # type: ignore - -import dns._asyncbackend -import dns._features -import dns.exception -import dns.inet - -if not dns._features.have("trio"): - raise ImportError("trio not found or too old") - - -def _maybe_timeout(timeout): - if timeout is not None: - return trio.move_on_after(timeout) - else: - return dns._asyncbackend.NullContext() - - -# for brevity -_lltuple = dns.inet.low_level_address_tuple - -# pylint: disable=redefined-outer-name - - -class DatagramSocket(dns._asyncbackend.DatagramSocket): - def __init__(self, sock): - super().__init__(sock.family, socket.SOCK_DGRAM) - self.socket = sock - - async def sendto(self, what, destination, timeout): - with _maybe_timeout(timeout): - if destination is None: - return await self.socket.send(what) - else: - return await self.socket.sendto(what, destination) - raise dns.exception.Timeout( - timeout=timeout - ) # pragma: no cover lgtm[py/unreachable-statement] - - async def recvfrom(self, size, timeout): - with _maybe_timeout(timeout): - return await self.socket.recvfrom(size) - raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] - - async def close(self): - self.socket.close() - - async def getpeername(self): - return self.socket.getpeername() - - async def getsockname(self): - return self.socket.getsockname() - - async def getpeercert(self, timeout): - raise NotImplementedError - - -class StreamSocket(dns._asyncbackend.StreamSocket): - def __init__(self, family, stream, tls=False): - super().__init__(family, socket.SOCK_STREAM) - self.stream = stream - self.tls = tls - - async def sendall(self, what, timeout): - with _maybe_timeout(timeout): - return await self.stream.send_all(what) - raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] - - async def recv(self, size, timeout): - with _maybe_timeout(timeout): - return await self.stream.receive_some(size) - raise dns.exception.Timeout(timeout=timeout) # lgtm[py/unreachable-statement] - - async def close(self): - await self.stream.aclose() - - async def getpeername(self): - if self.tls: - return self.stream.transport_stream.socket.getpeername() - else: - return self.stream.socket.getpeername() - - async def getsockname(self): - if self.tls: - return self.stream.transport_stream.socket.getsockname() - else: - return self.stream.socket.getsockname() - - async def getpeercert(self, timeout): - if self.tls: - with _maybe_timeout(timeout): - await self.stream.do_handshake() - return self.stream.getpeercert() - else: - raise NotImplementedError - - -if dns._features.have("doh"): - import httpcore - import httpcore._backends.trio - import httpx - - _CoreAsyncNetworkBackend = httpcore.AsyncNetworkBackend - _CoreTrioStream = httpcore._backends.trio.TrioStream - - from dns.query import _compute_times, _expiration_for_this_attempt, _remaining - - class _NetworkBackend(_CoreAsyncNetworkBackend): - def __init__(self, resolver, local_port, bootstrap_address, family): - super().__init__() - self._local_port = local_port - self._resolver = resolver - self._bootstrap_address = bootstrap_address - self._family = family - - async def connect_tcp( - self, host, port, timeout, local_address, socket_options=None - ): # pylint: disable=signature-differs - addresses = [] - _, expiration = _compute_times(timeout) - if dns.inet.is_address(host): - addresses.append(host) - elif self._bootstrap_address is not None: - addresses.append(self._bootstrap_address) - else: - timeout = _remaining(expiration) - family = self._family - if local_address: - family = dns.inet.af_for_address(local_address) - answers = await self._resolver.resolve_name( - host, family=family, lifetime=timeout - ) - addresses = answers.addresses() - for address in addresses: - try: - af = dns.inet.af_for_address(address) - if local_address is not None or self._local_port != 0: - source = (local_address, self._local_port) - else: - source = None - destination = (address, port) - attempt_expiration = _expiration_for_this_attempt(2.0, expiration) - timeout = _remaining(attempt_expiration) - sock = await Backend().make_socket( - af, socket.SOCK_STREAM, 0, source, destination, timeout - ) - return _CoreTrioStream(sock.stream) - except Exception: - continue - raise httpcore.ConnectError - - async def connect_unix_socket( - self, path, timeout, socket_options=None - ): # pylint: disable=signature-differs - raise NotImplementedError - - async def sleep(self, seconds): # pylint: disable=signature-differs - await trio.sleep(seconds) - - class _HTTPTransport(httpx.AsyncHTTPTransport): - def __init__( - self, - *args, - local_port=0, - bootstrap_address=None, - resolver=None, - family=socket.AF_UNSPEC, - **kwargs, - ): - if resolver is None and bootstrap_address is None: - # pylint: disable=import-outside-toplevel,redefined-outer-name - import dns.asyncresolver - - resolver = dns.asyncresolver.Resolver() - super().__init__(*args, **kwargs) - self._pool._network_backend = _NetworkBackend( - resolver, local_port, bootstrap_address, family - ) - -else: - _HTTPTransport = dns._asyncbackend.NullTransport # type: ignore - - -class Backend(dns._asyncbackend.Backend): - def name(self): - return "trio" - - async def make_socket( - self, - af, - socktype, - proto=0, - source=None, - destination=None, - timeout=None, - ssl_context=None, - server_hostname=None, - ): - s = trio.socket.socket(af, socktype, proto) - stream = None - try: - if source: - await s.bind(_lltuple(source, af)) - if socktype == socket.SOCK_STREAM or destination is not None: - connected = False - with _maybe_timeout(timeout): - await s.connect(_lltuple(destination, af)) - connected = True - if not connected: - raise dns.exception.Timeout( - timeout=timeout - ) # lgtm[py/unreachable-statement] - except Exception: # pragma: no cover - s.close() - raise - if socktype == socket.SOCK_DGRAM: - return DatagramSocket(s) - elif socktype == socket.SOCK_STREAM: - stream = trio.SocketStream(s) - tls = False - if ssl_context: - tls = True - try: - stream = trio.SSLStream( - stream, ssl_context, server_hostname=server_hostname - ) - except Exception: # pragma: no cover - await stream.aclose() - raise - return StreamSocket(af, stream, tls) - raise NotImplementedError( - "unsupported socket " + f"type {socktype}" - ) # pragma: no cover - - async def sleep(self, interval): - await trio.sleep(interval) - - def get_transport_class(self): - return _HTTPTransport - - async def wait_for(self, awaitable, timeout): - with _maybe_timeout(timeout): - return await awaitable - raise dns.exception.Timeout( - timeout=timeout - ) # pragma: no cover lgtm[py/unreachable-statement] diff --git a/venv/Lib/site-packages/dns/asyncbackend.py b/venv/Lib/site-packages/dns/asyncbackend.py deleted file mode 100644 index 0ec58b0..0000000 --- a/venv/Lib/site-packages/dns/asyncbackend.py +++ /dev/null @@ -1,101 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -from typing import Dict - -import dns.exception - -# pylint: disable=unused-import -from dns._asyncbackend import ( # noqa: F401 lgtm[py/unused-import] - Backend, - DatagramSocket, - Socket, - StreamSocket, -) - -# pylint: enable=unused-import - -_default_backend = None - -_backends: Dict[str, Backend] = {} - -# Allow sniffio import to be disabled for testing purposes -_no_sniffio = False - - -class AsyncLibraryNotFoundError(dns.exception.DNSException): - pass - - -def get_backend(name: str) -> Backend: - """Get the specified asynchronous backend. - - *name*, a ``str``, the name of the backend. Currently the "trio" - and "asyncio" backends are available. - - Raises NotImplementedError if an unknown backend name is specified. - """ - # pylint: disable=import-outside-toplevel,redefined-outer-name - backend = _backends.get(name) - if backend: - return backend - if name == "trio": - import dns._trio_backend - - backend = dns._trio_backend.Backend() - elif name == "asyncio": - import dns._asyncio_backend - - backend = dns._asyncio_backend.Backend() - else: - raise NotImplementedError(f"unimplemented async backend {name}") - _backends[name] = backend - return backend - - -def sniff() -> str: - """Attempt to determine the in-use asynchronous I/O library by using - the ``sniffio`` module if it is available. - - Returns the name of the library, or raises AsyncLibraryNotFoundError - if the library cannot be determined. - """ - # pylint: disable=import-outside-toplevel - try: - if _no_sniffio: - raise ImportError - import sniffio - - try: - return sniffio.current_async_library() - except sniffio.AsyncLibraryNotFoundError: - raise AsyncLibraryNotFoundError("sniffio cannot determine async library") - except ImportError: - import asyncio - - try: - asyncio.get_running_loop() - return "asyncio" - except RuntimeError: - raise AsyncLibraryNotFoundError("no async library detected") - - -def get_default_backend() -> Backend: - """Get the default backend, initializing it if necessary.""" - if _default_backend: - return _default_backend - - return set_default_backend(sniff()) - - -def set_default_backend(name: str) -> Backend: - """Set the default backend. - - It's not normally necessary to call this method, as - ``get_default_backend()`` will initialize the backend - appropriately in many cases. If ``sniffio`` is not installed, or - in testing situations, this function allows the backend to be set - explicitly. - """ - global _default_backend - _default_backend = get_backend(name) - return _default_backend diff --git a/venv/Lib/site-packages/dns/asyncquery.py b/venv/Lib/site-packages/dns/asyncquery.py deleted file mode 100644 index efad0fd..0000000 --- a/venv/Lib/site-packages/dns/asyncquery.py +++ /dev/null @@ -1,913 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Talk to a DNS server.""" - -import base64 -import contextlib -import random -import socket -import struct -import time -import urllib.parse -from typing import Any, Dict, Optional, Tuple, Union, cast - -import dns.asyncbackend -import dns.exception -import dns.inet -import dns.message -import dns.name -import dns.quic -import dns.rcode -import dns.rdataclass -import dns.rdatatype -import dns.transaction -from dns._asyncbackend import NullContext -from dns.query import ( - BadResponse, - HTTPVersion, - NoDOH, - NoDOQ, - UDPMode, - _check_status, - _compute_times, - _make_dot_ssl_context, - _matches_destination, - _remaining, - have_doh, - ssl, -) - -if have_doh: - import httpx - -# for brevity -_lltuple = dns.inet.low_level_address_tuple - - -def _source_tuple(af, address, port): - # Make a high level source tuple, or return None if address and port - # are both None - if address or port: - if address is None: - if af == socket.AF_INET: - address = "0.0.0.0" - elif af == socket.AF_INET6: - address = "::" - else: - raise NotImplementedError(f"unknown address family {af}") - return (address, port) - else: - return None - - -def _timeout(expiration, now=None): - if expiration is not None: - if not now: - now = time.time() - return max(expiration - now, 0) - else: - return None - - -async def send_udp( - sock: dns.asyncbackend.DatagramSocket, - what: Union[dns.message.Message, bytes], - destination: Any, - expiration: Optional[float] = None, -) -> Tuple[int, float]: - """Send a DNS message to the specified UDP socket. - - *sock*, a ``dns.asyncbackend.DatagramSocket``. - - *what*, a ``bytes`` or ``dns.message.Message``, the message to send. - - *destination*, a destination tuple appropriate for the address family - of the socket, specifying where to send the query. - - *expiration*, a ``float`` or ``None``, the absolute time at which - a timeout exception should be raised. If ``None``, no timeout will - occur. The expiration value is meaningless for the asyncio backend, as - asyncio's transport sendto() never blocks. - - Returns an ``(int, float)`` tuple of bytes sent and the sent time. - """ - - if isinstance(what, dns.message.Message): - what = what.to_wire() - sent_time = time.time() - n = await sock.sendto(what, destination, _timeout(expiration, sent_time)) - return (n, sent_time) - - -async def receive_udp( - sock: dns.asyncbackend.DatagramSocket, - destination: Optional[Any] = None, - expiration: Optional[float] = None, - ignore_unexpected: bool = False, - one_rr_per_rrset: bool = False, - keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None, - request_mac: Optional[bytes] = b"", - ignore_trailing: bool = False, - raise_on_truncation: bool = False, - ignore_errors: bool = False, - query: Optional[dns.message.Message] = None, -) -> Any: - """Read a DNS message from a UDP socket. - - *sock*, a ``dns.asyncbackend.DatagramSocket``. - - See :py:func:`dns.query.receive_udp()` for the documentation of the other - parameters, and exceptions. - - Returns a ``(dns.message.Message, float, tuple)`` tuple of the received message, the - received time, and the address where the message arrived from. - """ - - wire = b"" - while True: - (wire, from_address) = await sock.recvfrom(65535, _timeout(expiration)) - if not _matches_destination( - sock.family, from_address, destination, ignore_unexpected - ): - continue - received_time = time.time() - try: - r = dns.message.from_wire( - wire, - keyring=keyring, - request_mac=request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - raise_on_truncation=raise_on_truncation, - ) - except dns.message.Truncated as e: - # See the comment in query.py for details. - if ( - ignore_errors - and query is not None - and not query.is_response(e.message()) - ): - continue - else: - raise - except Exception: - if ignore_errors: - continue - else: - raise - if ignore_errors and query is not None and not query.is_response(r): - continue - return (r, received_time, from_address) - - -async def udp( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 53, - source: Optional[str] = None, - source_port: int = 0, - ignore_unexpected: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - raise_on_truncation: bool = False, - sock: Optional[dns.asyncbackend.DatagramSocket] = None, - backend: Optional[dns.asyncbackend.Backend] = None, - ignore_errors: bool = False, -) -> dns.message.Message: - """Return the response obtained after sending a query via UDP. - - *sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``, - the socket to use for the query. If ``None``, the default, a - socket is created. Note that if a socket is provided, the - *source*, *source_port*, and *backend* are ignored. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.query.udp()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - wire = q.to_wire() - (begin_time, expiration) = _compute_times(timeout) - af = dns.inet.af_for_address(where) - destination = _lltuple((where, port), af) - if sock: - cm: contextlib.AbstractAsyncContextManager = NullContext(sock) - else: - if not backend: - backend = dns.asyncbackend.get_default_backend() - stuple = _source_tuple(af, source, source_port) - if backend.datagram_connection_required(): - dtuple = (where, port) - else: - dtuple = None - cm = await backend.make_socket(af, socket.SOCK_DGRAM, 0, stuple, dtuple) - async with cm as s: - await send_udp(s, wire, destination, expiration) - (r, received_time, _) = await receive_udp( - s, - destination, - expiration, - ignore_unexpected, - one_rr_per_rrset, - q.keyring, - q.mac, - ignore_trailing, - raise_on_truncation, - ignore_errors, - q, - ) - r.time = received_time - begin_time - # We don't need to check q.is_response() if we are in ignore_errors mode - # as receive_udp() will have checked it. - if not (ignore_errors or q.is_response(r)): - raise BadResponse - return r - - -async def udp_with_fallback( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 53, - source: Optional[str] = None, - source_port: int = 0, - ignore_unexpected: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - udp_sock: Optional[dns.asyncbackend.DatagramSocket] = None, - tcp_sock: Optional[dns.asyncbackend.StreamSocket] = None, - backend: Optional[dns.asyncbackend.Backend] = None, - ignore_errors: bool = False, -) -> Tuple[dns.message.Message, bool]: - """Return the response to the query, trying UDP first and falling back - to TCP if UDP results in a truncated response. - - *udp_sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``, - the socket to use for the UDP query. If ``None``, the default, a - socket is created. Note that if a socket is provided the *source*, - *source_port*, and *backend* are ignored for the UDP query. - - *tcp_sock*, a ``dns.asyncbackend.StreamSocket``, or ``None``, the - socket to use for the TCP query. If ``None``, the default, a - socket is created. Note that if a socket is provided *where*, - *source*, *source_port*, and *backend* are ignored for the TCP query. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.query.udp_with_fallback()` for the documentation - of the other parameters, exceptions, and return type of this - method. - """ - try: - response = await udp( - q, - where, - timeout, - port, - source, - source_port, - ignore_unexpected, - one_rr_per_rrset, - ignore_trailing, - True, - udp_sock, - backend, - ignore_errors, - ) - return (response, False) - except dns.message.Truncated: - response = await tcp( - q, - where, - timeout, - port, - source, - source_port, - one_rr_per_rrset, - ignore_trailing, - tcp_sock, - backend, - ) - return (response, True) - - -async def send_tcp( - sock: dns.asyncbackend.StreamSocket, - what: Union[dns.message.Message, bytes], - expiration: Optional[float] = None, -) -> Tuple[int, float]: - """Send a DNS message to the specified TCP socket. - - *sock*, a ``dns.asyncbackend.StreamSocket``. - - See :py:func:`dns.query.send_tcp()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - - if isinstance(what, dns.message.Message): - tcpmsg = what.to_wire(prepend_length=True) - else: - # copying the wire into tcpmsg is inefficient, but lets us - # avoid writev() or doing a short write that would get pushed - # onto the net - tcpmsg = len(what).to_bytes(2, "big") + what - sent_time = time.time() - await sock.sendall(tcpmsg, _timeout(expiration, sent_time)) - return (len(tcpmsg), sent_time) - - -async def _read_exactly(sock, count, expiration): - """Read the specified number of bytes from stream. Keep trying until we - either get the desired amount, or we hit EOF. - """ - s = b"" - while count > 0: - n = await sock.recv(count, _timeout(expiration)) - if n == b"": - raise EOFError("EOF") - count = count - len(n) - s = s + n - return s - - -async def receive_tcp( - sock: dns.asyncbackend.StreamSocket, - expiration: Optional[float] = None, - one_rr_per_rrset: bool = False, - keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None, - request_mac: Optional[bytes] = b"", - ignore_trailing: bool = False, -) -> Tuple[dns.message.Message, float]: - """Read a DNS message from a TCP socket. - - *sock*, a ``dns.asyncbackend.StreamSocket``. - - See :py:func:`dns.query.receive_tcp()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - - ldata = await _read_exactly(sock, 2, expiration) - (l,) = struct.unpack("!H", ldata) - wire = await _read_exactly(sock, l, expiration) - received_time = time.time() - r = dns.message.from_wire( - wire, - keyring=keyring, - request_mac=request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - return (r, received_time) - - -async def tcp( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 53, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - sock: Optional[dns.asyncbackend.StreamSocket] = None, - backend: Optional[dns.asyncbackend.Backend] = None, -) -> dns.message.Message: - """Return the response obtained after sending a query via TCP. - - *sock*, a ``dns.asyncbacket.StreamSocket``, or ``None``, the - socket to use for the query. If ``None``, the default, a socket - is created. Note that if a socket is provided - *where*, *port*, *source*, *source_port*, and *backend* are ignored. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.query.tcp()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - - wire = q.to_wire() - (begin_time, expiration) = _compute_times(timeout) - if sock: - # Verify that the socket is connected, as if it's not connected, - # it's not writable, and the polling in send_tcp() will time out or - # hang forever. - await sock.getpeername() - cm: contextlib.AbstractAsyncContextManager = NullContext(sock) - else: - # These are simple (address, port) pairs, not family-dependent tuples - # you pass to low-level socket code. - af = dns.inet.af_for_address(where) - stuple = _source_tuple(af, source, source_port) - dtuple = (where, port) - if not backend: - backend = dns.asyncbackend.get_default_backend() - cm = await backend.make_socket( - af, socket.SOCK_STREAM, 0, stuple, dtuple, timeout - ) - async with cm as s: - await send_tcp(s, wire, expiration) - (r, received_time) = await receive_tcp( - s, expiration, one_rr_per_rrset, q.keyring, q.mac, ignore_trailing - ) - r.time = received_time - begin_time - if not q.is_response(r): - raise BadResponse - return r - - -async def tls( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 853, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - sock: Optional[dns.asyncbackend.StreamSocket] = None, - backend: Optional[dns.asyncbackend.Backend] = None, - ssl_context: Optional[ssl.SSLContext] = None, - server_hostname: Optional[str] = None, - verify: Union[bool, str] = True, -) -> dns.message.Message: - """Return the response obtained after sending a query via TLS. - - *sock*, an ``asyncbackend.StreamSocket``, or ``None``, the socket - to use for the query. If ``None``, the default, a socket is - created. Note that if a socket is provided, it must be a - connected SSL stream socket, and *where*, *port*, - *source*, *source_port*, *backend*, *ssl_context*, and *server_hostname* - are ignored. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.query.tls()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - (begin_time, expiration) = _compute_times(timeout) - if sock: - cm: contextlib.AbstractAsyncContextManager = NullContext(sock) - else: - if ssl_context is None: - ssl_context = _make_dot_ssl_context(server_hostname, verify) - af = dns.inet.af_for_address(where) - stuple = _source_tuple(af, source, source_port) - dtuple = (where, port) - if not backend: - backend = dns.asyncbackend.get_default_backend() - cm = await backend.make_socket( - af, - socket.SOCK_STREAM, - 0, - stuple, - dtuple, - timeout, - ssl_context, - server_hostname, - ) - async with cm as s: - timeout = _timeout(expiration) - response = await tcp( - q, - where, - timeout, - port, - source, - source_port, - one_rr_per_rrset, - ignore_trailing, - s, - backend, - ) - end_time = time.time() - response.time = end_time - begin_time - return response - - -def _maybe_get_resolver( - resolver: Optional["dns.asyncresolver.Resolver"], -) -> "dns.asyncresolver.Resolver": - # We need a separate method for this to avoid overriding the global - # variable "dns" with the as-yet undefined local variable "dns" - # in https(). - if resolver is None: - # pylint: disable=import-outside-toplevel,redefined-outer-name - import dns.asyncresolver - - resolver = dns.asyncresolver.Resolver() - return resolver - - -async def https( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 443, - source: Optional[str] = None, - source_port: int = 0, # pylint: disable=W0613 - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - client: Optional["httpx.AsyncClient"] = None, - path: str = "/dns-query", - post: bool = True, - verify: Union[bool, str] = True, - bootstrap_address: Optional[str] = None, - resolver: Optional["dns.asyncresolver.Resolver"] = None, - family: int = socket.AF_UNSPEC, - http_version: HTTPVersion = HTTPVersion.DEFAULT, -) -> dns.message.Message: - """Return the response obtained after sending a query via DNS-over-HTTPS. - - *client*, a ``httpx.AsyncClient``. If provided, the client to use for - the query. - - Unlike the other dnspython async functions, a backend cannot be provided - in this function because httpx always auto-detects the async backend. - - See :py:func:`dns.query.https()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - - try: - af = dns.inet.af_for_address(where) - except ValueError: - af = None - if af is not None and dns.inet.is_address(where): - if af == socket.AF_INET: - url = f"https://{where}:{port}{path}" - elif af == socket.AF_INET6: - url = f"https://[{where}]:{port}{path}" - else: - url = where - - extensions = {} - if bootstrap_address is None: - # pylint: disable=possibly-used-before-assignment - parsed = urllib.parse.urlparse(url) - if parsed.hostname is None: - raise ValueError("no hostname in URL") - if dns.inet.is_address(parsed.hostname): - bootstrap_address = parsed.hostname - extensions["sni_hostname"] = parsed.hostname - if parsed.port is not None: - port = parsed.port - - if http_version == HTTPVersion.H3 or ( - http_version == HTTPVersion.DEFAULT and not have_doh - ): - if bootstrap_address is None: - resolver = _maybe_get_resolver(resolver) - assert parsed.hostname is not None # for mypy - answers = await resolver.resolve_name(parsed.hostname, family) - bootstrap_address = random.choice(list(answers.addresses())) - return await _http3( - q, - bootstrap_address, - url, - timeout, - port, - source, - source_port, - one_rr_per_rrset, - ignore_trailing, - verify=verify, - post=post, - ) - - if not have_doh: - raise NoDOH # pragma: no cover - # pylint: disable=possibly-used-before-assignment - if client and not isinstance(client, httpx.AsyncClient): - raise ValueError("session parameter must be an httpx.AsyncClient") - # pylint: enable=possibly-used-before-assignment - - wire = q.to_wire() - headers = {"accept": "application/dns-message"} - - h1 = http_version in (HTTPVersion.H1, HTTPVersion.DEFAULT) - h2 = http_version in (HTTPVersion.H2, HTTPVersion.DEFAULT) - - backend = dns.asyncbackend.get_default_backend() - - if source is None: - local_address = None - local_port = 0 - else: - local_address = source - local_port = source_port - - if client: - cm: contextlib.AbstractAsyncContextManager = NullContext(client) - else: - transport = backend.get_transport_class()( - local_address=local_address, - http1=h1, - http2=h2, - verify=verify, - local_port=local_port, - bootstrap_address=bootstrap_address, - resolver=resolver, - family=family, - ) - - cm = httpx.AsyncClient(http1=h1, http2=h2, verify=verify, transport=transport) - - async with cm as the_client: - # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH - # GET and POST examples - if post: - headers.update( - { - "content-type": "application/dns-message", - "content-length": str(len(wire)), - } - ) - response = await backend.wait_for( - the_client.post( - url, - headers=headers, - content=wire, - extensions=extensions, - ), - timeout, - ) - else: - wire = base64.urlsafe_b64encode(wire).rstrip(b"=") - twire = wire.decode() # httpx does a repr() if we give it bytes - response = await backend.wait_for( - the_client.get( - url, - headers=headers, - params={"dns": twire}, - extensions=extensions, - ), - timeout, - ) - - # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH - # status codes - if response.status_code < 200 or response.status_code > 299: - raise ValueError( - f"{where} responded with status code {response.status_code}" - f"\nResponse body: {response.content!r}" - ) - r = dns.message.from_wire( - response.content, - keyring=q.keyring, - request_mac=q.request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - r.time = response.elapsed.total_seconds() - if not q.is_response(r): - raise BadResponse - return r - - -async def _http3( - q: dns.message.Message, - where: str, - url: str, - timeout: Optional[float] = None, - port: int = 853, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - verify: Union[bool, str] = True, - backend: Optional[dns.asyncbackend.Backend] = None, - hostname: Optional[str] = None, - post: bool = True, -) -> dns.message.Message: - if not dns.quic.have_quic: - raise NoDOH("DNS-over-HTTP3 is not available.") # pragma: no cover - - url_parts = urllib.parse.urlparse(url) - hostname = url_parts.hostname - if url_parts.port is not None: - port = url_parts.port - - q.id = 0 - wire = q.to_wire() - (cfactory, mfactory) = dns.quic.factories_for_backend(backend) - - async with cfactory() as context: - async with mfactory( - context, verify_mode=verify, server_name=hostname, h3=True - ) as the_manager: - the_connection = the_manager.connect(where, port, source, source_port) - (start, expiration) = _compute_times(timeout) - stream = await the_connection.make_stream(timeout) - async with stream: - # note that send_h3() does not need await - stream.send_h3(url, wire, post) - wire = await stream.receive(_remaining(expiration)) - _check_status(stream.headers(), where, wire) - finish = time.time() - r = dns.message.from_wire( - wire, - keyring=q.keyring, - request_mac=q.request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - r.time = max(finish - start, 0.0) - if not q.is_response(r): - raise BadResponse - return r - - -async def quic( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 853, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - connection: Optional[dns.quic.AsyncQuicConnection] = None, - verify: Union[bool, str] = True, - backend: Optional[dns.asyncbackend.Backend] = None, - hostname: Optional[str] = None, - server_hostname: Optional[str] = None, -) -> dns.message.Message: - """Return the response obtained after sending an asynchronous query via - DNS-over-QUIC. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.query.quic()` for the documentation of the other - parameters, exceptions, and return type of this method. - """ - - if not dns.quic.have_quic: - raise NoDOQ("DNS-over-QUIC is not available.") # pragma: no cover - - if server_hostname is not None and hostname is None: - hostname = server_hostname - - q.id = 0 - wire = q.to_wire() - the_connection: dns.quic.AsyncQuicConnection - if connection: - cfactory = dns.quic.null_factory - mfactory = dns.quic.null_factory - the_connection = connection - else: - (cfactory, mfactory) = dns.quic.factories_for_backend(backend) - - async with cfactory() as context: - async with mfactory( - context, - verify_mode=verify, - server_name=server_hostname, - ) as the_manager: - if not connection: - the_connection = the_manager.connect(where, port, source, source_port) - (start, expiration) = _compute_times(timeout) - stream = await the_connection.make_stream(timeout) - async with stream: - await stream.send(wire, True) - wire = await stream.receive(_remaining(expiration)) - finish = time.time() - r = dns.message.from_wire( - wire, - keyring=q.keyring, - request_mac=q.request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - r.time = max(finish - start, 0.0) - if not q.is_response(r): - raise BadResponse - return r - - -async def _inbound_xfr( - txn_manager: dns.transaction.TransactionManager, - s: dns.asyncbackend.Socket, - query: dns.message.Message, - serial: Optional[int], - timeout: Optional[float], - expiration: float, -) -> Any: - """Given a socket, does the zone transfer.""" - rdtype = query.question[0].rdtype - is_ixfr = rdtype == dns.rdatatype.IXFR - origin = txn_manager.from_wire_origin() - wire = query.to_wire() - is_udp = s.type == socket.SOCK_DGRAM - if is_udp: - udp_sock = cast(dns.asyncbackend.DatagramSocket, s) - await udp_sock.sendto(wire, None, _timeout(expiration)) - else: - tcp_sock = cast(dns.asyncbackend.StreamSocket, s) - tcpmsg = struct.pack("!H", len(wire)) + wire - await tcp_sock.sendall(tcpmsg, expiration) - with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound: - done = False - tsig_ctx = None - while not done: - (_, mexpiration) = _compute_times(timeout) - if mexpiration is None or ( - expiration is not None and mexpiration > expiration - ): - mexpiration = expiration - if is_udp: - timeout = _timeout(mexpiration) - (rwire, _) = await udp_sock.recvfrom(65535, timeout) - else: - ldata = await _read_exactly(tcp_sock, 2, mexpiration) - (l,) = struct.unpack("!H", ldata) - rwire = await _read_exactly(tcp_sock, l, mexpiration) - r = dns.message.from_wire( - rwire, - keyring=query.keyring, - request_mac=query.mac, - xfr=True, - origin=origin, - tsig_ctx=tsig_ctx, - multi=(not is_udp), - one_rr_per_rrset=is_ixfr, - ) - done = inbound.process_message(r) - yield r - tsig_ctx = r.tsig_ctx - if query.keyring and not r.had_tsig: - raise dns.exception.FormError("missing TSIG") - - -async def inbound_xfr( - where: str, - txn_manager: dns.transaction.TransactionManager, - query: Optional[dns.message.Message] = None, - port: int = 53, - timeout: Optional[float] = None, - lifetime: Optional[float] = None, - source: Optional[str] = None, - source_port: int = 0, - udp_mode: UDPMode = UDPMode.NEVER, - backend: Optional[dns.asyncbackend.Backend] = None, -) -> None: - """Conduct an inbound transfer and apply it via a transaction from the - txn_manager. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.query.inbound_xfr()` for the documentation of - the other parameters, exceptions, and return type of this method. - """ - if query is None: - (query, serial) = dns.xfr.make_query(txn_manager) - else: - serial = dns.xfr.extract_serial_from_query(query) - af = dns.inet.af_for_address(where) - stuple = _source_tuple(af, source, source_port) - dtuple = (where, port) - if not backend: - backend = dns.asyncbackend.get_default_backend() - (_, expiration) = _compute_times(lifetime) - if query.question[0].rdtype == dns.rdatatype.IXFR and udp_mode != UDPMode.NEVER: - s = await backend.make_socket( - af, socket.SOCK_DGRAM, 0, stuple, dtuple, _timeout(expiration) - ) - async with s: - try: - async for _ in _inbound_xfr( - txn_manager, s, query, serial, timeout, expiration - ): - pass - return - except dns.xfr.UseTCP: - if udp_mode == UDPMode.ONLY: - raise - - s = await backend.make_socket( - af, socket.SOCK_STREAM, 0, stuple, dtuple, _timeout(expiration) - ) - async with s: - async for _ in _inbound_xfr(txn_manager, s, query, serial, timeout, expiration): - pass diff --git a/venv/Lib/site-packages/dns/asyncresolver.py b/venv/Lib/site-packages/dns/asyncresolver.py deleted file mode 100644 index 8f5e062..0000000 --- a/venv/Lib/site-packages/dns/asyncresolver.py +++ /dev/null @@ -1,475 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Asynchronous DNS stub resolver.""" - -import socket -import time -from typing import Any, Dict, List, Optional, Union - -import dns._ddr -import dns.asyncbackend -import dns.asyncquery -import dns.exception -import dns.name -import dns.query -import dns.rdataclass -import dns.rdatatype -import dns.resolver # lgtm[py/import-and-import-from] - -# import some resolver symbols for brevity -from dns.resolver import NXDOMAIN, NoAnswer, NoRootSOA, NotAbsolute - -# for indentation purposes below -_udp = dns.asyncquery.udp -_tcp = dns.asyncquery.tcp - - -class Resolver(dns.resolver.BaseResolver): - """Asynchronous DNS stub resolver.""" - - async def resolve( - self, - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - search: Optional[bool] = None, - backend: Optional[dns.asyncbackend.Backend] = None, - ) -> dns.resolver.Answer: - """Query nameservers asynchronously to find the answer to the question. - - *backend*, a ``dns.asyncbackend.Backend``, or ``None``. If ``None``, - the default, then dnspython will use the default backend. - - See :py:func:`dns.resolver.Resolver.resolve()` for the - documentation of the other parameters, exceptions, and return - type of this method. - """ - - resolution = dns.resolver._Resolution( - self, qname, rdtype, rdclass, tcp, raise_on_no_answer, search - ) - if not backend: - backend = dns.asyncbackend.get_default_backend() - start = time.time() - while True: - (request, answer) = resolution.next_request() - # Note we need to say "if answer is not None" and not just - # "if answer" because answer implements __len__, and python - # will call that. We want to return if we have an answer - # object, including in cases where its length is 0. - if answer is not None: - # cache hit! - return answer - assert request is not None # needed for type checking - done = False - while not done: - (nameserver, tcp, backoff) = resolution.next_nameserver() - if backoff: - await backend.sleep(backoff) - timeout = self._compute_timeout(start, lifetime, resolution.errors) - try: - response = await nameserver.async_query( - request, - timeout=timeout, - source=source, - source_port=source_port, - max_size=tcp, - backend=backend, - ) - except Exception as ex: - (_, done) = resolution.query_result(None, ex) - continue - (answer, done) = resolution.query_result(response, None) - # Note we need to say "if answer is not None" and not just - # "if answer" because answer implements __len__, and python - # will call that. We want to return if we have an answer - # object, including in cases where its length is 0. - if answer is not None: - return answer - - async def resolve_address( - self, ipaddr: str, *args: Any, **kwargs: Any - ) -> dns.resolver.Answer: - """Use an asynchronous resolver to run a reverse query for PTR - records. - - This utilizes the resolve() method to perform a PTR lookup on the - specified IP address. - - *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get - the PTR record for. - - All other arguments that can be passed to the resolve() function - except for rdtype and rdclass are also supported by this - function. - - """ - # We make a modified kwargs for type checking happiness, as otherwise - # we get a legit warning about possibly having rdtype and rdclass - # in the kwargs more than once. - modified_kwargs: Dict[str, Any] = {} - modified_kwargs.update(kwargs) - modified_kwargs["rdtype"] = dns.rdatatype.PTR - modified_kwargs["rdclass"] = dns.rdataclass.IN - return await self.resolve( - dns.reversename.from_address(ipaddr), *args, **modified_kwargs - ) - - async def resolve_name( - self, - name: Union[dns.name.Name, str], - family: int = socket.AF_UNSPEC, - **kwargs: Any, - ) -> dns.resolver.HostAnswers: - """Use an asynchronous resolver to query for address records. - - This utilizes the resolve() method to perform A and/or AAAA lookups on - the specified name. - - *qname*, a ``dns.name.Name`` or ``str``, the name to resolve. - - *family*, an ``int``, the address family. If socket.AF_UNSPEC - (the default), both A and AAAA records will be retrieved. - - All other arguments that can be passed to the resolve() function - except for rdtype and rdclass are also supported by this - function. - """ - # We make a modified kwargs for type checking happiness, as otherwise - # we get a legit warning about possibly having rdtype and rdclass - # in the kwargs more than once. - modified_kwargs: Dict[str, Any] = {} - modified_kwargs.update(kwargs) - modified_kwargs.pop("rdtype", None) - modified_kwargs["rdclass"] = dns.rdataclass.IN - - if family == socket.AF_INET: - v4 = await self.resolve(name, dns.rdatatype.A, **modified_kwargs) - return dns.resolver.HostAnswers.make(v4=v4) - elif family == socket.AF_INET6: - v6 = await self.resolve(name, dns.rdatatype.AAAA, **modified_kwargs) - return dns.resolver.HostAnswers.make(v6=v6) - elif family != socket.AF_UNSPEC: - raise NotImplementedError(f"unknown address family {family}") - - raise_on_no_answer = modified_kwargs.pop("raise_on_no_answer", True) - lifetime = modified_kwargs.pop("lifetime", None) - start = time.time() - v6 = await self.resolve( - name, - dns.rdatatype.AAAA, - raise_on_no_answer=False, - lifetime=self._compute_timeout(start, lifetime), - **modified_kwargs, - ) - # Note that setting name ensures we query the same name - # for A as we did for AAAA. (This is just in case search lists - # are active by default in the resolver configuration and - # we might be talking to a server that says NXDOMAIN when it - # wants to say NOERROR no data. - name = v6.qname - v4 = await self.resolve( - name, - dns.rdatatype.A, - raise_on_no_answer=False, - lifetime=self._compute_timeout(start, lifetime), - **modified_kwargs, - ) - answers = dns.resolver.HostAnswers.make( - v6=v6, v4=v4, add_empty=not raise_on_no_answer - ) - if not answers: - raise NoAnswer(response=v6.response) - return answers - - # pylint: disable=redefined-outer-name - - async def canonical_name(self, name: Union[dns.name.Name, str]) -> dns.name.Name: - """Determine the canonical name of *name*. - - The canonical name is the name the resolver uses for queries - after all CNAME and DNAME renamings have been applied. - - *name*, a ``dns.name.Name`` or ``str``, the query name. - - This method can raise any exception that ``resolve()`` can - raise, other than ``dns.resolver.NoAnswer`` and - ``dns.resolver.NXDOMAIN``. - - Returns a ``dns.name.Name``. - """ - try: - answer = await self.resolve(name, raise_on_no_answer=False) - canonical_name = answer.canonical_name - except dns.resolver.NXDOMAIN as e: - canonical_name = e.canonical_name - return canonical_name - - async def try_ddr(self, lifetime: float = 5.0) -> None: - """Try to update the resolver's nameservers using Discovery of Designated - Resolvers (DDR). If successful, the resolver will subsequently use - DNS-over-HTTPS or DNS-over-TLS for future queries. - - *lifetime*, a float, is the maximum time to spend attempting DDR. The default - is 5 seconds. - - If the SVCB query is successful and results in a non-empty list of nameservers, - then the resolver's nameservers are set to the returned servers in priority - order. - - The current implementation does not use any address hints from the SVCB record, - nor does it resolve addresses for the SCVB target name, rather it assumes that - the bootstrap nameserver will always be one of the addresses and uses it. - A future revision to the code may offer fuller support. The code verifies that - the bootstrap nameserver is in the Subject Alternative Name field of the - TLS certficate. - """ - try: - expiration = time.time() + lifetime - answer = await self.resolve( - dns._ddr._local_resolver_name, "svcb", lifetime=lifetime - ) - timeout = dns.query._remaining(expiration) - nameservers = await dns._ddr._get_nameservers_async(answer, timeout) - if len(nameservers) > 0: - self.nameservers = nameservers - except Exception: - pass - - -default_resolver = None - - -def get_default_resolver() -> Resolver: - """Get the default asynchronous resolver, initializing it if necessary.""" - if default_resolver is None: - reset_default_resolver() - assert default_resolver is not None - return default_resolver - - -def reset_default_resolver() -> None: - """Re-initialize default asynchronous resolver. - - Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX - systems) will be re-read immediately. - """ - - global default_resolver - default_resolver = Resolver() - - -async def resolve( - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - search: Optional[bool] = None, - backend: Optional[dns.asyncbackend.Backend] = None, -) -> dns.resolver.Answer: - """Query nameservers asynchronously to find the answer to the question. - - This is a convenience function that uses the default resolver - object to make the query. - - See :py:func:`dns.asyncresolver.Resolver.resolve` for more - information on the parameters. - """ - - return await get_default_resolver().resolve( - qname, - rdtype, - rdclass, - tcp, - source, - raise_on_no_answer, - source_port, - lifetime, - search, - backend, - ) - - -async def resolve_address( - ipaddr: str, *args: Any, **kwargs: Any -) -> dns.resolver.Answer: - """Use a resolver to run a reverse query for PTR records. - - See :py:func:`dns.asyncresolver.Resolver.resolve_address` for more - information on the parameters. - """ - - return await get_default_resolver().resolve_address(ipaddr, *args, **kwargs) - - -async def resolve_name( - name: Union[dns.name.Name, str], family: int = socket.AF_UNSPEC, **kwargs: Any -) -> dns.resolver.HostAnswers: - """Use a resolver to asynchronously query for address records. - - See :py:func:`dns.asyncresolver.Resolver.resolve_name` for more - information on the parameters. - """ - - return await get_default_resolver().resolve_name(name, family, **kwargs) - - -async def canonical_name(name: Union[dns.name.Name, str]) -> dns.name.Name: - """Determine the canonical name of *name*. - - See :py:func:`dns.resolver.Resolver.canonical_name` for more - information on the parameters and possible exceptions. - """ - - return await get_default_resolver().canonical_name(name) - - -async def try_ddr(timeout: float = 5.0) -> None: - """Try to update the default resolver's nameservers using Discovery of Designated - Resolvers (DDR). If successful, the resolver will subsequently use - DNS-over-HTTPS or DNS-over-TLS for future queries. - - See :py:func:`dns.resolver.Resolver.try_ddr` for more information. - """ - return await get_default_resolver().try_ddr(timeout) - - -async def zone_for_name( - name: Union[dns.name.Name, str], - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - tcp: bool = False, - resolver: Optional[Resolver] = None, - backend: Optional[dns.asyncbackend.Backend] = None, -) -> dns.name.Name: - """Find the name of the zone which contains the specified name. - - See :py:func:`dns.resolver.Resolver.zone_for_name` for more - information on the parameters and possible exceptions. - """ - - if isinstance(name, str): - name = dns.name.from_text(name, dns.name.root) - if resolver is None: - resolver = get_default_resolver() - if not name.is_absolute(): - raise NotAbsolute(name) - while True: - try: - answer = await resolver.resolve( - name, dns.rdatatype.SOA, rdclass, tcp, backend=backend - ) - assert answer.rrset is not None - if answer.rrset.name == name: - return name - # otherwise we were CNAMEd or DNAMEd and need to look higher - except (NXDOMAIN, NoAnswer): - pass - try: - name = name.parent() - except dns.name.NoParent: # pragma: no cover - raise NoRootSOA - - -async def make_resolver_at( - where: Union[dns.name.Name, str], - port: int = 53, - family: int = socket.AF_UNSPEC, - resolver: Optional[Resolver] = None, -) -> Resolver: - """Make a stub resolver using the specified destination as the full resolver. - - *where*, a ``dns.name.Name`` or ``str`` the domain name or IP address of the - full resolver. - - *port*, an ``int``, the port to use. If not specified, the default is 53. - - *family*, an ``int``, the address family to use. This parameter is used if - *where* is not an address. The default is ``socket.AF_UNSPEC`` in which case - the first address returned by ``resolve_name()`` will be used, otherwise the - first address of the specified family will be used. - - *resolver*, a ``dns.asyncresolver.Resolver`` or ``None``, the resolver to use for - resolution of hostnames. If not specified, the default resolver will be used. - - Returns a ``dns.resolver.Resolver`` or raises an exception. - """ - if resolver is None: - resolver = get_default_resolver() - nameservers: List[Union[str, dns.nameserver.Nameserver]] = [] - if isinstance(where, str) and dns.inet.is_address(where): - nameservers.append(dns.nameserver.Do53Nameserver(where, port)) - else: - answers = await resolver.resolve_name(where, family) - for address in answers.addresses(): - nameservers.append(dns.nameserver.Do53Nameserver(address, port)) - res = dns.asyncresolver.Resolver(configure=False) - res.nameservers = nameservers - return res - - -async def resolve_at( - where: Union[dns.name.Name, str], - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - search: Optional[bool] = None, - backend: Optional[dns.asyncbackend.Backend] = None, - port: int = 53, - family: int = socket.AF_UNSPEC, - resolver: Optional[Resolver] = None, -) -> dns.resolver.Answer: - """Query nameservers to find the answer to the question. - - This is a convenience function that calls ``dns.asyncresolver.make_resolver_at()`` - to make a resolver, and then uses it to resolve the query. - - See ``dns.asyncresolver.Resolver.resolve`` for more information on the resolution - parameters, and ``dns.asyncresolver.make_resolver_at`` for information about the - resolver parameters *where*, *port*, *family*, and *resolver*. - - If making more than one query, it is more efficient to call - ``dns.asyncresolver.make_resolver_at()`` and then use that resolver for the queries - instead of calling ``resolve_at()`` multiple times. - """ - res = await make_resolver_at(where, port, family, resolver) - return await res.resolve( - qname, - rdtype, - rdclass, - tcp, - source, - raise_on_no_answer, - source_port, - lifetime, - search, - backend, - ) diff --git a/venv/Lib/site-packages/dns/dnssec.py b/venv/Lib/site-packages/dns/dnssec.py deleted file mode 100644 index b69d0a1..0000000 --- a/venv/Lib/site-packages/dns/dnssec.py +++ /dev/null @@ -1,1247 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Common DNSSEC-related functions and constants.""" - - -import base64 -import contextlib -import functools -import hashlib -import struct -import time -from datetime import datetime -from typing import Callable, Dict, List, Optional, Set, Tuple, Union, cast - -import dns._features -import dns.exception -import dns.name -import dns.node -import dns.rdata -import dns.rdataclass -import dns.rdataset -import dns.rdatatype -import dns.rrset -import dns.transaction -import dns.zone -from dns.dnssectypes import Algorithm, DSDigest, NSEC3Hash -from dns.exception import ( # pylint: disable=W0611 - AlgorithmKeyMismatch, - DeniedByPolicy, - UnsupportedAlgorithm, - ValidationFailure, -) -from dns.rdtypes.ANY.CDNSKEY import CDNSKEY -from dns.rdtypes.ANY.CDS import CDS -from dns.rdtypes.ANY.DNSKEY import DNSKEY -from dns.rdtypes.ANY.DS import DS -from dns.rdtypes.ANY.NSEC import NSEC, Bitmap -from dns.rdtypes.ANY.NSEC3PARAM import NSEC3PARAM -from dns.rdtypes.ANY.RRSIG import RRSIG, sigtime_to_posixtime -from dns.rdtypes.dnskeybase import Flag - -PublicKey = Union[ - "GenericPublicKey", - "rsa.RSAPublicKey", - "ec.EllipticCurvePublicKey", - "ed25519.Ed25519PublicKey", - "ed448.Ed448PublicKey", -] - -PrivateKey = Union[ - "GenericPrivateKey", - "rsa.RSAPrivateKey", - "ec.EllipticCurvePrivateKey", - "ed25519.Ed25519PrivateKey", - "ed448.Ed448PrivateKey", -] - -RRsetSigner = Callable[[dns.transaction.Transaction, dns.rrset.RRset], None] - - -def algorithm_from_text(text: str) -> Algorithm: - """Convert text into a DNSSEC algorithm value. - - *text*, a ``str``, the text to convert to into an algorithm value. - - Returns an ``int``. - """ - - return Algorithm.from_text(text) - - -def algorithm_to_text(value: Union[Algorithm, int]) -> str: - """Convert a DNSSEC algorithm value to text - - *value*, a ``dns.dnssec.Algorithm``. - - Returns a ``str``, the name of a DNSSEC algorithm. - """ - - return Algorithm.to_text(value) - - -def to_timestamp(value: Union[datetime, str, float, int]) -> int: - """Convert various format to a timestamp""" - if isinstance(value, datetime): - return int(value.timestamp()) - elif isinstance(value, str): - return sigtime_to_posixtime(value) - elif isinstance(value, float): - return int(value) - elif isinstance(value, int): - return value - else: - raise TypeError("Unsupported timestamp type") - - -def key_id(key: Union[DNSKEY, CDNSKEY]) -> int: - """Return the key id (a 16-bit number) for the specified key. - - *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY`` - - Returns an ``int`` between 0 and 65535 - """ - - rdata = key.to_wire() - assert rdata is not None # for mypy - if key.algorithm == Algorithm.RSAMD5: - return (rdata[-3] << 8) + rdata[-2] - else: - total = 0 - for i in range(len(rdata) // 2): - total += (rdata[2 * i] << 8) + rdata[2 * i + 1] - if len(rdata) % 2 != 0: - total += rdata[len(rdata) - 1] << 8 - total += (total >> 16) & 0xFFFF - return total & 0xFFFF - - -class Policy: - def __init__(self): - pass - - def ok_to_sign(self, _: DNSKEY) -> bool: # pragma: no cover - return False - - def ok_to_validate(self, _: DNSKEY) -> bool: # pragma: no cover - return False - - def ok_to_create_ds(self, _: DSDigest) -> bool: # pragma: no cover - return False - - def ok_to_validate_ds(self, _: DSDigest) -> bool: # pragma: no cover - return False - - -class SimpleDeny(Policy): - def __init__(self, deny_sign, deny_validate, deny_create_ds, deny_validate_ds): - super().__init__() - self._deny_sign = deny_sign - self._deny_validate = deny_validate - self._deny_create_ds = deny_create_ds - self._deny_validate_ds = deny_validate_ds - - def ok_to_sign(self, key: DNSKEY) -> bool: - return key.algorithm not in self._deny_sign - - def ok_to_validate(self, key: DNSKEY) -> bool: - return key.algorithm not in self._deny_validate - - def ok_to_create_ds(self, algorithm: DSDigest) -> bool: - return algorithm not in self._deny_create_ds - - def ok_to_validate_ds(self, algorithm: DSDigest) -> bool: - return algorithm not in self._deny_validate_ds - - -rfc_8624_policy = SimpleDeny( - {Algorithm.RSAMD5, Algorithm.DSA, Algorithm.DSANSEC3SHA1, Algorithm.ECCGOST}, - {Algorithm.RSAMD5, Algorithm.DSA, Algorithm.DSANSEC3SHA1}, - {DSDigest.NULL, DSDigest.SHA1, DSDigest.GOST}, - {DSDigest.NULL}, -) - -allow_all_policy = SimpleDeny(set(), set(), set(), set()) - - -default_policy = rfc_8624_policy - - -def make_ds( - name: Union[dns.name.Name, str], - key: dns.rdata.Rdata, - algorithm: Union[DSDigest, str], - origin: Optional[dns.name.Name] = None, - policy: Optional[Policy] = None, - validating: bool = False, -) -> DS: - """Create a DS record for a DNSSEC key. - - *name*, a ``dns.name.Name`` or ``str``, the owner name of the DS record. - - *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY`` or ``dns.rdtypes.ANY.DNSKEY.CDNSKEY``, - the key the DS is about. - - *algorithm*, a ``str`` or ``int`` specifying the hash algorithm. - The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case - does not matter for these strings. - - *origin*, a ``dns.name.Name`` or ``None``. If *key* is a relative name, - then it will be made absolute using the specified origin. - - *policy*, a ``dns.dnssec.Policy`` or ``None``. If ``None``, the default policy, - ``dns.dnssec.default_policy`` is used; this policy defaults to that of RFC 8624. - - *validating*, a ``bool``. If ``True``, then policy is checked in - validating mode, i.e. "Is it ok to validate using this digest algorithm?". - Otherwise the policy is checked in creating mode, i.e. "Is it ok to create a DS with - this digest algorithm?". - - Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. - - Raises ``DeniedByPolicy`` if the algorithm is denied by policy. - - Returns a ``dns.rdtypes.ANY.DS.DS`` - """ - - if policy is None: - policy = default_policy - try: - if isinstance(algorithm, str): - algorithm = DSDigest[algorithm.upper()] - except Exception: - raise UnsupportedAlgorithm(f'unsupported algorithm "{algorithm}"') - if validating: - check = policy.ok_to_validate_ds - else: - check = policy.ok_to_create_ds - if not check(algorithm): - raise DeniedByPolicy - if not isinstance(key, (DNSKEY, CDNSKEY)): - raise ValueError("key is not a DNSKEY/CDNSKEY") - if algorithm == DSDigest.SHA1: - dshash = hashlib.sha1() - elif algorithm == DSDigest.SHA256: - dshash = hashlib.sha256() - elif algorithm == DSDigest.SHA384: - dshash = hashlib.sha384() - else: - raise UnsupportedAlgorithm(f'unsupported algorithm "{algorithm}"') - - if isinstance(name, str): - name = dns.name.from_text(name, origin) - wire = name.canonicalize().to_wire() - kwire = key.to_wire(origin=origin) - assert wire is not None and kwire is not None # for mypy - dshash.update(wire) - dshash.update(kwire) - digest = dshash.digest() - - dsrdata = struct.pack("!HBB", key_id(key), key.algorithm, algorithm) + digest - ds = dns.rdata.from_wire( - dns.rdataclass.IN, dns.rdatatype.DS, dsrdata, 0, len(dsrdata) - ) - return cast(DS, ds) - - -def make_cds( - name: Union[dns.name.Name, str], - key: dns.rdata.Rdata, - algorithm: Union[DSDigest, str], - origin: Optional[dns.name.Name] = None, -) -> CDS: - """Create a CDS record for a DNSSEC key. - - *name*, a ``dns.name.Name`` or ``str``, the owner name of the DS record. - - *key*, a ``dns.rdtypes.ANY.DNSKEY.DNSKEY`` or ``dns.rdtypes.ANY.DNSKEY.CDNSKEY``, - the key the DS is about. - - *algorithm*, a ``str`` or ``int`` specifying the hash algorithm. - The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case - does not matter for these strings. - - *origin*, a ``dns.name.Name`` or ``None``. If *key* is a relative name, - then it will be made absolute using the specified origin. - - Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. - - Returns a ``dns.rdtypes.ANY.DS.CDS`` - """ - - ds = make_ds(name, key, algorithm, origin) - return CDS( - rdclass=ds.rdclass, - rdtype=dns.rdatatype.CDS, - key_tag=ds.key_tag, - algorithm=ds.algorithm, - digest_type=ds.digest_type, - digest=ds.digest, - ) - - -def _find_candidate_keys( - keys: Dict[dns.name.Name, Union[dns.rdataset.Rdataset, dns.node.Node]], rrsig: RRSIG -) -> Optional[List[DNSKEY]]: - value = keys.get(rrsig.signer) - if isinstance(value, dns.node.Node): - rdataset = value.get_rdataset(dns.rdataclass.IN, dns.rdatatype.DNSKEY) - else: - rdataset = value - if rdataset is None: - return None - return [ - cast(DNSKEY, rd) - for rd in rdataset - if rd.algorithm == rrsig.algorithm - and key_id(rd) == rrsig.key_tag - and (rd.flags & Flag.ZONE) == Flag.ZONE # RFC 4034 2.1.1 - and rd.protocol == 3 # RFC 4034 2.1.2 - ] - - -def _get_rrname_rdataset( - rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], -) -> Tuple[dns.name.Name, dns.rdataset.Rdataset]: - if isinstance(rrset, tuple): - return rrset[0], rrset[1] - else: - return rrset.name, rrset - - -def _validate_signature(sig: bytes, data: bytes, key: DNSKEY) -> None: - # pylint: disable=possibly-used-before-assignment - public_cls = get_algorithm_cls_from_dnskey(key).public_cls - try: - public_key = public_cls.from_dnskey(key) - except ValueError: - raise ValidationFailure("invalid public key") - public_key.verify(sig, data) - - -def _validate_rrsig( - rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], - rrsig: RRSIG, - keys: Dict[dns.name.Name, Union[dns.node.Node, dns.rdataset.Rdataset]], - origin: Optional[dns.name.Name] = None, - now: Optional[float] = None, - policy: Optional[Policy] = None, -) -> None: - """Validate an RRset against a single signature rdata, throwing an - exception if validation is not successful. - - *rrset*, the RRset to validate. This can be a - ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) - tuple. - - *rrsig*, a ``dns.rdata.Rdata``, the signature to validate. - - *keys*, the key dictionary, used to find the DNSKEY associated - with a given name. The dictionary is keyed by a - ``dns.name.Name``, and has ``dns.node.Node`` or - ``dns.rdataset.Rdataset`` values. - - *origin*, a ``dns.name.Name`` or ``None``, the origin to use for relative - names. - - *now*, a ``float`` or ``None``, the time, in seconds since the epoch, to - use as the current time when validating. If ``None``, the actual current - time is used. - - *policy*, a ``dns.dnssec.Policy`` or ``None``. If ``None``, the default policy, - ``dns.dnssec.default_policy`` is used; this policy defaults to that of RFC 8624. - - Raises ``ValidationFailure`` if the signature is expired, not yet valid, - the public key is invalid, the algorithm is unknown, the verification - fails, etc. - - Raises ``UnsupportedAlgorithm`` if the algorithm is recognized by - dnspython but not implemented. - """ - - if policy is None: - policy = default_policy - - candidate_keys = _find_candidate_keys(keys, rrsig) - if candidate_keys is None: - raise ValidationFailure("unknown key") - - if now is None: - now = time.time() - if rrsig.expiration < now: - raise ValidationFailure("expired") - if rrsig.inception > now: - raise ValidationFailure("not yet valid") - - data = _make_rrsig_signature_data(rrset, rrsig, origin) - - # pylint: disable=possibly-used-before-assignment - for candidate_key in candidate_keys: - if not policy.ok_to_validate(candidate_key): - continue - try: - _validate_signature(rrsig.signature, data, candidate_key) - return - except (InvalidSignature, ValidationFailure): - # this happens on an individual validation failure - continue - # nothing verified -- raise failure: - raise ValidationFailure("verify failure") - - -def _validate( - rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], - rrsigset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], - keys: Dict[dns.name.Name, Union[dns.node.Node, dns.rdataset.Rdataset]], - origin: Optional[dns.name.Name] = None, - now: Optional[float] = None, - policy: Optional[Policy] = None, -) -> None: - """Validate an RRset against a signature RRset, throwing an exception - if none of the signatures validate. - - *rrset*, the RRset to validate. This can be a - ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) - tuple. - - *rrsigset*, the signature RRset. This can be a - ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) - tuple. - - *keys*, the key dictionary, used to find the DNSKEY associated - with a given name. The dictionary is keyed by a - ``dns.name.Name``, and has ``dns.node.Node`` or - ``dns.rdataset.Rdataset`` values. - - *origin*, a ``dns.name.Name``, the origin to use for relative names; - defaults to None. - - *now*, an ``int`` or ``None``, the time, in seconds since the epoch, to - use as the current time when validating. If ``None``, the actual current - time is used. - - *policy*, a ``dns.dnssec.Policy`` or ``None``. If ``None``, the default policy, - ``dns.dnssec.default_policy`` is used; this policy defaults to that of RFC 8624. - - Raises ``ValidationFailure`` if the signature is expired, not yet valid, - the public key is invalid, the algorithm is unknown, the verification - fails, etc. - """ - - if policy is None: - policy = default_policy - - if isinstance(origin, str): - origin = dns.name.from_text(origin, dns.name.root) - - if isinstance(rrset, tuple): - rrname = rrset[0] - else: - rrname = rrset.name - - if isinstance(rrsigset, tuple): - rrsigname = rrsigset[0] - rrsigrdataset = rrsigset[1] - else: - rrsigname = rrsigset.name - rrsigrdataset = rrsigset - - rrname = rrname.choose_relativity(origin) - rrsigname = rrsigname.choose_relativity(origin) - if rrname != rrsigname: - raise ValidationFailure("owner names do not match") - - for rrsig in rrsigrdataset: - if not isinstance(rrsig, RRSIG): - raise ValidationFailure("expected an RRSIG") - try: - _validate_rrsig(rrset, rrsig, keys, origin, now, policy) - return - except (ValidationFailure, UnsupportedAlgorithm): - pass - raise ValidationFailure("no RRSIGs validated") - - -def _sign( - rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], - private_key: PrivateKey, - signer: dns.name.Name, - dnskey: DNSKEY, - inception: Optional[Union[datetime, str, int, float]] = None, - expiration: Optional[Union[datetime, str, int, float]] = None, - lifetime: Optional[int] = None, - verify: bool = False, - policy: Optional[Policy] = None, - origin: Optional[dns.name.Name] = None, - deterministic: bool = True, -) -> RRSIG: - """Sign RRset using private key. - - *rrset*, the RRset to validate. This can be a - ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) - tuple. - - *private_key*, the private key to use for signing, a - ``cryptography.hazmat.primitives.asymmetric`` private key class applicable - for DNSSEC. - - *signer*, a ``dns.name.Name``, the Signer's name. - - *dnskey*, a ``DNSKEY`` matching ``private_key``. - - *inception*, a ``datetime``, ``str``, ``int``, ``float`` or ``None``, the - signature inception time. If ``None``, the current time is used. If a ``str``, the - format is "YYYYMMDDHHMMSS" or alternatively the number of seconds since the UNIX - epoch in text form; this is the same the RRSIG rdata's text form. - Values of type `int` or `float` are interpreted as seconds since the UNIX epoch. - - *expiration*, a ``datetime``, ``str``, ``int``, ``float`` or ``None``, the signature - expiration time. If ``None``, the expiration time will be the inception time plus - the value of the *lifetime* parameter. See the description of *inception* above - for how the various parameter types are interpreted. - - *lifetime*, an ``int`` or ``None``, the signature lifetime in seconds. This - parameter is only meaningful if *expiration* is ``None``. - - *verify*, a ``bool``. If set to ``True``, the signer will verify signatures - after they are created; the default is ``False``. - - *policy*, a ``dns.dnssec.Policy`` or ``None``. If ``None``, the default policy, - ``dns.dnssec.default_policy`` is used; this policy defaults to that of RFC 8624. - - *origin*, a ``dns.name.Name`` or ``None``. If ``None``, the default, then all - names in the rrset (including its owner name) must be absolute; otherwise the - specified origin will be used to make names absolute when signing. - - *deterministic*, a ``bool``. If ``True``, the default, use deterministic - (reproducible) signatures when supported by the algorithm used for signing. - Currently, this only affects ECDSA. - - Raises ``DeniedByPolicy`` if the signature is denied by policy. - """ - - if policy is None: - policy = default_policy - if not policy.ok_to_sign(dnskey): - raise DeniedByPolicy - - if isinstance(rrset, tuple): - rdclass = rrset[1].rdclass - rdtype = rrset[1].rdtype - rrname = rrset[0] - original_ttl = rrset[1].ttl - else: - rdclass = rrset.rdclass - rdtype = rrset.rdtype - rrname = rrset.name - original_ttl = rrset.ttl - - if inception is not None: - rrsig_inception = to_timestamp(inception) - else: - rrsig_inception = int(time.time()) - - if expiration is not None: - rrsig_expiration = to_timestamp(expiration) - elif lifetime is not None: - rrsig_expiration = rrsig_inception + lifetime - else: - raise ValueError("expiration or lifetime must be specified") - - # Derelativize now because we need a correct labels length for the - # rrsig_template. - if origin is not None: - rrname = rrname.derelativize(origin) - labels = len(rrname) - 1 - - # Adjust labels appropriately for wildcards. - if rrname.is_wild(): - labels -= 1 - - rrsig_template = RRSIG( - rdclass=rdclass, - rdtype=dns.rdatatype.RRSIG, - type_covered=rdtype, - algorithm=dnskey.algorithm, - labels=labels, - original_ttl=original_ttl, - expiration=rrsig_expiration, - inception=rrsig_inception, - key_tag=key_id(dnskey), - signer=signer, - signature=b"", - ) - - data = dns.dnssec._make_rrsig_signature_data(rrset, rrsig_template, origin) - - # pylint: disable=possibly-used-before-assignment - if isinstance(private_key, GenericPrivateKey): - signing_key = private_key - else: - try: - private_cls = get_algorithm_cls_from_dnskey(dnskey) - signing_key = private_cls(key=private_key) - except UnsupportedAlgorithm: - raise TypeError("Unsupported key algorithm") - - signature = signing_key.sign(data, verify, deterministic) - - return cast(RRSIG, rrsig_template.replace(signature=signature)) - - -def _make_rrsig_signature_data( - rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], - rrsig: RRSIG, - origin: Optional[dns.name.Name] = None, -) -> bytes: - """Create signature rdata. - - *rrset*, the RRset to sign/validate. This can be a - ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) - tuple. - - *rrsig*, a ``dns.rdata.Rdata``, the signature to validate, or the - signature template used when signing. - - *origin*, a ``dns.name.Name`` or ``None``, the origin to use for relative - names. - - Raises ``UnsupportedAlgorithm`` if the algorithm is recognized by - dnspython but not implemented. - """ - - if isinstance(origin, str): - origin = dns.name.from_text(origin, dns.name.root) - - signer = rrsig.signer - if not signer.is_absolute(): - if origin is None: - raise ValidationFailure("relative RR name without an origin specified") - signer = signer.derelativize(origin) - - # For convenience, allow the rrset to be specified as a (name, - # rdataset) tuple as well as a proper rrset - rrname, rdataset = _get_rrname_rdataset(rrset) - - data = b"" - wire = rrsig.to_wire(origin=signer) - assert wire is not None # for mypy - data += wire[:18] - data += rrsig.signer.to_digestable(signer) - - # Derelativize the name before considering labels. - if not rrname.is_absolute(): - if origin is None: - raise ValidationFailure("relative RR name without an origin specified") - rrname = rrname.derelativize(origin) - - name_len = len(rrname) - if rrname.is_wild() and rrsig.labels != name_len - 2: - raise ValidationFailure("wild owner name has wrong label length") - if name_len - 1 < rrsig.labels: - raise ValidationFailure("owner name longer than RRSIG labels") - elif rrsig.labels < name_len - 1: - suffix = rrname.split(rrsig.labels + 1)[1] - rrname = dns.name.from_text("*", suffix) - rrnamebuf = rrname.to_digestable() - rrfixed = struct.pack("!HHI", rdataset.rdtype, rdataset.rdclass, rrsig.original_ttl) - rdatas = [rdata.to_digestable(origin) for rdata in rdataset] - for rdata in sorted(rdatas): - data += rrnamebuf - data += rrfixed - rrlen = struct.pack("!H", len(rdata)) - data += rrlen - data += rdata - - return data - - -def _make_dnskey( - public_key: PublicKey, - algorithm: Union[int, str], - flags: int = Flag.ZONE, - protocol: int = 3, -) -> DNSKEY: - """Convert a public key to DNSKEY Rdata - - *public_key*, a ``PublicKey`` (``GenericPublicKey`` or - ``cryptography.hazmat.primitives.asymmetric``) to convert. - - *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm. - - *flags*: DNSKEY flags field as an integer. - - *protocol*: DNSKEY protocol field as an integer. - - Raises ``ValueError`` if the specified key algorithm parameters are not - unsupported, ``TypeError`` if the key type is unsupported, - `UnsupportedAlgorithm` if the algorithm is unknown and - `AlgorithmKeyMismatch` if the algorithm does not match the key type. - - Return DNSKEY ``Rdata``. - """ - - algorithm = Algorithm.make(algorithm) - - # pylint: disable=possibly-used-before-assignment - if isinstance(public_key, GenericPublicKey): - return public_key.to_dnskey(flags=flags, protocol=protocol) - else: - public_cls = get_algorithm_cls(algorithm).public_cls - return public_cls(key=public_key).to_dnskey(flags=flags, protocol=protocol) - - -def _make_cdnskey( - public_key: PublicKey, - algorithm: Union[int, str], - flags: int = Flag.ZONE, - protocol: int = 3, -) -> CDNSKEY: - """Convert a public key to CDNSKEY Rdata - - *public_key*, the public key to convert, a - ``cryptography.hazmat.primitives.asymmetric`` public key class applicable - for DNSSEC. - - *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm. - - *flags*: DNSKEY flags field as an integer. - - *protocol*: DNSKEY protocol field as an integer. - - Raises ``ValueError`` if the specified key algorithm parameters are not - unsupported, ``TypeError`` if the key type is unsupported, - `UnsupportedAlgorithm` if the algorithm is unknown and - `AlgorithmKeyMismatch` if the algorithm does not match the key type. - - Return CDNSKEY ``Rdata``. - """ - - dnskey = _make_dnskey(public_key, algorithm, flags, protocol) - - return CDNSKEY( - rdclass=dnskey.rdclass, - rdtype=dns.rdatatype.CDNSKEY, - flags=dnskey.flags, - protocol=dnskey.protocol, - algorithm=dnskey.algorithm, - key=dnskey.key, - ) - - -def nsec3_hash( - domain: Union[dns.name.Name, str], - salt: Optional[Union[str, bytes]], - iterations: int, - algorithm: Union[int, str], -) -> str: - """ - Calculate the NSEC3 hash, according to - https://tools.ietf.org/html/rfc5155#section-5 - - *domain*, a ``dns.name.Name`` or ``str``, the name to hash. - - *salt*, a ``str``, ``bytes``, or ``None``, the hash salt. If a - string, it is decoded as a hex string. - - *iterations*, an ``int``, the number of iterations. - - *algorithm*, a ``str`` or ``int``, the hash algorithm. - The only defined algorithm is SHA1. - - Returns a ``str``, the encoded NSEC3 hash. - """ - - b32_conversion = str.maketrans( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", "0123456789ABCDEFGHIJKLMNOPQRSTUV" - ) - - try: - if isinstance(algorithm, str): - algorithm = NSEC3Hash[algorithm.upper()] - except Exception: - raise ValueError("Wrong hash algorithm (only SHA1 is supported)") - - if algorithm != NSEC3Hash.SHA1: - raise ValueError("Wrong hash algorithm (only SHA1 is supported)") - - if salt is None: - salt_encoded = b"" - elif isinstance(salt, str): - if len(salt) % 2 == 0: - salt_encoded = bytes.fromhex(salt) - else: - raise ValueError("Invalid salt length") - else: - salt_encoded = salt - - if not isinstance(domain, dns.name.Name): - domain = dns.name.from_text(domain) - domain_encoded = domain.canonicalize().to_wire() - assert domain_encoded is not None - - digest = hashlib.sha1(domain_encoded + salt_encoded).digest() - for _ in range(iterations): - digest = hashlib.sha1(digest + salt_encoded).digest() - - output = base64.b32encode(digest).decode("utf-8") - output = output.translate(b32_conversion) - - return output - - -def make_ds_rdataset( - rrset: Union[dns.rrset.RRset, Tuple[dns.name.Name, dns.rdataset.Rdataset]], - algorithms: Set[Union[DSDigest, str]], - origin: Optional[dns.name.Name] = None, -) -> dns.rdataset.Rdataset: - """Create a DS record from DNSKEY/CDNSKEY/CDS. - - *rrset*, the RRset to create DS Rdataset for. This can be a - ``dns.rrset.RRset`` or a (``dns.name.Name``, ``dns.rdataset.Rdataset``) - tuple. - - *algorithms*, a set of ``str`` or ``int`` specifying the hash algorithms. - The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case - does not matter for these strings. If the RRset is a CDS, only digest - algorithms matching algorithms are accepted. - - *origin*, a ``dns.name.Name`` or ``None``. If `key` is a relative name, - then it will be made absolute using the specified origin. - - Raises ``UnsupportedAlgorithm`` if any of the algorithms are unknown and - ``ValueError`` if the given RRset is not usable. - - Returns a ``dns.rdataset.Rdataset`` - """ - - rrname, rdataset = _get_rrname_rdataset(rrset) - - if rdataset.rdtype not in ( - dns.rdatatype.DNSKEY, - dns.rdatatype.CDNSKEY, - dns.rdatatype.CDS, - ): - raise ValueError("rrset not a DNSKEY/CDNSKEY/CDS") - - _algorithms = set() - for algorithm in algorithms: - try: - if isinstance(algorithm, str): - algorithm = DSDigest[algorithm.upper()] - except Exception: - raise UnsupportedAlgorithm(f'unsupported algorithm "{algorithm}"') - _algorithms.add(algorithm) - - if rdataset.rdtype == dns.rdatatype.CDS: - res = [] - for rdata in cds_rdataset_to_ds_rdataset(rdataset): - if rdata.digest_type in _algorithms: - res.append(rdata) - if len(res) == 0: - raise ValueError("no acceptable CDS rdata found") - return dns.rdataset.from_rdata_list(rdataset.ttl, res) - - res = [] - for algorithm in _algorithms: - res.extend(dnskey_rdataset_to_cds_rdataset(rrname, rdataset, algorithm, origin)) - return dns.rdataset.from_rdata_list(rdataset.ttl, res) - - -def cds_rdataset_to_ds_rdataset( - rdataset: dns.rdataset.Rdataset, -) -> dns.rdataset.Rdataset: - """Create a CDS record from DS. - - *rdataset*, a ``dns.rdataset.Rdataset``, to create DS Rdataset for. - - Raises ``ValueError`` if the rdataset is not CDS. - - Returns a ``dns.rdataset.Rdataset`` - """ - - if rdataset.rdtype != dns.rdatatype.CDS: - raise ValueError("rdataset not a CDS") - res = [] - for rdata in rdataset: - res.append( - CDS( - rdclass=rdata.rdclass, - rdtype=dns.rdatatype.DS, - key_tag=rdata.key_tag, - algorithm=rdata.algorithm, - digest_type=rdata.digest_type, - digest=rdata.digest, - ) - ) - return dns.rdataset.from_rdata_list(rdataset.ttl, res) - - -def dnskey_rdataset_to_cds_rdataset( - name: Union[dns.name.Name, str], - rdataset: dns.rdataset.Rdataset, - algorithm: Union[DSDigest, str], - origin: Optional[dns.name.Name] = None, -) -> dns.rdataset.Rdataset: - """Create a CDS record from DNSKEY/CDNSKEY. - - *name*, a ``dns.name.Name`` or ``str``, the owner name of the CDS record. - - *rdataset*, a ``dns.rdataset.Rdataset``, to create DS Rdataset for. - - *algorithm*, a ``str`` or ``int`` specifying the hash algorithm. - The currently supported hashes are "SHA1", "SHA256", and "SHA384". Case - does not matter for these strings. - - *origin*, a ``dns.name.Name`` or ``None``. If `key` is a relative name, - then it will be made absolute using the specified origin. - - Raises ``UnsupportedAlgorithm`` if the algorithm is unknown or - ``ValueError`` if the rdataset is not DNSKEY/CDNSKEY. - - Returns a ``dns.rdataset.Rdataset`` - """ - - if rdataset.rdtype not in (dns.rdatatype.DNSKEY, dns.rdatatype.CDNSKEY): - raise ValueError("rdataset not a DNSKEY/CDNSKEY") - res = [] - for rdata in rdataset: - res.append(make_cds(name, rdata, algorithm, origin)) - return dns.rdataset.from_rdata_list(rdataset.ttl, res) - - -def dnskey_rdataset_to_cdnskey_rdataset( - rdataset: dns.rdataset.Rdataset, -) -> dns.rdataset.Rdataset: - """Create a CDNSKEY record from DNSKEY. - - *rdataset*, a ``dns.rdataset.Rdataset``, to create CDNSKEY Rdataset for. - - Returns a ``dns.rdataset.Rdataset`` - """ - - if rdataset.rdtype != dns.rdatatype.DNSKEY: - raise ValueError("rdataset not a DNSKEY") - res = [] - for rdata in rdataset: - res.append( - CDNSKEY( - rdclass=rdataset.rdclass, - rdtype=rdataset.rdtype, - flags=rdata.flags, - protocol=rdata.protocol, - algorithm=rdata.algorithm, - key=rdata.key, - ) - ) - return dns.rdataset.from_rdata_list(rdataset.ttl, res) - - -def default_rrset_signer( - txn: dns.transaction.Transaction, - rrset: dns.rrset.RRset, - signer: dns.name.Name, - ksks: List[Tuple[PrivateKey, DNSKEY]], - zsks: List[Tuple[PrivateKey, DNSKEY]], - inception: Optional[Union[datetime, str, int, float]] = None, - expiration: Optional[Union[datetime, str, int, float]] = None, - lifetime: Optional[int] = None, - policy: Optional[Policy] = None, - origin: Optional[dns.name.Name] = None, - deterministic: bool = True, -) -> None: - """Default RRset signer""" - - if rrset.rdtype in set( - [ - dns.rdatatype.RdataType.DNSKEY, - dns.rdatatype.RdataType.CDS, - dns.rdatatype.RdataType.CDNSKEY, - ] - ): - keys = ksks - else: - keys = zsks - - for private_key, dnskey in keys: - rrsig = dns.dnssec.sign( - rrset=rrset, - private_key=private_key, - dnskey=dnskey, - inception=inception, - expiration=expiration, - lifetime=lifetime, - signer=signer, - policy=policy, - origin=origin, - deterministic=deterministic, - ) - txn.add(rrset.name, rrset.ttl, rrsig) - - -def sign_zone( - zone: dns.zone.Zone, - txn: Optional[dns.transaction.Transaction] = None, - keys: Optional[List[Tuple[PrivateKey, DNSKEY]]] = None, - add_dnskey: bool = True, - dnskey_ttl: Optional[int] = None, - inception: Optional[Union[datetime, str, int, float]] = None, - expiration: Optional[Union[datetime, str, int, float]] = None, - lifetime: Optional[int] = None, - nsec3: Optional[NSEC3PARAM] = None, - rrset_signer: Optional[RRsetSigner] = None, - policy: Optional[Policy] = None, - deterministic: bool = True, -) -> None: - """Sign zone. - - *zone*, a ``dns.zone.Zone``, the zone to sign. - - *txn*, a ``dns.transaction.Transaction``, an optional transaction to use for - signing. - - *keys*, a list of (``PrivateKey``, ``DNSKEY``) tuples, to use for signing. KSK/ZSK - roles are assigned automatically if the SEP flag is used, otherwise all RRsets are - signed by all keys. - - *add_dnskey*, a ``bool``. If ``True``, the default, all specified DNSKEYs are - automatically added to the zone on signing. - - *dnskey_ttl*, a``int``, specifies the TTL for DNSKEY RRs. If not specified the TTL - of the existing DNSKEY RRset used or the TTL of the SOA RRset. - - *inception*, a ``datetime``, ``str``, ``int``, ``float`` or ``None``, the signature - inception time. If ``None``, the current time is used. If a ``str``, the format is - "YYYYMMDDHHMMSS" or alternatively the number of seconds since the UNIX epoch in text - form; this is the same the RRSIG rdata's text form. Values of type `int` or `float` - are interpreted as seconds since the UNIX epoch. - - *expiration*, a ``datetime``, ``str``, ``int``, ``float`` or ``None``, the signature - expiration time. If ``None``, the expiration time will be the inception time plus - the value of the *lifetime* parameter. See the description of *inception* above for - how the various parameter types are interpreted. - - *lifetime*, an ``int`` or ``None``, the signature lifetime in seconds. This - parameter is only meaningful if *expiration* is ``None``. - - *nsec3*, a ``NSEC3PARAM`` Rdata, configures signing using NSEC3. Not yet - implemented. - - *rrset_signer*, a ``Callable``, an optional function for signing RRsets. The - function requires two arguments: transaction and RRset. If the not specified, - ``dns.dnssec.default_rrset_signer`` will be used. - - *deterministic*, a ``bool``. If ``True``, the default, use deterministic - (reproducible) signatures when supported by the algorithm used for signing. - Currently, this only affects ECDSA. - - Returns ``None``. - """ - - ksks = [] - zsks = [] - - # if we have both KSKs and ZSKs, split by SEP flag. if not, sign all - # records with all keys - if keys: - for key in keys: - if key[1].flags & Flag.SEP: - ksks.append(key) - else: - zsks.append(key) - if not ksks: - ksks = keys - if not zsks: - zsks = keys - else: - keys = [] - - if txn: - cm: contextlib.AbstractContextManager = contextlib.nullcontext(txn) - else: - cm = zone.writer() - - if zone.origin is None: - raise ValueError("no zone origin") - - with cm as _txn: - if add_dnskey: - if dnskey_ttl is None: - dnskey = _txn.get(zone.origin, dns.rdatatype.DNSKEY) - if dnskey: - dnskey_ttl = dnskey.ttl - else: - soa = _txn.get(zone.origin, dns.rdatatype.SOA) - dnskey_ttl = soa.ttl - for _, dnskey in keys: - _txn.add(zone.origin, dnskey_ttl, dnskey) - - if nsec3: - raise NotImplementedError("Signing with NSEC3 not yet implemented") - else: - _rrset_signer = rrset_signer or functools.partial( - default_rrset_signer, - signer=zone.origin, - ksks=ksks, - zsks=zsks, - inception=inception, - expiration=expiration, - lifetime=lifetime, - policy=policy, - origin=zone.origin, - deterministic=deterministic, - ) - return _sign_zone_nsec(zone, _txn, _rrset_signer) - - -def _sign_zone_nsec( - zone: dns.zone.Zone, - txn: dns.transaction.Transaction, - rrset_signer: Optional[RRsetSigner] = None, -) -> None: - """NSEC zone signer""" - - def _txn_add_nsec( - txn: dns.transaction.Transaction, - name: dns.name.Name, - next_secure: Optional[dns.name.Name], - rdclass: dns.rdataclass.RdataClass, - ttl: int, - rrset_signer: Optional[RRsetSigner] = None, - ) -> None: - """NSEC zone signer helper""" - mandatory_types = set( - [dns.rdatatype.RdataType.RRSIG, dns.rdatatype.RdataType.NSEC] - ) - node = txn.get_node(name) - if node and next_secure: - types = ( - set([rdataset.rdtype for rdataset in node.rdatasets]) | mandatory_types - ) - windows = Bitmap.from_rdtypes(list(types)) - rrset = dns.rrset.from_rdata( - name, - ttl, - NSEC( - rdclass=rdclass, - rdtype=dns.rdatatype.RdataType.NSEC, - next=next_secure, - windows=windows, - ), - ) - txn.add(rrset) - if rrset_signer: - rrset_signer(txn, rrset) - - rrsig_ttl = zone.get_soa().minimum - delegation = None - last_secure = None - - for name in sorted(txn.iterate_names()): - if delegation and name.is_subdomain(delegation): - # names below delegations are not secure - continue - elif txn.get(name, dns.rdatatype.NS) and name != zone.origin: - # inside delegation - delegation = name - else: - # outside delegation - delegation = None - - if rrset_signer: - node = txn.get_node(name) - if node: - for rdataset in node.rdatasets: - if rdataset.rdtype == dns.rdatatype.RRSIG: - # do not sign RRSIGs - continue - elif delegation and rdataset.rdtype != dns.rdatatype.DS: - # do not sign delegations except DS records - continue - else: - rrset = dns.rrset.from_rdata(name, rdataset.ttl, *rdataset) - rrset_signer(txn, rrset) - - # We need "is not None" as the empty name is False because its length is 0. - if last_secure is not None: - _txn_add_nsec(txn, last_secure, name, zone.rdclass, rrsig_ttl, rrset_signer) - last_secure = name - - if last_secure: - _txn_add_nsec( - txn, last_secure, zone.origin, zone.rdclass, rrsig_ttl, rrset_signer - ) - - -def _need_pyca(*args, **kwargs): - raise ImportError( - "DNSSEC validation requires python cryptography" - ) # pragma: no cover - - -if dns._features.have("dnssec"): - from cryptography.exceptions import InvalidSignature - from cryptography.hazmat.primitives.asymmetric import dsa # pylint: disable=W0611 - from cryptography.hazmat.primitives.asymmetric import ec # pylint: disable=W0611 - from cryptography.hazmat.primitives.asymmetric import ed448 # pylint: disable=W0611 - from cryptography.hazmat.primitives.asymmetric import rsa # pylint: disable=W0611 - from cryptography.hazmat.primitives.asymmetric import ( # pylint: disable=W0611 - ed25519, - ) - - from dns.dnssecalgs import ( # pylint: disable=C0412 - get_algorithm_cls, - get_algorithm_cls_from_dnskey, - ) - from dns.dnssecalgs.base import GenericPrivateKey, GenericPublicKey - - validate = _validate # type: ignore - validate_rrsig = _validate_rrsig # type: ignore - sign = _sign - make_dnskey = _make_dnskey - make_cdnskey = _make_cdnskey - _have_pyca = True -else: # pragma: no cover - validate = _need_pyca - validate_rrsig = _need_pyca - sign = _need_pyca - make_dnskey = _need_pyca - make_cdnskey = _need_pyca - _have_pyca = False - -### BEGIN generated Algorithm constants - -RSAMD5 = Algorithm.RSAMD5 -DH = Algorithm.DH -DSA = Algorithm.DSA -ECC = Algorithm.ECC -RSASHA1 = Algorithm.RSASHA1 -DSANSEC3SHA1 = Algorithm.DSANSEC3SHA1 -RSASHA1NSEC3SHA1 = Algorithm.RSASHA1NSEC3SHA1 -RSASHA256 = Algorithm.RSASHA256 -RSASHA512 = Algorithm.RSASHA512 -ECCGOST = Algorithm.ECCGOST -ECDSAP256SHA256 = Algorithm.ECDSAP256SHA256 -ECDSAP384SHA384 = Algorithm.ECDSAP384SHA384 -ED25519 = Algorithm.ED25519 -ED448 = Algorithm.ED448 -INDIRECT = Algorithm.INDIRECT -PRIVATEDNS = Algorithm.PRIVATEDNS -PRIVATEOID = Algorithm.PRIVATEOID - -### END generated Algorithm constants diff --git a/venv/Lib/site-packages/dns/dnssecalgs/__init__.py b/venv/Lib/site-packages/dns/dnssecalgs/__init__.py deleted file mode 100644 index 602367e..0000000 --- a/venv/Lib/site-packages/dns/dnssecalgs/__init__.py +++ /dev/null @@ -1,121 +0,0 @@ -from typing import Dict, Optional, Tuple, Type, Union - -import dns.name -from dns.dnssecalgs.base import GenericPrivateKey -from dns.dnssectypes import Algorithm -from dns.exception import UnsupportedAlgorithm -from dns.rdtypes.ANY.DNSKEY import DNSKEY - -if dns._features.have("dnssec"): - from dns.dnssecalgs.dsa import PrivateDSA, PrivateDSANSEC3SHA1 - from dns.dnssecalgs.ecdsa import PrivateECDSAP256SHA256, PrivateECDSAP384SHA384 - from dns.dnssecalgs.eddsa import PrivateED448, PrivateED25519 - from dns.dnssecalgs.rsa import ( - PrivateRSAMD5, - PrivateRSASHA1, - PrivateRSASHA1NSEC3SHA1, - PrivateRSASHA256, - PrivateRSASHA512, - ) - - _have_cryptography = True -else: - _have_cryptography = False - -AlgorithmPrefix = Optional[Union[bytes, dns.name.Name]] - -algorithms: Dict[Tuple[Algorithm, AlgorithmPrefix], Type[GenericPrivateKey]] = {} -if _have_cryptography: - # pylint: disable=possibly-used-before-assignment - algorithms.update( - { - (Algorithm.RSAMD5, None): PrivateRSAMD5, - (Algorithm.DSA, None): PrivateDSA, - (Algorithm.RSASHA1, None): PrivateRSASHA1, - (Algorithm.DSANSEC3SHA1, None): PrivateDSANSEC3SHA1, - (Algorithm.RSASHA1NSEC3SHA1, None): PrivateRSASHA1NSEC3SHA1, - (Algorithm.RSASHA256, None): PrivateRSASHA256, - (Algorithm.RSASHA512, None): PrivateRSASHA512, - (Algorithm.ECDSAP256SHA256, None): PrivateECDSAP256SHA256, - (Algorithm.ECDSAP384SHA384, None): PrivateECDSAP384SHA384, - (Algorithm.ED25519, None): PrivateED25519, - (Algorithm.ED448, None): PrivateED448, - } - ) - - -def get_algorithm_cls( - algorithm: Union[int, str], prefix: AlgorithmPrefix = None -) -> Type[GenericPrivateKey]: - """Get Private Key class from Algorithm. - - *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm. - - Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. - - Returns a ``dns.dnssecalgs.GenericPrivateKey`` - """ - algorithm = Algorithm.make(algorithm) - cls = algorithms.get((algorithm, prefix)) - if cls: - return cls - raise UnsupportedAlgorithm( - f'algorithm "{Algorithm.to_text(algorithm)}" not supported by dnspython' - ) - - -def get_algorithm_cls_from_dnskey(dnskey: DNSKEY) -> Type[GenericPrivateKey]: - """Get Private Key class from DNSKEY. - - *dnskey*, a ``DNSKEY`` to get Algorithm class for. - - Raises ``UnsupportedAlgorithm`` if the algorithm is unknown. - - Returns a ``dns.dnssecalgs.GenericPrivateKey`` - """ - prefix: AlgorithmPrefix = None - if dnskey.algorithm == Algorithm.PRIVATEDNS: - prefix, _ = dns.name.from_wire(dnskey.key, 0) - elif dnskey.algorithm == Algorithm.PRIVATEOID: - length = int(dnskey.key[0]) - prefix = dnskey.key[0 : length + 1] - return get_algorithm_cls(dnskey.algorithm, prefix) - - -def register_algorithm_cls( - algorithm: Union[int, str], - algorithm_cls: Type[GenericPrivateKey], - name: Optional[Union[dns.name.Name, str]] = None, - oid: Optional[bytes] = None, -) -> None: - """Register Algorithm Private Key class. - - *algorithm*, a ``str`` or ``int`` specifying the DNSKEY algorithm. - - *algorithm_cls*: A `GenericPrivateKey` class. - - *name*, an optional ``dns.name.Name`` or ``str``, for for PRIVATEDNS algorithms. - - *oid*: an optional BER-encoded `bytes` for PRIVATEOID algorithms. - - Raises ``ValueError`` if a name or oid is specified incorrectly. - """ - if not issubclass(algorithm_cls, GenericPrivateKey): - raise TypeError("Invalid algorithm class") - algorithm = Algorithm.make(algorithm) - prefix: AlgorithmPrefix = None - if algorithm == Algorithm.PRIVATEDNS: - if name is None: - raise ValueError("Name required for PRIVATEDNS algorithms") - if isinstance(name, str): - name = dns.name.from_text(name) - prefix = name - elif algorithm == Algorithm.PRIVATEOID: - if oid is None: - raise ValueError("OID required for PRIVATEOID algorithms") - prefix = bytes([len(oid)]) + oid - elif name: - raise ValueError("Name only supported for PRIVATEDNS algorithm") - elif oid: - raise ValueError("OID only supported for PRIVATEOID algorithm") - algorithms[(algorithm, prefix)] = algorithm_cls diff --git a/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index 49a69a9b19042a3b082cd942851e5c8eb65d37b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3740 zcmc&%&2JmW72lm*F3BY+QW8yBjwG+;*bZfxu4Kt|0;8y6sfm%4HY6)R212P7cPOp2 zAMETE~!p(kUJ`ml61?xf$UoPuq}oA4*;q+h0G zsh9Px`4w96r|6WNo8EPQnoj#S=nXl~dGGl%bjF{hv;G{N^Ka6dzC|sN<>{?}I0br( z5td@}u+Htn_giFInO5i>SD|;A$~2Z^caX<)mYr54bQ*2P}73bx4b_ z8K4#*4N#ph%+zR!VLr4i&L*UZI8wJ zt8SacsqFx`^{N_=f5HOB-R4W~9@~O_#=5}Fu6g?*cg2AZlk#>Db=vKa3+9~X8|(G0 z&o;iKh7&{)YgS2Y_MNP6t;Lfgy1upX?9tYzYfGR~>9aSUfzr$6)yKex@e=>hlNI2@ z2p0K)#rn$1lXz@6TV7pV`VhXe(C2J!t^Is`b*KPSTr!>-iE%!RB`#eMU(7t*7+V z7J(V*5nk#+&V=r$pp!zK-@9)FVuy2V2W+mCPhGu;~o3)^$0 zN$a7R&EFPoAS1xC<1}TB!m8iXVz8-6EVr0UqI=8@I z0wlE&8y*Yx#eoDsfQP@2JS}vc zCPHHHU^y8=Q(kc&D9|L&M>Iqos(tAOS^}v1~*6IPQKsyiR>r;@YP~Ovc z9cV++swhH{(_7>z6f*!^+WrkBWs~i@kzo8BY_62H0qll*^1s!xQBA~yx$u#-X6;@r zK?!;XOCvUL)xZk-Hz(9W$YTu!wK@!N0Ay8_1$NPD!35tC%0@Lc8hC|-!t&>xe!Q{y zfCbIaVUD%C*A*<vTb2>7#1vq6*;N(F8Fp~4bE9p zc->l3Yp0$EQ0qW%xXZ~7)KBi==UJTnvID2WIUf$3osoKUau>tPo zRr4R(tdsj_{lm%^d{;}c=|)j!PhN>U4QC?GVrwIJMP3p71~Bz4$)K=@rWOUb;%8XS6g(^OMQS-C&3;EPD%EpxddRCpim7cYlxP>s;H zIgwFKxExG113weWfzhYSz|F|Fr1BL|t*Z4Zsn@F?#)jy&;riy-ZEy_-ED9W}12LsYR?*@}0zO$JH;fjL%U(B`M1FFmR*=UXsa0F6e_2az z0gnHF&}^f{Y-oU3MD+vvn9+%mU%8?a**u5gLNpB&|i zcMj5VluqC21e9q@@`v%``m6Hbonw$G1ak-$fU)!L3j63_H#);QEW8q z06GvGJLjkYRln1Apf{#Q(qmE$dRLn6cbGH}vte6FOMUi;lTA3#VbVScttBm9>VOA~ zVe3oN8|$*irKt^Uefd2MehCL`CFJcP@o^4%*yC_{BW0fYq0{l$Pw+a74q%v5G9(W; zlRr{|rlh3Ks76L7WnvL%RESATz~JQ{`G@|FOz7`SmAoVH8pQmrQYP1ks(*_-gOKkg PH1cmlC*P9P*uVY*%zg(& diff --git a/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/base.cpython-310.pyc b/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/base.cpython-310.pyc deleted file mode 100644 index 4fc0c06a898f735232d4f7ef97e9a8a0cfa34696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3766 zcmb_f&2!tv6$cg|2=GIsBwCi_*kzhd8>Y4Faho>N@w9ejIg^p2cp@ilFq*-D*rf~^ zAM65BD~(T$554q%XlHuypVJ<3>7l2bdrQ-}zqcSriInS0m$MK1^>%;z_I)vJw;LKt z?;qEn{>{;}e^TdsG10k)n*9-kYg~`CSa7j!+?%DU+U=GL(TpUA~aX$n#(@Z zgdt3>-_=BoGhuOqnr5~Fr@bpd0!CLjP+p>_pGZlD7&H+GUB<)V)l>HArKc$$l> zKT0LRf(Dm}Ug{;HIUHS~cs=lXiculHhKl)Kz`#EU(pj6wGm7_E9|jM^E61K1tlP?>So_XBiC~Mh#eWAChn*|XSiqWx%Ox4 zFK~^2vXqKk`&8LRf2^#hdYp+1zC%O_hfHKpmvF{fVL;8@ zhE&=~JO%q`&vjH^u_}h^#4u62*^H9g z_IT&xo26Rw{{HdsNCf%R-F=jdQZlG)EP`+p3f|~XN|^LNeYo9!|IP=uC-%n zmt4(Om;v(k^j?eZs9N(zWB>euTHT!3{Qv11@~unoTX=q;|LGL{qN6HT46cy#P5fAR zUeWNpIOWF?wOgL|+hac}XCwvAqT_jflBBsZx}huW~`%j zQG5CglQo&XhPI++PggtvmR~3Y;2vuBSCETozy>7&lnPh~mdQ2Rs|I zS?p)>D|}7u*HwXivskXoN`@z})?IPxR<<*Knl;HsQ?Dcu$7&g85_Oz-$h z8eapMd6nsz(-8ddNf{#Pv5PhrxsWkJc$SAjKpIgMYR@~I?mi;$CGpoRqn!%9N{N09 z<~f8&M!-y7z4SI~3u4)#1?9Wb!BwI5Jdn)`cB$Nbm}I%11fp~im)ce(c9`)aY&z%l zW}=#SIxH)i<8qj65&;Y0;CCrv3E59os6CJGy~+WW+zKE$o&I^(@pyN8|D6w}DU5Py z%I<%L9p|K{4D2zDD_1>@8Z*#SpT;U+_)>cw+q;$Q&S8V!eJwIpKJI0p$l!mCT7p_% ze9?)kVh^7n4Iw30&s*jt%Tk4&AJOPdB9vN`^IOy+xz2o)yoGLI4%0M}KcSiTi6|#u zqt^d+KzFd@E^0=kp|vIsh?$7P-!R6$h2!}Tdf%{G>)*`AJRA{Y<}1)wh}W+eTl$vO zZs?MB8uSXo9|n@7t6&xuGJ`NVEa56VbQyOE(SK`}NyzWfV0$`9>4e*%E-Er>>SxMh zmy5*j1EKy-spQRFD;d?Qt^0dlY?bMa^3NA1u@K5jIl6M$rBDg^Ijx#{=fb{Q#*SZ* Vrl@4HtMzo7*?Md8>l(e={{^ElS&IMw diff --git a/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/cryptography.cpython-310.pyc b/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/cryptography.cpython-310.pyc deleted file mode 100644 index 1a424af85e7e544ae449e4d3270780e37b9eef95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2664 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%0D}Mch6SADT0MV&wzXpwR^>8#9?!q~R zi_ZWIQ(5@GkCKVJuT-iEC(G5OpBEN6Cb%$;R5X;iRI6$1apC4^37CS73pOa&QO8!B z_*B5hqr!&k!n|>^NL)3R}A# zPRBS$ha*A_6j6pIfrHO1-R>X+K@VC#+g|yOc6VkFpmJwknYp5Zz_#YDu7QA1qjr0x zRY+SP=;vPUKQR_exL*+WdOh_TPNxX+s!8Hi5@bg8Itg<8mrOgpQw^?%5>QbxL}-;{ z8j|Vz>2Nm&V*y!uq-tYU;Y>#4dqtTjXaQHH?RzC`6h))DM17a2?-U=)?!sT94C^cM zOvfwCeo|6P;GlJ!tAgd~hqQu*%H#4iE?FPlJ5%pF3Nt9&> zxBXNog0lK4iFNR3jUq_VC4zvSkvn|DXAXWY+vE+GH?A_>-$&QEhnCzz$^HQGvNRdE z9`{V-d`o)5mcDRMD$?6?bz-!Gs;mhgsk5RJV^!3iQetd~I>OA03=>Rmf$8x+25%pGxi`m=W-h|5dQh7=GY1Ehu#ntT;*=sLJ z|5OIA4r3j`I=(f3^TJ8wXprw09w8=GLaI)qjM%qfAoT``??E6*V@sRTAjtAHScvG!!6lLtejgnlqGW9dzv2VF7g+-ZvCA8bKWlLQ4S#0YEwoIVYfN?NkowT)xS!aDfTV## zhXKL$_{1GEE zLM!J8!DrJ;XLflyrq|&QKJ7Hs4O;CciCZKzz19JR0!C5N1J)-7J-@AVJ_xI`XQzj?2>>G$<}UpM;Is&C*~_|N;h zqGA~TC1dunV632||Ar8TV6o9-0b``|nD@-U)Vdj4Jv*>_PT*+Uic38=aC=_hY1@wd zUO6ah-H9u`YEWgyKMYY4?n^_s(tBYBHQ1i;Vf)gBU58y371$M7gWZ5#6*bs3S%*Cb zyDl2A8@hcS_MDi9J+IrZiEA51YvC1EZnRil7jiq=kF#(q>O7Z;K$Wu_rMoh1@tn&} zZtrK^n2e=WbvVfSJ1QFN9zIsxgD8^^fu6};3K%QfTvS9A79bK#HqgV^wnRO#vNAT}nK`nCrr_g3vq&5BV;f`aku$W1JS&Y{ zSl*b8b;Q99b6qjaots1zw^A8zs|E};2NBqqD^$fR%}rR}8R}iM{O{4~mzz&hsnX5C zPQNEN@5}Ug)*oy>y1#Z1#hV8*IoN#E-P%mMnf!Qw@QZe2x+#+M6O>eTfPMOj?1(gK z4-VB5rkqDfk&s4>)tJQ=nDyqmc{D$>ZS7*=9fDx;a43X;#{DBGg!zb#jbk=sdwgWV zwgekq^y?%(fcTDSj9PwhBa}&s%n8p@ zEhLXS{oYm=IR#vG&mxe?mEhgAIPMOzZfBK}uz+E`z_|Fz0)1r>BKJ?X05d9DOv}p6 zPFw_eP|~p#emhYPFYZ8Drv-u$!+(v@DaD}A8*GVjgrCKH{Hz~c%lZCjd3HNy#haIkz#B~BLqKaTa^hB zRKEf*oe^$OJvWsiL~^@GaB@PCJD{{UO4FXqcKbqkRQ+2L6lXJnf>F_VNTqfvA49y2-vigtF~=H9kTeE!l7%3$_d z!Rp}bs;D5)>Urh#Bq}(H$m_uqO-!0F@~V)TRK0G}O%X7P2&6+nGJUnBv|V*mCQI>OX4JUmMZN(3VHg7Pgo6HZSGAupd4I)>Ey)L)+|zafocspV-3n}V)B zrY53k?2=T|!zQr7<#bliD=p5DX|U-yyM-x`6>+V&=*l&6Ns)sWJf~{0pF-b-n;9 z>Mw$ds$T^4Z}{Rf6!jMpWL;YO1WNTKS}#F&ww^1Xqv`%XbSr56hI-s3u>!H)S_rOp zX8zH%ccY_Tl(kPeAl3JU;Df8WfCzfstb2glvWcmJ*4sO^qx7(cQ&!;sqOB`P_C4Gy z+S7|}dv*>*N0Ord3PF9^Ejt|Gi#qC;s8$JG)4sR{#uTy>CWw6)(? lrF`z*Ev_YhC;U^okXDQeYp@2dFucvihm9MJQo~v({S3DkW>)|J diff --git a/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/eddsa.cpython-310.pyc b/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/eddsa.cpython-310.pyc deleted file mode 100644 index 9495920fc8c027b422b1a081af770b260f6ad8fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2990 zcmaJ@OK;mo5auo^ijpXab{r>Z9##54t2R-RHbK)OEgbmK0tt*DP7Waq5VUq}%ONFo zNxP7sp5kl&gMG}s*ZvV+dg!U=+}iZ<%`&oO$Ib#f+}T~u&V2LO?NzH~18wH_%bULy z4dV}DCYuFj4n6r5L>PiaM$CN1Xv`xXo4%>XW@N<$zYyELt$8ad#*XjACBLNkLR5|` zenpS%$c?Lhl^Nd~q9~kQLpZYZ!t`t4OQHu1E76{9)xCp0&jEVG^r`V!x2B2_1hI>RvS^tw%+6{NU*`)*d0 z;)^?XZheiJ*?BeSr@ajo_BRKQRA(nlV=pYP zJXn0zrgJBo4Q38KSpt!U&xGM~!K5iTx+$!6TNH%7Yx$NirMb>EI+kCMwkXLWb{OlH zD2vLj^@911uwb2=RUTv(XLHZ6z~HglU-BN`mVyw@sWmZZsyx&Z8&O zAR}YT*kdC$;`^Lj1i@?>IGE32w7mno)(1^9vl1Dts|tQlF33wmP2uy`!})Jkp90im zwZGAecfS_oiJM6k=>ouhn=<6q?5|){jmK!+>ptt=q5MN6WI=i2FB~TE;kCtX zyC-BLZ1go~4cOP{OVxP1G~c*;^X|=S4d_E*(fG0j`yEO9JKc@UUhkR$lmyoh0qFRTVn4$=%~tz~I3BAAuRC^*;OA8gbk0J%jda~Obb&_yLo77VbvU?1 zi+Rjq!>LI)T6D%+8BZxUPd`##>EK2I+sFMxfvwJAvdI-ygUs2GU8zvO5$hK)aXbJB zsB7rD-gta?_Q>JmpHU5$oVSOGGXcq3qLPlhuPD>~?#pPMahM6y;)O zt@V15B8%1gMCjlNWi&Dxlm-?^VnV-_4VUo(XVz=Z`M=!c|8R@H=7sX#-1V4NrHySz z8i6y1{)@AU(u4^oNJ=p!_@9KR%}G@4m;oPzoe)b3qwmXF&=A?ACF`9+!k@c>@` z7}FYUMQQC97Zie^tYi9+dJCgEPp4XPdZanhpF zi55+bEjqaBCrl!J)Kwyf!F%W|3Z1XeCv0$-qS;ezP@iBGkRROKczv7(xP`5LZIK=* zr@~!WTp$TeY&}uM78bsx#m|Tkce-kyV->0$7NkSn-hxi+R?l@i2{=0Gbl`4ab)I%y zCqmqEb0)LXK_7KUCzF4rJ@E`{ZH7bKz%A6LxRZ8v#`kXX-J4orGKg^#C{#>RSm_YH zh?}T&`1)u~%20FxD?Ek`zkaw4df`M0RDYIcmC!S-`^(Q-`Fk(FXy_WzS*hb#2ZDxN nTX>RtGUr}?t$jx?nS^SVYq;EF9^L>h^Gt8roAGSVp0WQ2|CxV< diff --git a/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/rsa.cpython-310.pyc b/venv/Lib/site-packages/dns/dnssecalgs/__pycache__/rsa.cpython-310.pyc deleted file mode 100644 index 22263958aa0224ae719bc1faf3b7eb2860661668..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4712 zcmai2U3U}58Qz`!&}t=F0{j8SfH);NQBR`85Ym=X3Na=$CN2ku_GIgGwrkDUURzqJ zvn!w4m2XOV$zSNPF7uc6rWd{PHFs$!ecoBivL);;XGZhPJ0I^n@5hX3mrAaNZ}MN) zHb0!uw0{#g`I!I@QQ}*=rg4qyP0h=Gbx#LoP1Z6zL#IBYX|^oSQf;$ow{l*t<#>+5 zRx{snJ-1cx3JTlJVyonpR6Ez4XqCOPu6?C(hv&c7cwQ7<8D0h0Xl#p! zqs!h5;!P3PSeokuoQKgyYREVMo?eiC~zI?piZ!pc_l& zA2m1HGE6pGwC>~Om8He+8npGv&jxsi5^tdr8kx*vFEwFonZn}webw@8kpp5t&Q=~R zb0A?N%|BPVzF2vb z8rwKWJ{YK*78;xFSVTT?k>=xYBMOqP6sgIBBuH&3fTHDw0hI?IwdpJiDDfPsp0=eO z=sms15_Vwp37dVB+zGqu%QZ_DFexPvLWvowIeo8kOiMjet%0~Y{w%bpsAC?WksY(I z?dx>R#5}Ni`j*|-xqema>-#J*w{q0eW1Mm0wXtuYWp11DLvAI`L7qd>XEWNq8QBWw z2=AMi;~rRj#M`zO-#bQm%zTg(xcf@~yWTT<#*C(9v`03+FoPU0i@2v%L3MHOBpQ3yjYG5wZDw?)8+l}IGr_+{+;8i%5+9_M(Fo%h?qB6QSktyOw z-PRhcn3}BsyO<3THd7;vlGI%b6aQ#)U8GLZ_DO{}wc|u~8%b)CRZ~4m-9H4)u2__^ zE#XpRNRM?Q&+)}yJG4S-py9cMHbsCFC=bf2DLQIJD0Y01lI<~#-uNOamrd&zbqA%$ z=J0z<-M`On~^NFXAWoBR`vo^}93^>v-hMQ#CS;fM`#ihr;xTA!`z$~6qG z5#DD#gR^ZW>uRK_Mp~yvTE`=?N>8lS3n;W#4~ z&IDYnlDbEiCP-2i4RuY|o_wn^yE<}O;vx~U6-Hs4gbj(5qBZDZ7<}YMR8&}fhQ{EM z8D244R^Om7kkbe`yRVV+Bk&jk&!mfIZ+->WS+yJEX0IY6X7~6xDe+Fd<|uV>8DXZn zs3fI_bl|OIQ6gTFM(Q9(nP_-2d7nh;9vhlYS?xCv{2C=DpSYYe^$J{auRNrxPP?WK zxlSDJiBoBYV&wSJodrP1Yg;;4VLd%DUg0KqjWnV{+*qy|Uim1%kPh3Ch!Xi*OiFV{ z&mZ{-P|eJId2&NULgJ0%A8|x+p3V$jOrr~_aAk5HE2u?ByfbwM%YB6rF)_iIiK9{k zns4oQdzVfec`$al#-4mztH{r3)w@)EL6u4;C5pAS!NJh^sw_Rfu!8m5L1+VSz0{KJl{ONyIjkU9+-T?vvFXEWf4FnkJKQj zJnwy{Sj4y&C~vaM$VR%8)HkLl<@<*;km7Bqr)M5%R~lMIsb`Ie+m=*)JM+6;t6eX<5SZe?pPuh?3BlDg#2~ zQ%Ir8#E^hYmoWxtnX?)A2GT#%h_9(4G`8jF>8DSher0jt&UrM@-Kyk+fkQszGure_ zI+h{jG(yoqXiT?JI%Y=b80<-J`p;>pVWiS}XY=xVNJAQ-cp)^l_b4yrlf2x%`^8y) zk{aD^OvF6jCe@8dK|xca~1E% z`tUEu`pGpUWmlOa9m~UE$!-Tbse+t;WRE$QCe!7iGP6pIDkZ5T zAyxEHSV-kT%25=HM9=$fuGG1oJx?Eyf#Q!)QNk^ None: - pass - - @abstractmethod - def verify(self, signature: bytes, data: bytes) -> None: - """Verify signed DNSSEC data""" - - @abstractmethod - def encode_key_bytes(self) -> bytes: - """Encode key as bytes for DNSKEY""" - - @classmethod - def _ensure_algorithm_key_combination(cls, key: DNSKEY) -> None: - if key.algorithm != cls.algorithm: - raise AlgorithmKeyMismatch - - def to_dnskey(self, flags: int = Flag.ZONE, protocol: int = 3) -> DNSKEY: - """Return public key as DNSKEY""" - return DNSKEY( - rdclass=dns.rdataclass.IN, - rdtype=dns.rdatatype.DNSKEY, - flags=flags, - protocol=protocol, - algorithm=self.algorithm, - key=self.encode_key_bytes(), - ) - - @classmethod - @abstractmethod - def from_dnskey(cls, key: DNSKEY) -> "GenericPublicKey": - """Create public key from DNSKEY""" - - @classmethod - @abstractmethod - def from_pem(cls, public_pem: bytes) -> "GenericPublicKey": - """Create public key from PEM-encoded SubjectPublicKeyInfo as specified - in RFC 5280""" - - @abstractmethod - def to_pem(self) -> bytes: - """Return public-key as PEM-encoded SubjectPublicKeyInfo as specified - in RFC 5280""" - - -class GenericPrivateKey(ABC): - public_cls: Type[GenericPublicKey] - - @abstractmethod - def __init__(self, key: Any) -> None: - pass - - @abstractmethod - def sign( - self, - data: bytes, - verify: bool = False, - deterministic: bool = True, - ) -> bytes: - """Sign DNSSEC data""" - - @abstractmethod - def public_key(self) -> "GenericPublicKey": - """Return public key instance""" - - @classmethod - @abstractmethod - def from_pem( - cls, private_pem: bytes, password: Optional[bytes] = None - ) -> "GenericPrivateKey": - """Create private key from PEM-encoded PKCS#8""" - - @abstractmethod - def to_pem(self, password: Optional[bytes] = None) -> bytes: - """Return private key as PEM-encoded PKCS#8""" diff --git a/venv/Lib/site-packages/dns/dnssecalgs/cryptography.py b/venv/Lib/site-packages/dns/dnssecalgs/cryptography.py deleted file mode 100644 index 5a31a81..0000000 --- a/venv/Lib/site-packages/dns/dnssecalgs/cryptography.py +++ /dev/null @@ -1,68 +0,0 @@ -from typing import Any, Optional, Type - -from cryptography.hazmat.primitives import serialization - -from dns.dnssecalgs.base import GenericPrivateKey, GenericPublicKey -from dns.exception import AlgorithmKeyMismatch - - -class CryptographyPublicKey(GenericPublicKey): - key: Any = None - key_cls: Any = None - - def __init__(self, key: Any) -> None: # pylint: disable=super-init-not-called - if self.key_cls is None: - raise TypeError("Undefined private key class") - if not isinstance( # pylint: disable=isinstance-second-argument-not-valid-type - key, self.key_cls - ): - raise AlgorithmKeyMismatch - self.key = key - - @classmethod - def from_pem(cls, public_pem: bytes) -> "GenericPublicKey": - key = serialization.load_pem_public_key(public_pem) - return cls(key=key) - - def to_pem(self) -> bytes: - return self.key.public_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PublicFormat.SubjectPublicKeyInfo, - ) - - -class CryptographyPrivateKey(GenericPrivateKey): - key: Any = None - key_cls: Any = None - public_cls: Type[CryptographyPublicKey] - - def __init__(self, key: Any) -> None: # pylint: disable=super-init-not-called - if self.key_cls is None: - raise TypeError("Undefined private key class") - if not isinstance( # pylint: disable=isinstance-second-argument-not-valid-type - key, self.key_cls - ): - raise AlgorithmKeyMismatch - self.key = key - - def public_key(self) -> "CryptographyPublicKey": - return self.public_cls(key=self.key.public_key()) - - @classmethod - def from_pem( - cls, private_pem: bytes, password: Optional[bytes] = None - ) -> "GenericPrivateKey": - key = serialization.load_pem_private_key(private_pem, password=password) - return cls(key=key) - - def to_pem(self, password: Optional[bytes] = None) -> bytes: - encryption_algorithm: serialization.KeySerializationEncryption - if password: - encryption_algorithm = serialization.BestAvailableEncryption(password) - else: - encryption_algorithm = serialization.NoEncryption() - return self.key.private_bytes( - encoding=serialization.Encoding.PEM, - format=serialization.PrivateFormat.PKCS8, - encryption_algorithm=encryption_algorithm, - ) diff --git a/venv/Lib/site-packages/dns/dnssecalgs/dsa.py b/venv/Lib/site-packages/dns/dnssecalgs/dsa.py deleted file mode 100644 index adca3de..0000000 --- a/venv/Lib/site-packages/dns/dnssecalgs/dsa.py +++ /dev/null @@ -1,106 +0,0 @@ -import struct - -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import dsa, utils - -from dns.dnssecalgs.cryptography import CryptographyPrivateKey, CryptographyPublicKey -from dns.dnssectypes import Algorithm -from dns.rdtypes.ANY.DNSKEY import DNSKEY - - -class PublicDSA(CryptographyPublicKey): - key: dsa.DSAPublicKey - key_cls = dsa.DSAPublicKey - algorithm = Algorithm.DSA - chosen_hash = hashes.SHA1() - - def verify(self, signature: bytes, data: bytes) -> None: - sig_r = signature[1:21] - sig_s = signature[21:] - sig = utils.encode_dss_signature( - int.from_bytes(sig_r, "big"), int.from_bytes(sig_s, "big") - ) - self.key.verify(sig, data, self.chosen_hash) - - def encode_key_bytes(self) -> bytes: - """Encode a public key per RFC 2536, section 2.""" - pn = self.key.public_numbers() - dsa_t = (self.key.key_size // 8 - 64) // 8 - if dsa_t > 8: - raise ValueError("unsupported DSA key size") - octets = 64 + dsa_t * 8 - res = struct.pack("!B", dsa_t) - res += pn.parameter_numbers.q.to_bytes(20, "big") - res += pn.parameter_numbers.p.to_bytes(octets, "big") - res += pn.parameter_numbers.g.to_bytes(octets, "big") - res += pn.y.to_bytes(octets, "big") - return res - - @classmethod - def from_dnskey(cls, key: DNSKEY) -> "PublicDSA": - cls._ensure_algorithm_key_combination(key) - keyptr = key.key - (t,) = struct.unpack("!B", keyptr[0:1]) - keyptr = keyptr[1:] - octets = 64 + t * 8 - dsa_q = keyptr[0:20] - keyptr = keyptr[20:] - dsa_p = keyptr[0:octets] - keyptr = keyptr[octets:] - dsa_g = keyptr[0:octets] - keyptr = keyptr[octets:] - dsa_y = keyptr[0:octets] - return cls( - key=dsa.DSAPublicNumbers( # type: ignore - int.from_bytes(dsa_y, "big"), - dsa.DSAParameterNumbers( - int.from_bytes(dsa_p, "big"), - int.from_bytes(dsa_q, "big"), - int.from_bytes(dsa_g, "big"), - ), - ).public_key(default_backend()), - ) - - -class PrivateDSA(CryptographyPrivateKey): - key: dsa.DSAPrivateKey - key_cls = dsa.DSAPrivateKey - public_cls = PublicDSA - - def sign( - self, - data: bytes, - verify: bool = False, - deterministic: bool = True, - ) -> bytes: - """Sign using a private key per RFC 2536, section 3.""" - public_dsa_key = self.key.public_key() - if public_dsa_key.key_size > 1024: - raise ValueError("DSA key size overflow") - der_signature = self.key.sign(data, self.public_cls.chosen_hash) - dsa_r, dsa_s = utils.decode_dss_signature(der_signature) - dsa_t = (public_dsa_key.key_size // 8 - 64) // 8 - octets = 20 - signature = ( - struct.pack("!B", dsa_t) - + int.to_bytes(dsa_r, length=octets, byteorder="big") - + int.to_bytes(dsa_s, length=octets, byteorder="big") - ) - if verify: - self.public_key().verify(signature, data) - return signature - - @classmethod - def generate(cls, key_size: int) -> "PrivateDSA": - return cls( - key=dsa.generate_private_key(key_size=key_size), - ) - - -class PublicDSANSEC3SHA1(PublicDSA): - algorithm = Algorithm.DSANSEC3SHA1 - - -class PrivateDSANSEC3SHA1(PrivateDSA): - public_cls = PublicDSANSEC3SHA1 diff --git a/venv/Lib/site-packages/dns/dnssecalgs/ecdsa.py b/venv/Lib/site-packages/dns/dnssecalgs/ecdsa.py deleted file mode 100644 index 86d5764..0000000 --- a/venv/Lib/site-packages/dns/dnssecalgs/ecdsa.py +++ /dev/null @@ -1,97 +0,0 @@ -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import ec, utils - -from dns.dnssecalgs.cryptography import CryptographyPrivateKey, CryptographyPublicKey -from dns.dnssectypes import Algorithm -from dns.rdtypes.ANY.DNSKEY import DNSKEY - - -class PublicECDSA(CryptographyPublicKey): - key: ec.EllipticCurvePublicKey - key_cls = ec.EllipticCurvePublicKey - algorithm: Algorithm - chosen_hash: hashes.HashAlgorithm - curve: ec.EllipticCurve - octets: int - - def verify(self, signature: bytes, data: bytes) -> None: - sig_r = signature[0 : self.octets] - sig_s = signature[self.octets :] - sig = utils.encode_dss_signature( - int.from_bytes(sig_r, "big"), int.from_bytes(sig_s, "big") - ) - self.key.verify(sig, data, ec.ECDSA(self.chosen_hash)) - - def encode_key_bytes(self) -> bytes: - """Encode a public key per RFC 6605, section 4.""" - pn = self.key.public_numbers() - return pn.x.to_bytes(self.octets, "big") + pn.y.to_bytes(self.octets, "big") - - @classmethod - def from_dnskey(cls, key: DNSKEY) -> "PublicECDSA": - cls._ensure_algorithm_key_combination(key) - ecdsa_x = key.key[0 : cls.octets] - ecdsa_y = key.key[cls.octets : cls.octets * 2] - return cls( - key=ec.EllipticCurvePublicNumbers( - curve=cls.curve, - x=int.from_bytes(ecdsa_x, "big"), - y=int.from_bytes(ecdsa_y, "big"), - ).public_key(default_backend()), - ) - - -class PrivateECDSA(CryptographyPrivateKey): - key: ec.EllipticCurvePrivateKey - key_cls = ec.EllipticCurvePrivateKey - public_cls = PublicECDSA - - def sign( - self, - data: bytes, - verify: bool = False, - deterministic: bool = True, - ) -> bytes: - """Sign using a private key per RFC 6605, section 4.""" - algorithm = ec.ECDSA( - self.public_cls.chosen_hash, deterministic_signing=deterministic - ) - der_signature = self.key.sign(data, algorithm) - dsa_r, dsa_s = utils.decode_dss_signature(der_signature) - signature = int.to_bytes( - dsa_r, length=self.public_cls.octets, byteorder="big" - ) + int.to_bytes(dsa_s, length=self.public_cls.octets, byteorder="big") - if verify: - self.public_key().verify(signature, data) - return signature - - @classmethod - def generate(cls) -> "PrivateECDSA": - return cls( - key=ec.generate_private_key( - curve=cls.public_cls.curve, backend=default_backend() - ), - ) - - -class PublicECDSAP256SHA256(PublicECDSA): - algorithm = Algorithm.ECDSAP256SHA256 - chosen_hash = hashes.SHA256() - curve = ec.SECP256R1() - octets = 32 - - -class PrivateECDSAP256SHA256(PrivateECDSA): - public_cls = PublicECDSAP256SHA256 - - -class PublicECDSAP384SHA384(PublicECDSA): - algorithm = Algorithm.ECDSAP384SHA384 - chosen_hash = hashes.SHA384() - curve = ec.SECP384R1() - octets = 48 - - -class PrivateECDSAP384SHA384(PrivateECDSA): - public_cls = PublicECDSAP384SHA384 diff --git a/venv/Lib/site-packages/dns/dnssecalgs/eddsa.py b/venv/Lib/site-packages/dns/dnssecalgs/eddsa.py deleted file mode 100644 index 604bcbf..0000000 --- a/venv/Lib/site-packages/dns/dnssecalgs/eddsa.py +++ /dev/null @@ -1,70 +0,0 @@ -from typing import Type - -from cryptography.hazmat.primitives import serialization -from cryptography.hazmat.primitives.asymmetric import ed448, ed25519 - -from dns.dnssecalgs.cryptography import CryptographyPrivateKey, CryptographyPublicKey -from dns.dnssectypes import Algorithm -from dns.rdtypes.ANY.DNSKEY import DNSKEY - - -class PublicEDDSA(CryptographyPublicKey): - def verify(self, signature: bytes, data: bytes) -> None: - self.key.verify(signature, data) - - def encode_key_bytes(self) -> bytes: - """Encode a public key per RFC 8080, section 3.""" - return self.key.public_bytes( - encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw - ) - - @classmethod - def from_dnskey(cls, key: DNSKEY) -> "PublicEDDSA": - cls._ensure_algorithm_key_combination(key) - return cls( - key=cls.key_cls.from_public_bytes(key.key), - ) - - -class PrivateEDDSA(CryptographyPrivateKey): - public_cls: Type[PublicEDDSA] - - def sign( - self, - data: bytes, - verify: bool = False, - deterministic: bool = True, - ) -> bytes: - """Sign using a private key per RFC 8080, section 4.""" - signature = self.key.sign(data) - if verify: - self.public_key().verify(signature, data) - return signature - - @classmethod - def generate(cls) -> "PrivateEDDSA": - return cls(key=cls.key_cls.generate()) - - -class PublicED25519(PublicEDDSA): - key: ed25519.Ed25519PublicKey - key_cls = ed25519.Ed25519PublicKey - algorithm = Algorithm.ED25519 - - -class PrivateED25519(PrivateEDDSA): - key: ed25519.Ed25519PrivateKey - key_cls = ed25519.Ed25519PrivateKey - public_cls = PublicED25519 - - -class PublicED448(PublicEDDSA): - key: ed448.Ed448PublicKey - key_cls = ed448.Ed448PublicKey - algorithm = Algorithm.ED448 - - -class PrivateED448(PrivateEDDSA): - key: ed448.Ed448PrivateKey - key_cls = ed448.Ed448PrivateKey - public_cls = PublicED448 diff --git a/venv/Lib/site-packages/dns/dnssecalgs/rsa.py b/venv/Lib/site-packages/dns/dnssecalgs/rsa.py deleted file mode 100644 index 27537aa..0000000 --- a/venv/Lib/site-packages/dns/dnssecalgs/rsa.py +++ /dev/null @@ -1,124 +0,0 @@ -import math -import struct - -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import padding, rsa - -from dns.dnssecalgs.cryptography import CryptographyPrivateKey, CryptographyPublicKey -from dns.dnssectypes import Algorithm -from dns.rdtypes.ANY.DNSKEY import DNSKEY - - -class PublicRSA(CryptographyPublicKey): - key: rsa.RSAPublicKey - key_cls = rsa.RSAPublicKey - algorithm: Algorithm - chosen_hash: hashes.HashAlgorithm - - def verify(self, signature: bytes, data: bytes) -> None: - self.key.verify(signature, data, padding.PKCS1v15(), self.chosen_hash) - - def encode_key_bytes(self) -> bytes: - """Encode a public key per RFC 3110, section 2.""" - pn = self.key.public_numbers() - _exp_len = math.ceil(int.bit_length(pn.e) / 8) - exp = int.to_bytes(pn.e, length=_exp_len, byteorder="big") - if _exp_len > 255: - exp_header = b"\0" + struct.pack("!H", _exp_len) - else: - exp_header = struct.pack("!B", _exp_len) - if pn.n.bit_length() < 512 or pn.n.bit_length() > 4096: - raise ValueError("unsupported RSA key length") - return exp_header + exp + pn.n.to_bytes((pn.n.bit_length() + 7) // 8, "big") - - @classmethod - def from_dnskey(cls, key: DNSKEY) -> "PublicRSA": - cls._ensure_algorithm_key_combination(key) - keyptr = key.key - (bytes_,) = struct.unpack("!B", keyptr[0:1]) - keyptr = keyptr[1:] - if bytes_ == 0: - (bytes_,) = struct.unpack("!H", keyptr[0:2]) - keyptr = keyptr[2:] - rsa_e = keyptr[0:bytes_] - rsa_n = keyptr[bytes_:] - return cls( - key=rsa.RSAPublicNumbers( - int.from_bytes(rsa_e, "big"), int.from_bytes(rsa_n, "big") - ).public_key(default_backend()) - ) - - -class PrivateRSA(CryptographyPrivateKey): - key: rsa.RSAPrivateKey - key_cls = rsa.RSAPrivateKey - public_cls = PublicRSA - default_public_exponent = 65537 - - def sign( - self, - data: bytes, - verify: bool = False, - deterministic: bool = True, - ) -> bytes: - """Sign using a private key per RFC 3110, section 3.""" - signature = self.key.sign(data, padding.PKCS1v15(), self.public_cls.chosen_hash) - if verify: - self.public_key().verify(signature, data) - return signature - - @classmethod - def generate(cls, key_size: int) -> "PrivateRSA": - return cls( - key=rsa.generate_private_key( - public_exponent=cls.default_public_exponent, - key_size=key_size, - backend=default_backend(), - ) - ) - - -class PublicRSAMD5(PublicRSA): - algorithm = Algorithm.RSAMD5 - chosen_hash = hashes.MD5() - - -class PrivateRSAMD5(PrivateRSA): - public_cls = PublicRSAMD5 - - -class PublicRSASHA1(PublicRSA): - algorithm = Algorithm.RSASHA1 - chosen_hash = hashes.SHA1() - - -class PrivateRSASHA1(PrivateRSA): - public_cls = PublicRSASHA1 - - -class PublicRSASHA1NSEC3SHA1(PublicRSA): - algorithm = Algorithm.RSASHA1NSEC3SHA1 - chosen_hash = hashes.SHA1() - - -class PrivateRSASHA1NSEC3SHA1(PrivateRSA): - public_cls = PublicRSASHA1NSEC3SHA1 - - -class PublicRSASHA256(PublicRSA): - algorithm = Algorithm.RSASHA256 - chosen_hash = hashes.SHA256() - - -class PrivateRSASHA256(PrivateRSA): - public_cls = PublicRSASHA256 - - -class PublicRSASHA512(PublicRSA): - algorithm = Algorithm.RSASHA512 - chosen_hash = hashes.SHA512() - - -class PrivateRSASHA512(PrivateRSA): - public_cls = PublicRSASHA512 diff --git a/venv/Lib/site-packages/dns/dnssectypes.py b/venv/Lib/site-packages/dns/dnssectypes.py deleted file mode 100644 index 02131e0..0000000 --- a/venv/Lib/site-packages/dns/dnssectypes.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Common DNSSEC-related types.""" - -# This is a separate file to avoid import circularity between dns.dnssec and -# the implementations of the DS and DNSKEY types. - -import dns.enum - - -class Algorithm(dns.enum.IntEnum): - RSAMD5 = 1 - DH = 2 - DSA = 3 - ECC = 4 - RSASHA1 = 5 - DSANSEC3SHA1 = 6 - RSASHA1NSEC3SHA1 = 7 - RSASHA256 = 8 - RSASHA512 = 10 - ECCGOST = 12 - ECDSAP256SHA256 = 13 - ECDSAP384SHA384 = 14 - ED25519 = 15 - ED448 = 16 - INDIRECT = 252 - PRIVATEDNS = 253 - PRIVATEOID = 254 - - @classmethod - def _maximum(cls): - return 255 - - -class DSDigest(dns.enum.IntEnum): - """DNSSEC Delegation Signer Digest Algorithm""" - - NULL = 0 - SHA1 = 1 - SHA256 = 2 - GOST = 3 - SHA384 = 4 - - @classmethod - def _maximum(cls): - return 255 - - -class NSEC3Hash(dns.enum.IntEnum): - """NSEC3 hash algorithm""" - - SHA1 = 1 - - @classmethod - def _maximum(cls): - return 255 diff --git a/venv/Lib/site-packages/dns/e164.py b/venv/Lib/site-packages/dns/e164.py deleted file mode 100644 index 453736d..0000000 --- a/venv/Lib/site-packages/dns/e164.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS E.164 helpers.""" - -from typing import Iterable, Optional, Union - -import dns.exception -import dns.name -import dns.resolver - -#: The public E.164 domain. -public_enum_domain = dns.name.from_text("e164.arpa.") - - -def from_e164( - text: str, origin: Optional[dns.name.Name] = public_enum_domain -) -> dns.name.Name: - """Convert an E.164 number in textual form into a Name object whose - value is the ENUM domain name for that number. - - Non-digits in the text are ignored, i.e. "16505551212", - "+1.650.555.1212" and "1 (650) 555-1212" are all the same. - - *text*, a ``str``, is an E.164 number in textual form. - - *origin*, a ``dns.name.Name``, the domain in which the number - should be constructed. The default is ``e164.arpa.``. - - Returns a ``dns.name.Name``. - """ - - parts = [d for d in text if d.isdigit()] - parts.reverse() - return dns.name.from_text(".".join(parts), origin=origin) - - -def to_e164( - name: dns.name.Name, - origin: Optional[dns.name.Name] = public_enum_domain, - want_plus_prefix: bool = True, -) -> str: - """Convert an ENUM domain name into an E.164 number. - - Note that dnspython does not have any information about preferred - number formats within national numbering plans, so all numbers are - emitted as a simple string of digits, prefixed by a '+' (unless - *want_plus_prefix* is ``False``). - - *name* is a ``dns.name.Name``, the ENUM domain name. - - *origin* is a ``dns.name.Name``, a domain containing the ENUM - domain name. The name is relativized to this domain before being - converted to text. If ``None``, no relativization is done. - - *want_plus_prefix* is a ``bool``. If True, add a '+' to the beginning of - the returned number. - - Returns a ``str``. - - """ - if origin is not None: - name = name.relativize(origin) - dlabels = [d for d in name.labels if d.isdigit() and len(d) == 1] - if len(dlabels) != len(name.labels): - raise dns.exception.SyntaxError("non-digit labels in ENUM domain name") - dlabels.reverse() - text = b"".join(dlabels) - if want_plus_prefix: - text = b"+" + text - return text.decode() - - -def query( - number: str, - domains: Iterable[Union[dns.name.Name, str]], - resolver: Optional[dns.resolver.Resolver] = None, -) -> dns.resolver.Answer: - """Look for NAPTR RRs for the specified number in the specified domains. - - e.g. lookup('16505551212', ['e164.dnspython.org.', 'e164.arpa.']) - - *number*, a ``str`` is the number to look for. - - *domains* is an iterable containing ``dns.name.Name`` values. - - *resolver*, a ``dns.resolver.Resolver``, is the resolver to use. If - ``None``, the default resolver is used. - """ - - if resolver is None: - resolver = dns.resolver.get_default_resolver() - e_nx = dns.resolver.NXDOMAIN() - for domain in domains: - if isinstance(domain, str): - domain = dns.name.from_text(domain) - qname = dns.e164.from_e164(number, domain) - try: - return resolver.resolve(qname, "NAPTR") - except dns.resolver.NXDOMAIN as e: - e_nx += e - raise e_nx diff --git a/venv/Lib/site-packages/dns/edns.py b/venv/Lib/site-packages/dns/edns.py deleted file mode 100644 index f7d9ff9..0000000 --- a/venv/Lib/site-packages/dns/edns.py +++ /dev/null @@ -1,572 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2009-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""EDNS Options""" - -import binascii -import math -import socket -import struct -from typing import Any, Dict, Optional, Union - -import dns.enum -import dns.inet -import dns.rdata -import dns.wire - - -class OptionType(dns.enum.IntEnum): - #: NSID - NSID = 3 - #: DAU - DAU = 5 - #: DHU - DHU = 6 - #: N3U - N3U = 7 - #: ECS (client-subnet) - ECS = 8 - #: EXPIRE - EXPIRE = 9 - #: COOKIE - COOKIE = 10 - #: KEEPALIVE - KEEPALIVE = 11 - #: PADDING - PADDING = 12 - #: CHAIN - CHAIN = 13 - #: EDE (extended-dns-error) - EDE = 15 - #: REPORTCHANNEL - REPORTCHANNEL = 18 - - @classmethod - def _maximum(cls): - return 65535 - - -class Option: - """Base class for all EDNS option types.""" - - def __init__(self, otype: Union[OptionType, str]): - """Initialize an option. - - *otype*, a ``dns.edns.OptionType``, is the option type. - """ - self.otype = OptionType.make(otype) - - def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]: - """Convert an option to wire format. - - Returns a ``bytes`` or ``None``. - - """ - raise NotImplementedError # pragma: no cover - - def to_text(self) -> str: - raise NotImplementedError # pragma: no cover - - @classmethod - def from_wire_parser(cls, otype: OptionType, parser: "dns.wire.Parser") -> "Option": - """Build an EDNS option object from wire format. - - *otype*, a ``dns.edns.OptionType``, is the option type. - - *parser*, a ``dns.wire.Parser``, the parser, which should be - restructed to the option length. - - Returns a ``dns.edns.Option``. - """ - raise NotImplementedError # pragma: no cover - - def _cmp(self, other): - """Compare an EDNS option with another option of the same type. - - Returns < 0 if < *other*, 0 if == *other*, and > 0 if > *other*. - """ - wire = self.to_wire() - owire = other.to_wire() - if wire == owire: - return 0 - if wire > owire: - return 1 - return -1 - - def __eq__(self, other): - if not isinstance(other, Option): - return False - if self.otype != other.otype: - return False - return self._cmp(other) == 0 - - def __ne__(self, other): - if not isinstance(other, Option): - return True - if self.otype != other.otype: - return True - return self._cmp(other) != 0 - - def __lt__(self, other): - if not isinstance(other, Option) or self.otype != other.otype: - return NotImplemented - return self._cmp(other) < 0 - - def __le__(self, other): - if not isinstance(other, Option) or self.otype != other.otype: - return NotImplemented - return self._cmp(other) <= 0 - - def __ge__(self, other): - if not isinstance(other, Option) or self.otype != other.otype: - return NotImplemented - return self._cmp(other) >= 0 - - def __gt__(self, other): - if not isinstance(other, Option) or self.otype != other.otype: - return NotImplemented - return self._cmp(other) > 0 - - def __str__(self): - return self.to_text() - - -class GenericOption(Option): # lgtm[py/missing-equals] - """Generic Option Class - - This class is used for EDNS option types for which we have no better - implementation. - """ - - def __init__(self, otype: Union[OptionType, str], data: Union[bytes, str]): - super().__init__(otype) - self.data = dns.rdata.Rdata._as_bytes(data, True) - - def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]: - if file: - file.write(self.data) - return None - else: - return self.data - - def to_text(self) -> str: - return "Generic %d" % self.otype - - @classmethod - def from_wire_parser( - cls, otype: Union[OptionType, str], parser: "dns.wire.Parser" - ) -> Option: - return cls(otype, parser.get_remaining()) - - -class ECSOption(Option): # lgtm[py/missing-equals] - """EDNS Client Subnet (ECS, RFC7871)""" - - def __init__(self, address: str, srclen: Optional[int] = None, scopelen: int = 0): - """*address*, a ``str``, is the client address information. - - *srclen*, an ``int``, the source prefix length, which is the - leftmost number of bits of the address to be used for the - lookup. The default is 24 for IPv4 and 56 for IPv6. - - *scopelen*, an ``int``, the scope prefix length. This value - must be 0 in queries, and should be set in responses. - """ - - super().__init__(OptionType.ECS) - af = dns.inet.af_for_address(address) - - if af == socket.AF_INET6: - self.family = 2 - if srclen is None: - srclen = 56 - address = dns.rdata.Rdata._as_ipv6_address(address) - srclen = dns.rdata.Rdata._as_int(srclen, 0, 128) - scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 128) - elif af == socket.AF_INET: - self.family = 1 - if srclen is None: - srclen = 24 - address = dns.rdata.Rdata._as_ipv4_address(address) - srclen = dns.rdata.Rdata._as_int(srclen, 0, 32) - scopelen = dns.rdata.Rdata._as_int(scopelen, 0, 32) - else: # pragma: no cover (this will never happen) - raise ValueError("Bad address family") - - assert srclen is not None - self.address = address - self.srclen = srclen - self.scopelen = scopelen - - addrdata = dns.inet.inet_pton(af, address) - nbytes = int(math.ceil(srclen / 8.0)) - - # Truncate to srclen and pad to the end of the last octet needed - # See RFC section 6 - self.addrdata = addrdata[:nbytes] - nbits = srclen % 8 - if nbits != 0: - last = struct.pack("B", ord(self.addrdata[-1:]) & (0xFF << (8 - nbits))) - self.addrdata = self.addrdata[:-1] + last - - def to_text(self) -> str: - return f"ECS {self.address}/{self.srclen} scope/{self.scopelen}" - - @staticmethod - def from_text(text: str) -> Option: - """Convert a string into a `dns.edns.ECSOption` - - *text*, a `str`, the text form of the option. - - Returns a `dns.edns.ECSOption`. - - Examples: - - >>> import dns.edns - >>> - >>> # basic example - >>> dns.edns.ECSOption.from_text('1.2.3.4/24') - >>> - >>> # also understands scope - >>> dns.edns.ECSOption.from_text('1.2.3.4/24/32') - >>> - >>> # IPv6 - >>> dns.edns.ECSOption.from_text('2001:4b98::1/64/64') - >>> - >>> # it understands results from `dns.edns.ECSOption.to_text()` - >>> dns.edns.ECSOption.from_text('ECS 1.2.3.4/24/32') - """ - optional_prefix = "ECS" - tokens = text.split() - ecs_text = None - if len(tokens) == 1: - ecs_text = tokens[0] - elif len(tokens) == 2: - if tokens[0] != optional_prefix: - raise ValueError(f'could not parse ECS from "{text}"') - ecs_text = tokens[1] - else: - raise ValueError(f'could not parse ECS from "{text}"') - n_slashes = ecs_text.count("/") - if n_slashes == 1: - address, tsrclen = ecs_text.split("/") - tscope = "0" - elif n_slashes == 2: - address, tsrclen, tscope = ecs_text.split("/") - else: - raise ValueError(f'could not parse ECS from "{text}"') - try: - scope = int(tscope) - except ValueError: - raise ValueError("invalid scope " + f'"{tscope}": scope must be an integer') - try: - srclen = int(tsrclen) - except ValueError: - raise ValueError( - "invalid srclen " + f'"{tsrclen}": srclen must be an integer' - ) - return ECSOption(address, srclen, scope) - - def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]: - value = ( - struct.pack("!HBB", self.family, self.srclen, self.scopelen) + self.addrdata - ) - if file: - file.write(value) - return None - else: - return value - - @classmethod - def from_wire_parser( - cls, otype: Union[OptionType, str], parser: "dns.wire.Parser" - ) -> Option: - family, src, scope = parser.get_struct("!HBB") - addrlen = int(math.ceil(src / 8.0)) - prefix = parser.get_bytes(addrlen) - if family == 1: - pad = 4 - addrlen - addr = dns.ipv4.inet_ntoa(prefix + b"\x00" * pad) - elif family == 2: - pad = 16 - addrlen - addr = dns.ipv6.inet_ntoa(prefix + b"\x00" * pad) - else: - raise ValueError("unsupported family") - - return cls(addr, src, scope) - - -class EDECode(dns.enum.IntEnum): - OTHER = 0 - UNSUPPORTED_DNSKEY_ALGORITHM = 1 - UNSUPPORTED_DS_DIGEST_TYPE = 2 - STALE_ANSWER = 3 - FORGED_ANSWER = 4 - DNSSEC_INDETERMINATE = 5 - DNSSEC_BOGUS = 6 - SIGNATURE_EXPIRED = 7 - SIGNATURE_NOT_YET_VALID = 8 - DNSKEY_MISSING = 9 - RRSIGS_MISSING = 10 - NO_ZONE_KEY_BIT_SET = 11 - NSEC_MISSING = 12 - CACHED_ERROR = 13 - NOT_READY = 14 - BLOCKED = 15 - CENSORED = 16 - FILTERED = 17 - PROHIBITED = 18 - STALE_NXDOMAIN_ANSWER = 19 - NOT_AUTHORITATIVE = 20 - NOT_SUPPORTED = 21 - NO_REACHABLE_AUTHORITY = 22 - NETWORK_ERROR = 23 - INVALID_DATA = 24 - - @classmethod - def _maximum(cls): - return 65535 - - -class EDEOption(Option): # lgtm[py/missing-equals] - """Extended DNS Error (EDE, RFC8914)""" - - _preserve_case = {"DNSKEY", "DS", "DNSSEC", "RRSIGs", "NSEC", "NXDOMAIN"} - - def __init__(self, code: Union[EDECode, str], text: Optional[str] = None): - """*code*, a ``dns.edns.EDECode`` or ``str``, the info code of the - extended error. - - *text*, a ``str`` or ``None``, specifying additional information about - the error. - """ - - super().__init__(OptionType.EDE) - - self.code = EDECode.make(code) - if text is not None and not isinstance(text, str): - raise ValueError("text must be string or None") - self.text = text - - def to_text(self) -> str: - output = f"EDE {self.code}" - if self.code in EDECode: - desc = EDECode.to_text(self.code) - desc = " ".join( - word if word in self._preserve_case else word.title() - for word in desc.split("_") - ) - output += f" ({desc})" - if self.text is not None: - output += f": {self.text}" - return output - - def to_wire(self, file: Optional[Any] = None) -> Optional[bytes]: - value = struct.pack("!H", self.code) - if self.text is not None: - value += self.text.encode("utf8") - - if file: - file.write(value) - return None - else: - return value - - @classmethod - def from_wire_parser( - cls, otype: Union[OptionType, str], parser: "dns.wire.Parser" - ) -> Option: - code = EDECode.make(parser.get_uint16()) - text = parser.get_remaining() - - if text: - if text[-1] == 0: # text MAY be null-terminated - text = text[:-1] - btext = text.decode("utf8") - else: - btext = None - - return cls(code, btext) - - -class NSIDOption(Option): - def __init__(self, nsid: bytes): - super().__init__(OptionType.NSID) - self.nsid = nsid - - def to_wire(self, file: Any = None) -> Optional[bytes]: - if file: - file.write(self.nsid) - return None - else: - return self.nsid - - def to_text(self) -> str: - if all(c >= 0x20 and c <= 0x7E for c in self.nsid): - # All ASCII printable, so it's probably a string. - value = self.nsid.decode() - else: - value = binascii.hexlify(self.nsid).decode() - return f"NSID {value}" - - @classmethod - def from_wire_parser( - cls, otype: Union[OptionType, str], parser: dns.wire.Parser - ) -> Option: - return cls(parser.get_remaining()) - - -class CookieOption(Option): - def __init__(self, client: bytes, server: bytes): - super().__init__(dns.edns.OptionType.COOKIE) - self.client = client - self.server = server - if len(client) != 8: - raise ValueError("client cookie must be 8 bytes") - if len(server) != 0 and (len(server) < 8 or len(server) > 32): - raise ValueError("server cookie must be empty or between 8 and 32 bytes") - - def to_wire(self, file: Any = None) -> Optional[bytes]: - if file: - file.write(self.client) - if len(self.server) > 0: - file.write(self.server) - return None - else: - return self.client + self.server - - def to_text(self) -> str: - client = binascii.hexlify(self.client).decode() - if len(self.server) > 0: - server = binascii.hexlify(self.server).decode() - else: - server = "" - return f"COOKIE {client}{server}" - - @classmethod - def from_wire_parser( - cls, otype: Union[OptionType, str], parser: dns.wire.Parser - ) -> Option: - return cls(parser.get_bytes(8), parser.get_remaining()) - - -class ReportChannelOption(Option): - # RFC 9567 - def __init__(self, agent_domain: dns.name.Name): - super().__init__(OptionType.REPORTCHANNEL) - self.agent_domain = agent_domain - - def to_wire(self, file: Any = None) -> Optional[bytes]: - return self.agent_domain.to_wire(file) - - def to_text(self) -> str: - return "REPORTCHANNEL " + self.agent_domain.to_text() - - @classmethod - def from_wire_parser( - cls, otype: Union[OptionType, str], parser: dns.wire.Parser - ) -> Option: - return cls(parser.get_name()) - - -_type_to_class: Dict[OptionType, Any] = { - OptionType.ECS: ECSOption, - OptionType.EDE: EDEOption, - OptionType.NSID: NSIDOption, - OptionType.COOKIE: CookieOption, - OptionType.REPORTCHANNEL: ReportChannelOption, -} - - -def get_option_class(otype: OptionType) -> Any: - """Return the class for the specified option type. - - The GenericOption class is used if a more specific class is not - known. - """ - - cls = _type_to_class.get(otype) - if cls is None: - cls = GenericOption - return cls - - -def option_from_wire_parser( - otype: Union[OptionType, str], parser: "dns.wire.Parser" -) -> Option: - """Build an EDNS option object from wire format. - - *otype*, an ``int``, is the option type. - - *parser*, a ``dns.wire.Parser``, the parser, which should be - restricted to the option length. - - Returns an instance of a subclass of ``dns.edns.Option``. - """ - otype = OptionType.make(otype) - cls = get_option_class(otype) - return cls.from_wire_parser(otype, parser) - - -def option_from_wire( - otype: Union[OptionType, str], wire: bytes, current: int, olen: int -) -> Option: - """Build an EDNS option object from wire format. - - *otype*, an ``int``, is the option type. - - *wire*, a ``bytes``, is the wire-format message. - - *current*, an ``int``, is the offset in *wire* of the beginning - of the rdata. - - *olen*, an ``int``, is the length of the wire-format option data - - Returns an instance of a subclass of ``dns.edns.Option``. - """ - parser = dns.wire.Parser(wire, current) - with parser.restrict_to(olen): - return option_from_wire_parser(otype, parser) - - -def register_type(implementation: Any, otype: OptionType) -> None: - """Register the implementation of an option type. - - *implementation*, a ``class``, is a subclass of ``dns.edns.Option``. - - *otype*, an ``int``, is the option type. - """ - - _type_to_class[otype] = implementation - - -### BEGIN generated OptionType constants - -NSID = OptionType.NSID -DAU = OptionType.DAU -DHU = OptionType.DHU -N3U = OptionType.N3U -ECS = OptionType.ECS -EXPIRE = OptionType.EXPIRE -COOKIE = OptionType.COOKIE -KEEPALIVE = OptionType.KEEPALIVE -PADDING = OptionType.PADDING -CHAIN = OptionType.CHAIN -EDE = OptionType.EDE -REPORTCHANNEL = OptionType.REPORTCHANNEL - -### END generated OptionType constants diff --git a/venv/Lib/site-packages/dns/entropy.py b/venv/Lib/site-packages/dns/entropy.py deleted file mode 100644 index 4dcdc62..0000000 --- a/venv/Lib/site-packages/dns/entropy.py +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2009-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import hashlib -import os -import random -import threading -import time -from typing import Any, Optional - - -class EntropyPool: - # This is an entropy pool for Python implementations that do not - # have a working SystemRandom. I'm not sure there are any, but - # leaving this code doesn't hurt anything as the library code - # is used if present. - - def __init__(self, seed: Optional[bytes] = None): - self.pool_index = 0 - self.digest: Optional[bytearray] = None - self.next_byte = 0 - self.lock = threading.Lock() - self.hash = hashlib.sha1() - self.hash_len = 20 - self.pool = bytearray(b"\0" * self.hash_len) - if seed is not None: - self._stir(seed) - self.seeded = True - self.seed_pid = os.getpid() - else: - self.seeded = False - self.seed_pid = 0 - - def _stir(self, entropy: bytes) -> None: - for c in entropy: - if self.pool_index == self.hash_len: - self.pool_index = 0 - b = c & 0xFF - self.pool[self.pool_index] ^= b - self.pool_index += 1 - - def stir(self, entropy: bytes) -> None: - with self.lock: - self._stir(entropy) - - def _maybe_seed(self) -> None: - if not self.seeded or self.seed_pid != os.getpid(): - try: - seed = os.urandom(16) - except Exception: # pragma: no cover - try: - with open("/dev/urandom", "rb", 0) as r: - seed = r.read(16) - except Exception: - seed = str(time.time()).encode() - self.seeded = True - self.seed_pid = os.getpid() - self.digest = None - seed = bytearray(seed) - self._stir(seed) - - def random_8(self) -> int: - with self.lock: - self._maybe_seed() - if self.digest is None or self.next_byte == self.hash_len: - self.hash.update(bytes(self.pool)) - self.digest = bytearray(self.hash.digest()) - self._stir(self.digest) - self.next_byte = 0 - value = self.digest[self.next_byte] - self.next_byte += 1 - return value - - def random_16(self) -> int: - return self.random_8() * 256 + self.random_8() - - def random_32(self) -> int: - return self.random_16() * 65536 + self.random_16() - - def random_between(self, first: int, last: int) -> int: - size = last - first + 1 - if size > 4294967296: - raise ValueError("too big") - if size > 65536: - rand = self.random_32 - max = 4294967295 - elif size > 256: - rand = self.random_16 - max = 65535 - else: - rand = self.random_8 - max = 255 - return first + size * rand() // (max + 1) - - -pool = EntropyPool() - -system_random: Optional[Any] -try: - system_random = random.SystemRandom() -except Exception: # pragma: no cover - system_random = None - - -def random_16() -> int: - if system_random is not None: - return system_random.randrange(0, 65536) - else: - return pool.random_16() - - -def between(first: int, last: int) -> int: - if system_random is not None: - return system_random.randrange(first, last + 1) - else: - return pool.random_between(first, last) diff --git a/venv/Lib/site-packages/dns/enum.py b/venv/Lib/site-packages/dns/enum.py deleted file mode 100644 index 71461f1..0000000 --- a/venv/Lib/site-packages/dns/enum.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import enum -from typing import Type, TypeVar, Union - -TIntEnum = TypeVar("TIntEnum", bound="IntEnum") - - -class IntEnum(enum.IntEnum): - @classmethod - def _missing_(cls, value): - cls._check_value(value) - val = int.__new__(cls, value) - val._name_ = cls._extra_to_text(value, None) or f"{cls._prefix()}{value}" - val._value_ = value - return val - - @classmethod - def _check_value(cls, value): - max = cls._maximum() - if not isinstance(value, int): - raise TypeError - if value < 0 or value > max: - name = cls._short_name() - raise ValueError(f"{name} must be an int between >= 0 and <= {max}") - - @classmethod - def from_text(cls: Type[TIntEnum], text: str) -> TIntEnum: - text = text.upper() - try: - return cls[text] - except KeyError: - pass - value = cls._extra_from_text(text) - if value: - return value - prefix = cls._prefix() - if text.startswith(prefix) and text[len(prefix) :].isdigit(): - value = int(text[len(prefix) :]) - cls._check_value(value) - try: - return cls(value) - except ValueError: - return value - raise cls._unknown_exception_class() - - @classmethod - def to_text(cls: Type[TIntEnum], value: int) -> str: - cls._check_value(value) - try: - text = cls(value).name - except ValueError: - text = None - text = cls._extra_to_text(value, text) - if text is None: - text = f"{cls._prefix()}{value}" - return text - - @classmethod - def make(cls: Type[TIntEnum], value: Union[int, str]) -> TIntEnum: - """Convert text or a value into an enumerated type, if possible. - - *value*, the ``int`` or ``str`` to convert. - - Raises a class-specific exception if a ``str`` is provided that - cannot be converted. - - Raises ``ValueError`` if the value is out of range. - - Returns an enumeration from the calling class corresponding to the - value, if one is defined, or an ``int`` otherwise. - """ - - if isinstance(value, str): - return cls.from_text(value) - cls._check_value(value) - return cls(value) - - @classmethod - def _maximum(cls): - raise NotImplementedError # pragma: no cover - - @classmethod - def _short_name(cls): - return cls.__name__.lower() - - @classmethod - def _prefix(cls): - return "" - - @classmethod - def _extra_from_text(cls, text): # pylint: disable=W0613 - return None - - @classmethod - def _extra_to_text(cls, value, current_text): # pylint: disable=W0613 - return current_text - - @classmethod - def _unknown_exception_class(cls): - return ValueError diff --git a/venv/Lib/site-packages/dns/exception.py b/venv/Lib/site-packages/dns/exception.py deleted file mode 100644 index 223f2d6..0000000 --- a/venv/Lib/site-packages/dns/exception.py +++ /dev/null @@ -1,169 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Common DNS Exceptions. - -Dnspython modules may also define their own exceptions, which will -always be subclasses of ``DNSException``. -""" - - -from typing import Optional, Set - - -class DNSException(Exception): - """Abstract base class shared by all dnspython exceptions. - - It supports two basic modes of operation: - - a) Old/compatible mode is used if ``__init__`` was called with - empty *kwargs*. In compatible mode all *args* are passed - to the standard Python Exception class as before and all *args* are - printed by the standard ``__str__`` implementation. Class variable - ``msg`` (or doc string if ``msg`` is ``None``) is returned from ``str()`` - if *args* is empty. - - b) New/parametrized mode is used if ``__init__`` was called with - non-empty *kwargs*. - In the new mode *args* must be empty and all kwargs must match - those set in class variable ``supp_kwargs``. All kwargs are stored inside - ``self.kwargs`` and used in a new ``__str__`` implementation to construct - a formatted message based on the ``fmt`` class variable, a ``string``. - - In the simplest case it is enough to override the ``supp_kwargs`` - and ``fmt`` class variables to get nice parametrized messages. - """ - - msg: Optional[str] = None # non-parametrized message - supp_kwargs: Set[str] = set() # accepted parameters for _fmt_kwargs (sanity check) - fmt: Optional[str] = None # message parametrized with results from _fmt_kwargs - - def __init__(self, *args, **kwargs): - self._check_params(*args, **kwargs) - if kwargs: - # This call to a virtual method from __init__ is ok in our usage - self.kwargs = self._check_kwargs(**kwargs) # lgtm[py/init-calls-subclass] - self.msg = str(self) - else: - self.kwargs = dict() # defined but empty for old mode exceptions - if self.msg is None: - # doc string is better implicit message than empty string - self.msg = self.__doc__ - if args: - super().__init__(*args) - else: - super().__init__(self.msg) - - def _check_params(self, *args, **kwargs): - """Old exceptions supported only args and not kwargs. - - For sanity we do not allow to mix old and new behavior.""" - if args or kwargs: - assert bool(args) != bool( - kwargs - ), "keyword arguments are mutually exclusive with positional args" - - def _check_kwargs(self, **kwargs): - if kwargs: - assert ( - set(kwargs.keys()) == self.supp_kwargs - ), f"following set of keyword args is required: {self.supp_kwargs}" - return kwargs - - def _fmt_kwargs(self, **kwargs): - """Format kwargs before printing them. - - Resulting dictionary has to have keys necessary for str.format call - on fmt class variable. - """ - fmtargs = {} - for kw, data in kwargs.items(): - if isinstance(data, (list, set)): - # convert list of to list of str() - fmtargs[kw] = list(map(str, data)) - if len(fmtargs[kw]) == 1: - # remove list brackets [] from single-item lists - fmtargs[kw] = fmtargs[kw].pop() - else: - fmtargs[kw] = data - return fmtargs - - def __str__(self): - if self.kwargs and self.fmt: - # provide custom message constructed from keyword arguments - fmtargs = self._fmt_kwargs(**self.kwargs) - return self.fmt.format(**fmtargs) - else: - # print *args directly in the same way as old DNSException - return super().__str__() - - -class FormError(DNSException): - """DNS message is malformed.""" - - -class SyntaxError(DNSException): - """Text input is malformed.""" - - -class UnexpectedEnd(SyntaxError): - """Text input ended unexpectedly.""" - - -class TooBig(DNSException): - """The DNS message is too big.""" - - -class Timeout(DNSException): - """The DNS operation timed out.""" - - supp_kwargs = {"timeout"} - fmt = "The DNS operation timed out after {timeout:.3f} seconds" - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - -class UnsupportedAlgorithm(DNSException): - """The DNSSEC algorithm is not supported.""" - - -class AlgorithmKeyMismatch(UnsupportedAlgorithm): - """The DNSSEC algorithm is not supported for the given key type.""" - - -class ValidationFailure(DNSException): - """The DNSSEC signature is invalid.""" - - -class DeniedByPolicy(DNSException): - """Denied by DNSSEC policy.""" - - -class ExceptionWrapper: - def __init__(self, exception_class): - self.exception_class = exception_class - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if exc_type is not None and not isinstance(exc_val, self.exception_class): - raise self.exception_class(str(exc_val)) from exc_val - return False diff --git a/venv/Lib/site-packages/dns/flags.py b/venv/Lib/site-packages/dns/flags.py deleted file mode 100644 index 4c60be1..0000000 --- a/venv/Lib/site-packages/dns/flags.py +++ /dev/null @@ -1,123 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Message Flags.""" - -import enum -from typing import Any - -# Standard DNS flags - - -class Flag(enum.IntFlag): - #: Query Response - QR = 0x8000 - #: Authoritative Answer - AA = 0x0400 - #: Truncated Response - TC = 0x0200 - #: Recursion Desired - RD = 0x0100 - #: Recursion Available - RA = 0x0080 - #: Authentic Data - AD = 0x0020 - #: Checking Disabled - CD = 0x0010 - - -# EDNS flags - - -class EDNSFlag(enum.IntFlag): - #: DNSSEC answer OK - DO = 0x8000 - - -def _from_text(text: str, enum_class: Any) -> int: - flags = 0 - tokens = text.split() - for t in tokens: - flags |= enum_class[t.upper()] - return flags - - -def _to_text(flags: int, enum_class: Any) -> str: - text_flags = [] - for k, v in enum_class.__members__.items(): - if flags & v != 0: - text_flags.append(k) - return " ".join(text_flags) - - -def from_text(text: str) -> int: - """Convert a space-separated list of flag text values into a flags - value. - - Returns an ``int`` - """ - - return _from_text(text, Flag) - - -def to_text(flags: int) -> str: - """Convert a flags value into a space-separated list of flag text - values. - - Returns a ``str``. - """ - - return _to_text(flags, Flag) - - -def edns_from_text(text: str) -> int: - """Convert a space-separated list of EDNS flag text values into a EDNS - flags value. - - Returns an ``int`` - """ - - return _from_text(text, EDNSFlag) - - -def edns_to_text(flags: int) -> str: - """Convert an EDNS flags value into a space-separated list of EDNS flag - text values. - - Returns a ``str``. - """ - - return _to_text(flags, EDNSFlag) - - -### BEGIN generated Flag constants - -QR = Flag.QR -AA = Flag.AA -TC = Flag.TC -RD = Flag.RD -RA = Flag.RA -AD = Flag.AD -CD = Flag.CD - -### END generated Flag constants - -### BEGIN generated EDNSFlag constants - -DO = EDNSFlag.DO - -### END generated EDNSFlag constants diff --git a/venv/Lib/site-packages/dns/grange.py b/venv/Lib/site-packages/dns/grange.py deleted file mode 100644 index a967ca4..0000000 --- a/venv/Lib/site-packages/dns/grange.py +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2012-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS GENERATE range conversion.""" - -from typing import Tuple - -import dns - - -def from_text(text: str) -> Tuple[int, int, int]: - """Convert the text form of a range in a ``$GENERATE`` statement to an - integer. - - *text*, a ``str``, the textual range in ``$GENERATE`` form. - - Returns a tuple of three ``int`` values ``(start, stop, step)``. - """ - - start = -1 - stop = -1 - step = 1 - cur = "" - state = 0 - # state 0 1 2 - # x - y / z - - if text and text[0] == "-": - raise dns.exception.SyntaxError("Start cannot be a negative number") - - for c in text: - if c == "-" and state == 0: - start = int(cur) - cur = "" - state = 1 - elif c == "/": - stop = int(cur) - cur = "" - state = 2 - elif c.isdigit(): - cur += c - else: - raise dns.exception.SyntaxError(f"Could not parse {c}") - - if state == 0: - raise dns.exception.SyntaxError("no stop value specified") - elif state == 1: - stop = int(cur) - else: - assert state == 2 - step = int(cur) - - assert step >= 1 - assert start >= 0 - if start > stop: - raise dns.exception.SyntaxError("start must be <= stop") - - return (start, stop, step) diff --git a/venv/Lib/site-packages/dns/immutable.py b/venv/Lib/site-packages/dns/immutable.py deleted file mode 100644 index 36b0362..0000000 --- a/venv/Lib/site-packages/dns/immutable.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import collections.abc -from typing import Any, Callable - -from dns._immutable_ctx import immutable - - -@immutable -class Dict(collections.abc.Mapping): # lgtm[py/missing-equals] - def __init__( - self, - dictionary: Any, - no_copy: bool = False, - map_factory: Callable[[], collections.abc.MutableMapping] = dict, - ): - """Make an immutable dictionary from the specified dictionary. - - If *no_copy* is `True`, then *dictionary* will be wrapped instead - of copied. Only set this if you are sure there will be no external - references to the dictionary. - """ - if no_copy and isinstance(dictionary, collections.abc.MutableMapping): - self._odict = dictionary - else: - self._odict = map_factory() - self._odict.update(dictionary) - self._hash = None - - def __getitem__(self, key): - return self._odict.__getitem__(key) - - def __hash__(self): # pylint: disable=invalid-hash-returned - if self._hash is None: - h = 0 - for key in sorted(self._odict.keys()): - h ^= hash(key) - object.__setattr__(self, "_hash", h) - # this does return an int, but pylint doesn't figure that out - return self._hash - - def __len__(self): - return len(self._odict) - - def __iter__(self): - return iter(self._odict) - - -def constify(o: Any) -> Any: - """ - Convert mutable types to immutable types. - """ - if isinstance(o, bytearray): - return bytes(o) - if isinstance(o, tuple): - try: - hash(o) - return o - except Exception: - return tuple(constify(elt) for elt in o) - if isinstance(o, list): - return tuple(constify(elt) for elt in o) - if isinstance(o, dict): - cdict = dict() - for k, v in o.items(): - cdict[k] = constify(v) - return Dict(cdict, True) - return o diff --git a/venv/Lib/site-packages/dns/inet.py b/venv/Lib/site-packages/dns/inet.py deleted file mode 100644 index 4a03f99..0000000 --- a/venv/Lib/site-packages/dns/inet.py +++ /dev/null @@ -1,197 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Generic Internet address helper functions.""" - -import socket -from typing import Any, Optional, Tuple - -import dns.ipv4 -import dns.ipv6 - -# We assume that AF_INET and AF_INET6 are always defined. We keep -# these here for the benefit of any old code (unlikely though that -# is!). -AF_INET = socket.AF_INET -AF_INET6 = socket.AF_INET6 - - -def inet_pton(family: int, text: str) -> bytes: - """Convert the textual form of a network address into its binary form. - - *family* is an ``int``, the address family. - - *text* is a ``str``, the textual address. - - Raises ``NotImplementedError`` if the address family specified is not - implemented. - - Returns a ``bytes``. - """ - - if family == AF_INET: - return dns.ipv4.inet_aton(text) - elif family == AF_INET6: - return dns.ipv6.inet_aton(text, True) - else: - raise NotImplementedError - - -def inet_ntop(family: int, address: bytes) -> str: - """Convert the binary form of a network address into its textual form. - - *family* is an ``int``, the address family. - - *address* is a ``bytes``, the network address in binary form. - - Raises ``NotImplementedError`` if the address family specified is not - implemented. - - Returns a ``str``. - """ - - if family == AF_INET: - return dns.ipv4.inet_ntoa(address) - elif family == AF_INET6: - return dns.ipv6.inet_ntoa(address) - else: - raise NotImplementedError - - -def af_for_address(text: str) -> int: - """Determine the address family of a textual-form network address. - - *text*, a ``str``, the textual address. - - Raises ``ValueError`` if the address family cannot be determined - from the input. - - Returns an ``int``. - """ - - try: - dns.ipv4.inet_aton(text) - return AF_INET - except Exception: - try: - dns.ipv6.inet_aton(text, True) - return AF_INET6 - except Exception: - raise ValueError - - -def is_multicast(text: str) -> bool: - """Is the textual-form network address a multicast address? - - *text*, a ``str``, the textual address. - - Raises ``ValueError`` if the address family cannot be determined - from the input. - - Returns a ``bool``. - """ - - try: - first = dns.ipv4.inet_aton(text)[0] - return first >= 224 and first <= 239 - except Exception: - try: - first = dns.ipv6.inet_aton(text, True)[0] - return first == 255 - except Exception: - raise ValueError - - -def is_address(text: str) -> bool: - """Is the specified string an IPv4 or IPv6 address? - - *text*, a ``str``, the textual address. - - Returns a ``bool``. - """ - - try: - dns.ipv4.inet_aton(text) - return True - except Exception: - try: - dns.ipv6.inet_aton(text, True) - return True - except Exception: - return False - - -def low_level_address_tuple( - high_tuple: Tuple[str, int], af: Optional[int] = None -) -> Any: - """Given a "high-level" address tuple, i.e. - an (address, port) return the appropriate "low-level" address tuple - suitable for use in socket calls. - - If an *af* other than ``None`` is provided, it is assumed the - address in the high-level tuple is valid and has that af. If af - is ``None``, then af_for_address will be called. - """ - address, port = high_tuple - if af is None: - af = af_for_address(address) - if af == AF_INET: - return (address, port) - elif af == AF_INET6: - i = address.find("%") - if i < 0: - # no scope, shortcut! - return (address, port, 0, 0) - # try to avoid getaddrinfo() - addrpart = address[:i] - scope = address[i + 1 :] - if scope.isdigit(): - return (addrpart, port, 0, int(scope)) - try: - return (addrpart, port, 0, socket.if_nametoindex(scope)) - except AttributeError: # pragma: no cover (we can't really test this) - ai_flags = socket.AI_NUMERICHOST - ((*_, tup), *_) = socket.getaddrinfo(address, port, flags=ai_flags) - return tup - else: - raise NotImplementedError(f"unknown address family {af}") - - -def any_for_af(af): - """Return the 'any' address for the specified address family.""" - if af == socket.AF_INET: - return "0.0.0.0" - elif af == socket.AF_INET6: - return "::" - raise NotImplementedError(f"unknown address family {af}") - - -def canonicalize(text: str) -> str: - """Verify that *address* is a valid text form IPv4 or IPv6 address and return its - canonical text form. IPv6 addresses with scopes are rejected. - - *text*, a ``str``, the address in textual form. - - Raises ``ValueError`` if the text is not valid. - """ - try: - return dns.ipv6.canonicalize(text) - except Exception: - try: - return dns.ipv4.canonicalize(text) - except Exception: - raise ValueError diff --git a/venv/Lib/site-packages/dns/ipv4.py b/venv/Lib/site-packages/dns/ipv4.py deleted file mode 100644 index 65ee69c..0000000 --- a/venv/Lib/site-packages/dns/ipv4.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""IPv4 helper functions.""" - -import struct -from typing import Union - -import dns.exception - - -def inet_ntoa(address: bytes) -> str: - """Convert an IPv4 address in binary form to text form. - - *address*, a ``bytes``, the IPv4 address in binary form. - - Returns a ``str``. - """ - - if len(address) != 4: - raise dns.exception.SyntaxError - return "%u.%u.%u.%u" % (address[0], address[1], address[2], address[3]) - - -def inet_aton(text: Union[str, bytes]) -> bytes: - """Convert an IPv4 address in text form to binary form. - - *text*, a ``str`` or ``bytes``, the IPv4 address in textual form. - - Returns a ``bytes``. - """ - - if not isinstance(text, bytes): - btext = text.encode() - else: - btext = text - parts = btext.split(b".") - if len(parts) != 4: - raise dns.exception.SyntaxError - for part in parts: - if not part.isdigit(): - raise dns.exception.SyntaxError - if len(part) > 1 and part[0] == ord("0"): - # No leading zeros - raise dns.exception.SyntaxError - try: - b = [int(part) for part in parts] - return struct.pack("BBBB", *b) - except Exception: - raise dns.exception.SyntaxError - - -def canonicalize(text: Union[str, bytes]) -> str: - """Verify that *address* is a valid text form IPv4 address and return its - canonical text form. - - *text*, a ``str`` or ``bytes``, the IPv4 address in textual form. - - Raises ``dns.exception.SyntaxError`` if the text is not valid. - """ - # Note that inet_aton() only accepts canonial form, but we still run through - # inet_ntoa() to ensure the output is a str. - return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text)) diff --git a/venv/Lib/site-packages/dns/ipv6.py b/venv/Lib/site-packages/dns/ipv6.py deleted file mode 100644 index 4dd1d1c..0000000 --- a/venv/Lib/site-packages/dns/ipv6.py +++ /dev/null @@ -1,217 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""IPv6 helper functions.""" - -import binascii -import re -from typing import List, Union - -import dns.exception -import dns.ipv4 - -_leading_zero = re.compile(r"0+([0-9a-f]+)") - - -def inet_ntoa(address: bytes) -> str: - """Convert an IPv6 address in binary form to text form. - - *address*, a ``bytes``, the IPv6 address in binary form. - - Raises ``ValueError`` if the address isn't 16 bytes long. - Returns a ``str``. - """ - - if len(address) != 16: - raise ValueError("IPv6 addresses are 16 bytes long") - hex = binascii.hexlify(address) - chunks = [] - i = 0 - l = len(hex) - while i < l: - chunk = hex[i : i + 4].decode() - # strip leading zeros. we do this with an re instead of - # with lstrip() because lstrip() didn't support chars until - # python 2.2.2 - m = _leading_zero.match(chunk) - if m is not None: - chunk = m.group(1) - chunks.append(chunk) - i += 4 - # - # Compress the longest subsequence of 0-value chunks to :: - # - best_start = 0 - best_len = 0 - start = -1 - last_was_zero = False - for i in range(8): - if chunks[i] != "0": - if last_was_zero: - end = i - current_len = end - start - if current_len > best_len: - best_start = start - best_len = current_len - last_was_zero = False - elif not last_was_zero: - start = i - last_was_zero = True - if last_was_zero: - end = 8 - current_len = end - start - if current_len > best_len: - best_start = start - best_len = current_len - if best_len > 1: - if best_start == 0 and (best_len == 6 or best_len == 5 and chunks[5] == "ffff"): - # We have an embedded IPv4 address - if best_len == 6: - prefix = "::" - else: - prefix = "::ffff:" - thex = prefix + dns.ipv4.inet_ntoa(address[12:]) - else: - thex = ( - ":".join(chunks[:best_start]) - + "::" - + ":".join(chunks[best_start + best_len :]) - ) - else: - thex = ":".join(chunks) - return thex - - -_v4_ending = re.compile(rb"(.*):(\d+\.\d+\.\d+\.\d+)$") -_colon_colon_start = re.compile(rb"::.*") -_colon_colon_end = re.compile(rb".*::$") - - -def inet_aton(text: Union[str, bytes], ignore_scope: bool = False) -> bytes: - """Convert an IPv6 address in text form to binary form. - - *text*, a ``str`` or ``bytes``, the IPv6 address in textual form. - - *ignore_scope*, a ``bool``. If ``True``, a scope will be ignored. - If ``False``, the default, it is an error for a scope to be present. - - Returns a ``bytes``. - """ - - # - # Our aim here is not something fast; we just want something that works. - # - if not isinstance(text, bytes): - btext = text.encode() - else: - btext = text - - if ignore_scope: - parts = btext.split(b"%") - l = len(parts) - if l == 2: - btext = parts[0] - elif l > 2: - raise dns.exception.SyntaxError - - if btext == b"": - raise dns.exception.SyntaxError - elif btext.endswith(b":") and not btext.endswith(b"::"): - raise dns.exception.SyntaxError - elif btext.startswith(b":") and not btext.startswith(b"::"): - raise dns.exception.SyntaxError - elif btext == b"::": - btext = b"0::" - # - # Get rid of the icky dot-quad syntax if we have it. - # - m = _v4_ending.match(btext) - if m is not None: - b = dns.ipv4.inet_aton(m.group(2)) - btext = ( - f"{m.group(1).decode()}:{b[0]:02x}{b[1]:02x}:{b[2]:02x}{b[3]:02x}" - ).encode() - # - # Try to turn '::' into ':'; if no match try to - # turn '::' into ':' - # - m = _colon_colon_start.match(btext) - if m is not None: - btext = btext[1:] - else: - m = _colon_colon_end.match(btext) - if m is not None: - btext = btext[:-1] - # - # Now canonicalize into 8 chunks of 4 hex digits each - # - chunks = btext.split(b":") - l = len(chunks) - if l > 8: - raise dns.exception.SyntaxError - seen_empty = False - canonical: List[bytes] = [] - for c in chunks: - if c == b"": - if seen_empty: - raise dns.exception.SyntaxError - seen_empty = True - for _ in range(0, 8 - l + 1): - canonical.append(b"0000") - else: - lc = len(c) - if lc > 4: - raise dns.exception.SyntaxError - if lc != 4: - c = (b"0" * (4 - lc)) + c - canonical.append(c) - if l < 8 and not seen_empty: - raise dns.exception.SyntaxError - btext = b"".join(canonical) - - # - # Finally we can go to binary. - # - try: - return binascii.unhexlify(btext) - except (binascii.Error, TypeError): - raise dns.exception.SyntaxError - - -_mapped_prefix = b"\x00" * 10 + b"\xff\xff" - - -def is_mapped(address: bytes) -> bool: - """Is the specified address a mapped IPv4 address? - - *address*, a ``bytes`` is an IPv6 address in binary form. - - Returns a ``bool``. - """ - - return address.startswith(_mapped_prefix) - - -def canonicalize(text: Union[str, bytes]) -> str: - """Verify that *address* is a valid text form IPv6 address and return its - canonical text form. Addresses with scopes are rejected. - - *text*, a ``str`` or ``bytes``, the IPv6 address in textual form. - - Raises ``dns.exception.SyntaxError`` if the text is not valid. - """ - return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text)) diff --git a/venv/Lib/site-packages/dns/message.py b/venv/Lib/site-packages/dns/message.py deleted file mode 100644 index e978a0a..0000000 --- a/venv/Lib/site-packages/dns/message.py +++ /dev/null @@ -1,1933 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Messages""" - -import contextlib -import enum -import io -import time -from typing import Any, Dict, List, Optional, Tuple, Union, cast - -import dns.edns -import dns.entropy -import dns.enum -import dns.exception -import dns.flags -import dns.name -import dns.opcode -import dns.rcode -import dns.rdata -import dns.rdataclass -import dns.rdatatype -import dns.rdtypes.ANY.OPT -import dns.rdtypes.ANY.TSIG -import dns.renderer -import dns.rrset -import dns.tsig -import dns.ttl -import dns.wire - - -class ShortHeader(dns.exception.FormError): - """The DNS packet passed to from_wire() is too short.""" - - -class TrailingJunk(dns.exception.FormError): - """The DNS packet passed to from_wire() has extra junk at the end of it.""" - - -class UnknownHeaderField(dns.exception.DNSException): - """The header field name was not recognized when converting from text - into a message.""" - - -class BadEDNS(dns.exception.FormError): - """An OPT record occurred somewhere other than - the additional data section.""" - - -class BadTSIG(dns.exception.FormError): - """A TSIG record occurred somewhere other than the end of - the additional data section.""" - - -class UnknownTSIGKey(dns.exception.DNSException): - """A TSIG with an unknown key was received.""" - - -class Truncated(dns.exception.DNSException): - """The truncated flag is set.""" - - supp_kwargs = {"message"} - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - def message(self): - """As much of the message as could be processed. - - Returns a ``dns.message.Message``. - """ - return self.kwargs["message"] - - -class NotQueryResponse(dns.exception.DNSException): - """Message is not a response to a query.""" - - -class ChainTooLong(dns.exception.DNSException): - """The CNAME chain is too long.""" - - -class AnswerForNXDOMAIN(dns.exception.DNSException): - """The rcode is NXDOMAIN but an answer was found.""" - - -class NoPreviousName(dns.exception.SyntaxError): - """No previous name was known.""" - - -class MessageSection(dns.enum.IntEnum): - """Message sections""" - - QUESTION = 0 - ANSWER = 1 - AUTHORITY = 2 - ADDITIONAL = 3 - - @classmethod - def _maximum(cls): - return 3 - - -class MessageError: - def __init__(self, exception: Exception, offset: int): - self.exception = exception - self.offset = offset - - -DEFAULT_EDNS_PAYLOAD = 1232 -MAX_CHAIN = 16 - -IndexKeyType = Tuple[ - int, - dns.name.Name, - dns.rdataclass.RdataClass, - dns.rdatatype.RdataType, - Optional[dns.rdatatype.RdataType], - Optional[dns.rdataclass.RdataClass], -] -IndexType = Dict[IndexKeyType, dns.rrset.RRset] -SectionType = Union[int, str, List[dns.rrset.RRset]] - - -class Message: - """A DNS message.""" - - _section_enum = MessageSection - - def __init__(self, id: Optional[int] = None): - if id is None: - self.id = dns.entropy.random_16() - else: - self.id = id - self.flags = 0 - self.sections: List[List[dns.rrset.RRset]] = [[], [], [], []] - self.opt: Optional[dns.rrset.RRset] = None - self.request_payload = 0 - self.pad = 0 - self.keyring: Any = None - self.tsig: Optional[dns.rrset.RRset] = None - self.request_mac = b"" - self.xfr = False - self.origin: Optional[dns.name.Name] = None - self.tsig_ctx: Optional[Any] = None - self.index: IndexType = {} - self.errors: List[MessageError] = [] - self.time = 0.0 - self.wire: Optional[bytes] = None - - @property - def question(self) -> List[dns.rrset.RRset]: - """The question section.""" - return self.sections[0] - - @question.setter - def question(self, v): - self.sections[0] = v - - @property - def answer(self) -> List[dns.rrset.RRset]: - """The answer section.""" - return self.sections[1] - - @answer.setter - def answer(self, v): - self.sections[1] = v - - @property - def authority(self) -> List[dns.rrset.RRset]: - """The authority section.""" - return self.sections[2] - - @authority.setter - def authority(self, v): - self.sections[2] = v - - @property - def additional(self) -> List[dns.rrset.RRset]: - """The additional data section.""" - return self.sections[3] - - @additional.setter - def additional(self, v): - self.sections[3] = v - - def __repr__(self): - return "" - - def __str__(self): - return self.to_text() - - def to_text( - self, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - **kw: Dict[str, Any], - ) -> str: - """Convert the message to text. - - The *origin*, *relativize*, and any other keyword - arguments are passed to the RRset ``to_wire()`` method. - - Returns a ``str``. - """ - - s = io.StringIO() - s.write("id %d\n" % self.id) - s.write(f"opcode {dns.opcode.to_text(self.opcode())}\n") - s.write(f"rcode {dns.rcode.to_text(self.rcode())}\n") - s.write(f"flags {dns.flags.to_text(self.flags)}\n") - if self.edns >= 0: - s.write(f"edns {self.edns}\n") - if self.ednsflags != 0: - s.write(f"eflags {dns.flags.edns_to_text(self.ednsflags)}\n") - s.write("payload %d\n" % self.payload) - for opt in self.options: - s.write(f"option {opt.to_text()}\n") - for name, which in self._section_enum.__members__.items(): - s.write(f";{name}\n") - for rrset in self.section_from_number(which): - s.write(rrset.to_text(origin, relativize, **kw)) - s.write("\n") - # - # We strip off the final \n so the caller can print the result without - # doing weird things to get around eccentricities in Python print - # formatting - # - return s.getvalue()[:-1] - - def __eq__(self, other): - """Two messages are equal if they have the same content in the - header, question, answer, and authority sections. - - Returns a ``bool``. - """ - - if not isinstance(other, Message): - return False - if self.id != other.id: - return False - if self.flags != other.flags: - return False - for i, section in enumerate(self.sections): - other_section = other.sections[i] - for n in section: - if n not in other_section: - return False - for n in other_section: - if n not in section: - return False - return True - - def __ne__(self, other): - return not self.__eq__(other) - - def is_response(self, other: "Message") -> bool: - """Is *other*, also a ``dns.message.Message``, a response to this - message? - - Returns a ``bool``. - """ - - if ( - other.flags & dns.flags.QR == 0 - or self.id != other.id - or dns.opcode.from_flags(self.flags) != dns.opcode.from_flags(other.flags) - ): - return False - if other.rcode() in { - dns.rcode.FORMERR, - dns.rcode.SERVFAIL, - dns.rcode.NOTIMP, - dns.rcode.REFUSED, - }: - # We don't check the question section in these cases if - # the other question section is empty, even though they - # still really ought to have a question section. - if len(other.question) == 0: - return True - if dns.opcode.is_update(self.flags): - # This is assuming the "sender doesn't include anything - # from the update", but we don't care to check the other - # case, which is that all the sections are returned and - # identical. - return True - for n in self.question: - if n not in other.question: - return False - for n in other.question: - if n not in self.question: - return False - return True - - def section_number(self, section: List[dns.rrset.RRset]) -> int: - """Return the "section number" of the specified section for use - in indexing. - - *section* is one of the section attributes of this message. - - Raises ``ValueError`` if the section isn't known. - - Returns an ``int``. - """ - - for i, our_section in enumerate(self.sections): - if section is our_section: - return self._section_enum(i) - raise ValueError("unknown section") - - def section_from_number(self, number: int) -> List[dns.rrset.RRset]: - """Return the section list associated with the specified section - number. - - *number* is a section number `int` or the text form of a section - name. - - Raises ``ValueError`` if the section isn't known. - - Returns a ``list``. - """ - - section = self._section_enum.make(number) - return self.sections[section] - - def find_rrset( - self, - section: SectionType, - name: dns.name.Name, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - deleting: Optional[dns.rdataclass.RdataClass] = None, - create: bool = False, - force_unique: bool = False, - idna_codec: Optional[dns.name.IDNACodec] = None, - ) -> dns.rrset.RRset: - """Find the RRset with the given attributes in the specified section. - - *section*, an ``int`` section number, a ``str`` section name, or one of - the section attributes of this message. This specifies the - the section of the message to search. For example:: - - my_message.find_rrset(my_message.answer, name, rdclass, rdtype) - my_message.find_rrset(dns.message.ANSWER, name, rdclass, rdtype) - my_message.find_rrset("ANSWER", name, rdclass, rdtype) - - *name*, a ``dns.name.Name`` or ``str``, the name of the RRset. - - *rdclass*, an ``int`` or ``str``, the class of the RRset. - - *rdtype*, an ``int`` or ``str``, the type of the RRset. - - *covers*, an ``int`` or ``str``, the covers value of the RRset. - The default is ``dns.rdatatype.NONE``. - - *deleting*, an ``int``, ``str``, or ``None``, the deleting value of the - RRset. The default is ``None``. - - *create*, a ``bool``. If ``True``, create the RRset if it is not found. - The created RRset is appended to *section*. - - *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``, - create a new RRset regardless of whether a matching RRset exists - already. The default is ``False``. This is useful when creating - DDNS Update messages, as order matters for them. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - Raises ``KeyError`` if the RRset was not found and create was - ``False``. - - Returns a ``dns.rrset.RRset object``. - """ - - if isinstance(section, int): - section_number = section - section = self.section_from_number(section_number) - elif isinstance(section, str): - section_number = self._section_enum.from_text(section) - section = self.section_from_number(section_number) - else: - section_number = self.section_number(section) - if isinstance(name, str): - name = dns.name.from_text(name, idna_codec=idna_codec) - rdtype = dns.rdatatype.RdataType.make(rdtype) - rdclass = dns.rdataclass.RdataClass.make(rdclass) - covers = dns.rdatatype.RdataType.make(covers) - if deleting is not None: - deleting = dns.rdataclass.RdataClass.make(deleting) - key = (section_number, name, rdclass, rdtype, covers, deleting) - if not force_unique: - if self.index is not None: - rrset = self.index.get(key) - if rrset is not None: - return rrset - else: - for rrset in section: - if rrset.full_match(name, rdclass, rdtype, covers, deleting): - return rrset - if not create: - raise KeyError - rrset = dns.rrset.RRset(name, rdclass, rdtype, covers, deleting) - section.append(rrset) - if self.index is not None: - self.index[key] = rrset - return rrset - - def get_rrset( - self, - section: SectionType, - name: dns.name.Name, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - deleting: Optional[dns.rdataclass.RdataClass] = None, - create: bool = False, - force_unique: bool = False, - idna_codec: Optional[dns.name.IDNACodec] = None, - ) -> Optional[dns.rrset.RRset]: - """Get the RRset with the given attributes in the specified section. - - If the RRset is not found, None is returned. - - *section*, an ``int`` section number, a ``str`` section name, or one of - the section attributes of this message. This specifies the - the section of the message to search. For example:: - - my_message.get_rrset(my_message.answer, name, rdclass, rdtype) - my_message.get_rrset(dns.message.ANSWER, name, rdclass, rdtype) - my_message.get_rrset("ANSWER", name, rdclass, rdtype) - - *name*, a ``dns.name.Name`` or ``str``, the name of the RRset. - - *rdclass*, an ``int`` or ``str``, the class of the RRset. - - *rdtype*, an ``int`` or ``str``, the type of the RRset. - - *covers*, an ``int`` or ``str``, the covers value of the RRset. - The default is ``dns.rdatatype.NONE``. - - *deleting*, an ``int``, ``str``, or ``None``, the deleting value of the - RRset. The default is ``None``. - - *create*, a ``bool``. If ``True``, create the RRset if it is not found. - The created RRset is appended to *section*. - - *force_unique*, a ``bool``. If ``True`` and *create* is also ``True``, - create a new RRset regardless of whether a matching RRset exists - already. The default is ``False``. This is useful when creating - DDNS Update messages, as order matters for them. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - Returns a ``dns.rrset.RRset object`` or ``None``. - """ - - try: - rrset = self.find_rrset( - section, - name, - rdclass, - rdtype, - covers, - deleting, - create, - force_unique, - idna_codec, - ) - except KeyError: - rrset = None - return rrset - - def section_count(self, section: SectionType) -> int: - """Returns the number of records in the specified section. - - *section*, an ``int`` section number, a ``str`` section name, or one of - the section attributes of this message. This specifies the - the section of the message to count. For example:: - - my_message.section_count(my_message.answer) - my_message.section_count(dns.message.ANSWER) - my_message.section_count("ANSWER") - """ - - if isinstance(section, int): - section_number = section - section = self.section_from_number(section_number) - elif isinstance(section, str): - section_number = self._section_enum.from_text(section) - section = self.section_from_number(section_number) - else: - section_number = self.section_number(section) - count = sum(max(1, len(rrs)) for rrs in section) - if section_number == MessageSection.ADDITIONAL: - if self.opt is not None: - count += 1 - if self.tsig is not None: - count += 1 - return count - - def _compute_opt_reserve(self) -> int: - """Compute the size required for the OPT RR, padding excluded""" - if not self.opt: - return 0 - # 1 byte for the root name, 10 for the standard RR fields - size = 11 - # This would be more efficient if options had a size() method, but we won't - # worry about that for now. We also don't worry if there is an existing padding - # option, as it is unlikely and probably harmless, as the worst case is that we - # may add another, and this seems to be legal. - for option in self.opt[0].options: - wire = option.to_wire() - # We add 4 here to account for the option type and length - size += len(wire) + 4 - if self.pad: - # Padding will be added, so again add the option type and length. - size += 4 - return size - - def _compute_tsig_reserve(self) -> int: - """Compute the size required for the TSIG RR""" - # This would be more efficient if TSIGs had a size method, but we won't - # worry about for now. Also, we can't really cope with the potential - # compressibility of the TSIG owner name, so we estimate with the uncompressed - # size. We will disable compression when TSIG and padding are both is active - # so that the padding comes out right. - if not self.tsig: - return 0 - f = io.BytesIO() - self.tsig.to_wire(f) - return len(f.getvalue()) - - def to_wire( - self, - origin: Optional[dns.name.Name] = None, - max_size: int = 0, - multi: bool = False, - tsig_ctx: Optional[Any] = None, - prepend_length: bool = False, - prefer_truncation: bool = False, - **kw: Dict[str, Any], - ) -> bytes: - """Return a string containing the message in DNS compressed wire - format. - - Additional keyword arguments are passed to the RRset ``to_wire()`` - method. - - *origin*, a ``dns.name.Name`` or ``None``, the origin to be appended - to any relative names. If ``None``, and the message has an origin - attribute that is not ``None``, then it will be used. - - *max_size*, an ``int``, the maximum size of the wire format - output; default is 0, which means "the message's request - payload, if nonzero, or 65535". - - *multi*, a ``bool``, should be set to ``True`` if this message is - part of a multiple message sequence. - - *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the - ongoing TSIG context, used when signing zone transfers. - - *prepend_length*, a ``bool``, should be set to ``True`` if the caller - wants the message length prepended to the message itself. This is - useful for messages sent over TCP, TLS (DoT), or QUIC (DoQ). - - *prefer_truncation*, a ``bool``, should be set to ``True`` if the caller - wants the message to be truncated if it would otherwise exceed the - maximum length. If the truncation occurs before the additional section, - the TC bit will be set. - - Raises ``dns.exception.TooBig`` if *max_size* was exceeded. - - Returns a ``bytes``. - """ - - if origin is None and self.origin is not None: - origin = self.origin - if max_size == 0: - if self.request_payload != 0: - max_size = self.request_payload - else: - max_size = 65535 - if max_size < 512: - max_size = 512 - elif max_size > 65535: - max_size = 65535 - r = dns.renderer.Renderer(self.id, self.flags, max_size, origin) - opt_reserve = self._compute_opt_reserve() - r.reserve(opt_reserve) - tsig_reserve = self._compute_tsig_reserve() - r.reserve(tsig_reserve) - try: - for rrset in self.question: - r.add_question(rrset.name, rrset.rdtype, rrset.rdclass) - for rrset in self.answer: - r.add_rrset(dns.renderer.ANSWER, rrset, **kw) - for rrset in self.authority: - r.add_rrset(dns.renderer.AUTHORITY, rrset, **kw) - for rrset in self.additional: - r.add_rrset(dns.renderer.ADDITIONAL, rrset, **kw) - except dns.exception.TooBig: - if prefer_truncation: - if r.section < dns.renderer.ADDITIONAL: - r.flags |= dns.flags.TC - else: - raise - r.release_reserved() - if self.opt is not None: - r.add_opt(self.opt, self.pad, opt_reserve, tsig_reserve) - r.write_header() - if self.tsig is not None: - (new_tsig, ctx) = dns.tsig.sign( - r.get_wire(), - self.keyring, - self.tsig[0], - int(time.time()), - self.request_mac, - tsig_ctx, - multi, - ) - self.tsig.clear() - self.tsig.add(new_tsig) - r.add_rrset(dns.renderer.ADDITIONAL, self.tsig) - r.write_header() - if multi: - self.tsig_ctx = ctx - wire = r.get_wire() - self.wire = wire - if prepend_length: - wire = len(wire).to_bytes(2, "big") + wire - return wire - - @staticmethod - def _make_tsig( - keyname, algorithm, time_signed, fudge, mac, original_id, error, other - ): - tsig = dns.rdtypes.ANY.TSIG.TSIG( - dns.rdataclass.ANY, - dns.rdatatype.TSIG, - algorithm, - time_signed, - fudge, - mac, - original_id, - error, - other, - ) - return dns.rrset.from_rdata(keyname, 0, tsig) - - def use_tsig( - self, - keyring: Any, - keyname: Optional[Union[dns.name.Name, str]] = None, - fudge: int = 300, - original_id: Optional[int] = None, - tsig_error: int = 0, - other_data: bytes = b"", - algorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm, - ) -> None: - """When sending, a TSIG signature using the specified key - should be added. - - *key*, a ``dns.tsig.Key`` is the key to use. If a key is specified, - the *keyring* and *algorithm* fields are not used. - - *keyring*, a ``dict``, ``callable`` or ``dns.tsig.Key``, is either - the TSIG keyring or key to use. - - The format of a keyring dict is a mapping from TSIG key name, as - ``dns.name.Name`` to ``dns.tsig.Key`` or a TSIG secret, a ``bytes``. - If a ``dict`` *keyring* is specified but a *keyname* is not, the key - used will be the first key in the *keyring*. Note that the order of - keys in a dictionary is not defined, so applications should supply a - keyname when a ``dict`` keyring is used, unless they know the keyring - contains only one key. If a ``callable`` keyring is specified, the - callable will be called with the message and the keyname, and is - expected to return a key. - - *keyname*, a ``dns.name.Name``, ``str`` or ``None``, the name of - this TSIG key to use; defaults to ``None``. If *keyring* is a - ``dict``, the key must be defined in it. If *keyring* is a - ``dns.tsig.Key``, this is ignored. - - *fudge*, an ``int``, the TSIG time fudge. - - *original_id*, an ``int``, the TSIG original id. If ``None``, - the message's id is used. - - *tsig_error*, an ``int``, the TSIG error code. - - *other_data*, a ``bytes``, the TSIG other data. - - *algorithm*, a ``dns.name.Name`` or ``str``, the TSIG algorithm to use. This is - only used if *keyring* is a ``dict``, and the key entry is a ``bytes``. - """ - - if isinstance(keyring, dns.tsig.Key): - key = keyring - keyname = key.name - elif callable(keyring): - key = keyring(self, keyname) - else: - if isinstance(keyname, str): - keyname = dns.name.from_text(keyname) - if keyname is None: - keyname = next(iter(keyring)) - key = keyring[keyname] - if isinstance(key, bytes): - key = dns.tsig.Key(keyname, key, algorithm) - self.keyring = key - if original_id is None: - original_id = self.id - self.tsig = self._make_tsig( - keyname, - self.keyring.algorithm, - 0, - fudge, - b"\x00" * dns.tsig.mac_sizes[self.keyring.algorithm], - original_id, - tsig_error, - other_data, - ) - - @property - def keyname(self) -> Optional[dns.name.Name]: - if self.tsig: - return self.tsig.name - else: - return None - - @property - def keyalgorithm(self) -> Optional[dns.name.Name]: - if self.tsig: - return self.tsig[0].algorithm - else: - return None - - @property - def mac(self) -> Optional[bytes]: - if self.tsig: - return self.tsig[0].mac - else: - return None - - @property - def tsig_error(self) -> Optional[int]: - if self.tsig: - return self.tsig[0].error - else: - return None - - @property - def had_tsig(self) -> bool: - return bool(self.tsig) - - @staticmethod - def _make_opt(flags=0, payload=DEFAULT_EDNS_PAYLOAD, options=None): - opt = dns.rdtypes.ANY.OPT.OPT(payload, dns.rdatatype.OPT, options or ()) - return dns.rrset.from_rdata(dns.name.root, int(flags), opt) - - def use_edns( - self, - edns: Optional[Union[int, bool]] = 0, - ednsflags: int = 0, - payload: int = DEFAULT_EDNS_PAYLOAD, - request_payload: Optional[int] = None, - options: Optional[List[dns.edns.Option]] = None, - pad: int = 0, - ) -> None: - """Configure EDNS behavior. - - *edns*, an ``int``, is the EDNS level to use. Specifying ``None``, ``False``, - or ``-1`` means "do not use EDNS", and in this case the other parameters are - ignored. Specifying ``True`` is equivalent to specifying 0, i.e. "use EDNS0". - - *ednsflags*, an ``int``, the EDNS flag values. - - *payload*, an ``int``, is the EDNS sender's payload field, which is the maximum - size of UDP datagram the sender can handle. I.e. how big a response to this - message can be. - - *request_payload*, an ``int``, is the EDNS payload size to use when sending this - message. If not specified, defaults to the value of *payload*. - - *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS options. - - *pad*, a non-negative ``int``. If 0, the default, do not pad; otherwise add - padding bytes to make the message size a multiple of *pad*. Note that if - padding is non-zero, an EDNS PADDING option will always be added to the - message. - """ - - if edns is None or edns is False: - edns = -1 - elif edns is True: - edns = 0 - if edns < 0: - self.opt = None - self.request_payload = 0 - else: - # make sure the EDNS version in ednsflags agrees with edns - ednsflags &= 0xFF00FFFF - ednsflags |= edns << 16 - if options is None: - options = [] - self.opt = self._make_opt(ednsflags, payload, options) - if request_payload is None: - request_payload = payload - self.request_payload = request_payload - if pad < 0: - raise ValueError("pad must be non-negative") - self.pad = pad - - @property - def edns(self) -> int: - if self.opt: - return (self.ednsflags & 0xFF0000) >> 16 - else: - return -1 - - @property - def ednsflags(self) -> int: - if self.opt: - return self.opt.ttl - else: - return 0 - - @ednsflags.setter - def ednsflags(self, v): - if self.opt: - self.opt.ttl = v - elif v: - self.opt = self._make_opt(v) - - @property - def payload(self) -> int: - if self.opt: - return self.opt[0].payload - else: - return 0 - - @property - def options(self) -> Tuple: - if self.opt: - return self.opt[0].options - else: - return () - - def want_dnssec(self, wanted: bool = True) -> None: - """Enable or disable 'DNSSEC desired' flag in requests. - - *wanted*, a ``bool``. If ``True``, then DNSSEC data is - desired in the response, EDNS is enabled if required, and then - the DO bit is set. If ``False``, the DO bit is cleared if - EDNS is enabled. - """ - - if wanted: - self.ednsflags |= dns.flags.DO - elif self.opt: - self.ednsflags &= ~int(dns.flags.DO) - - def rcode(self) -> dns.rcode.Rcode: - """Return the rcode. - - Returns a ``dns.rcode.Rcode``. - """ - return dns.rcode.from_flags(int(self.flags), int(self.ednsflags)) - - def set_rcode(self, rcode: dns.rcode.Rcode) -> None: - """Set the rcode. - - *rcode*, a ``dns.rcode.Rcode``, is the rcode to set. - """ - (value, evalue) = dns.rcode.to_flags(rcode) - self.flags &= 0xFFF0 - self.flags |= value - self.ednsflags &= 0x00FFFFFF - self.ednsflags |= evalue - - def opcode(self) -> dns.opcode.Opcode: - """Return the opcode. - - Returns a ``dns.opcode.Opcode``. - """ - return dns.opcode.from_flags(int(self.flags)) - - def set_opcode(self, opcode: dns.opcode.Opcode) -> None: - """Set the opcode. - - *opcode*, a ``dns.opcode.Opcode``, is the opcode to set. - """ - self.flags &= 0x87FF - self.flags |= dns.opcode.to_flags(opcode) - - def get_options(self, otype: dns.edns.OptionType) -> List[dns.edns.Option]: - """Return the list of options of the specified type.""" - return [option for option in self.options if option.otype == otype] - - def extended_errors(self) -> List[dns.edns.EDEOption]: - """Return the list of Extended DNS Error (EDE) options in the message""" - return cast(List[dns.edns.EDEOption], self.get_options(dns.edns.OptionType.EDE)) - - def _get_one_rr_per_rrset(self, value): - # What the caller picked is fine. - return value - - # pylint: disable=unused-argument - - def _parse_rr_header(self, section, name, rdclass, rdtype): - return (rdclass, rdtype, None, False) - - # pylint: enable=unused-argument - - def _parse_special_rr_header(self, section, count, position, name, rdclass, rdtype): - if rdtype == dns.rdatatype.OPT: - if ( - section != MessageSection.ADDITIONAL - or self.opt - or name != dns.name.root - ): - raise BadEDNS - elif rdtype == dns.rdatatype.TSIG: - if ( - section != MessageSection.ADDITIONAL - or rdclass != dns.rdatatype.ANY - or position != count - 1 - ): - raise BadTSIG - return (rdclass, rdtype, None, False) - - -class ChainingResult: - """The result of a call to dns.message.QueryMessage.resolve_chaining(). - - The ``answer`` attribute is the answer RRSet, or ``None`` if it doesn't - exist. - - The ``canonical_name`` attribute is the canonical name after all - chaining has been applied (this is the same name as ``rrset.name`` in cases - where rrset is not ``None``). - - The ``minimum_ttl`` attribute is the minimum TTL, i.e. the TTL to - use if caching the data. It is the smallest of all the CNAME TTLs - and either the answer TTL if it exists or the SOA TTL and SOA - minimum values for negative answers. - - The ``cnames`` attribute is a list of all the CNAME RRSets followed to - get to the canonical name. - """ - - def __init__( - self, - canonical_name: dns.name.Name, - answer: Optional[dns.rrset.RRset], - minimum_ttl: int, - cnames: List[dns.rrset.RRset], - ): - self.canonical_name = canonical_name - self.answer = answer - self.minimum_ttl = minimum_ttl - self.cnames = cnames - - -class QueryMessage(Message): - def resolve_chaining(self) -> ChainingResult: - """Follow the CNAME chain in the response to determine the answer - RRset. - - Raises ``dns.message.NotQueryResponse`` if the message is not - a response. - - Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long. - - Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN - but an answer was found. - - Raises ``dns.exception.FormError`` if the question count is not 1. - - Returns a ChainingResult object. - """ - if self.flags & dns.flags.QR == 0: - raise NotQueryResponse - if len(self.question) != 1: - raise dns.exception.FormError - question = self.question[0] - qname = question.name - min_ttl = dns.ttl.MAX_TTL - answer = None - count = 0 - cnames = [] - while count < MAX_CHAIN: - try: - answer = self.find_rrset( - self.answer, qname, question.rdclass, question.rdtype - ) - min_ttl = min(min_ttl, answer.ttl) - break - except KeyError: - if question.rdtype != dns.rdatatype.CNAME: - try: - crrset = self.find_rrset( - self.answer, qname, question.rdclass, dns.rdatatype.CNAME - ) - cnames.append(crrset) - min_ttl = min(min_ttl, crrset.ttl) - for rd in crrset: - qname = rd.target - break - count += 1 - continue - except KeyError: - # Exit the chaining loop - break - else: - # Exit the chaining loop - break - if count >= MAX_CHAIN: - raise ChainTooLong - if self.rcode() == dns.rcode.NXDOMAIN and answer is not None: - raise AnswerForNXDOMAIN - if answer is None: - # Further minimize the TTL with NCACHE. - auname = qname - while True: - # Look for an SOA RR whose owner name is a superdomain - # of qname. - try: - srrset = self.find_rrset( - self.authority, auname, question.rdclass, dns.rdatatype.SOA - ) - min_ttl = min(min_ttl, srrset.ttl, srrset[0].minimum) - break - except KeyError: - try: - auname = auname.parent() - except dns.name.NoParent: - break - return ChainingResult(qname, answer, min_ttl, cnames) - - def canonical_name(self) -> dns.name.Name: - """Return the canonical name of the first name in the question - section. - - Raises ``dns.message.NotQueryResponse`` if the message is not - a response. - - Raises ``dns.message.ChainTooLong`` if the CNAME chain is too long. - - Raises ``dns.message.AnswerForNXDOMAIN`` if the rcode is NXDOMAIN - but an answer was found. - - Raises ``dns.exception.FormError`` if the question count is not 1. - """ - return self.resolve_chaining().canonical_name - - -def _maybe_import_update(): - # We avoid circular imports by doing this here. We do it in another - # function as doing it in _message_factory_from_opcode() makes "dns" - # a local symbol, and the first line fails :) - - # pylint: disable=redefined-outer-name,import-outside-toplevel,unused-import - import dns.update # noqa: F401 - - -def _message_factory_from_opcode(opcode): - if opcode == dns.opcode.QUERY: - return QueryMessage - elif opcode == dns.opcode.UPDATE: - _maybe_import_update() - return dns.update.UpdateMessage - else: - return Message - - -class _WireReader: - """Wire format reader. - - parser: the binary parser - message: The message object being built - initialize_message: Callback to set message parsing options - question_only: Are we only reading the question? - one_rr_per_rrset: Put each RR into its own RRset? - keyring: TSIG keyring - ignore_trailing: Ignore trailing junk at end of request? - multi: Is this message part of a multi-message sequence? - DNS dynamic updates. - continue_on_error: try to extract as much information as possible from - the message, accumulating MessageErrors in the *errors* attribute instead of - raising them. - """ - - def __init__( - self, - wire, - initialize_message, - question_only=False, - one_rr_per_rrset=False, - ignore_trailing=False, - keyring=None, - multi=False, - continue_on_error=False, - ): - self.parser = dns.wire.Parser(wire) - self.message = None - self.initialize_message = initialize_message - self.question_only = question_only - self.one_rr_per_rrset = one_rr_per_rrset - self.ignore_trailing = ignore_trailing - self.keyring = keyring - self.multi = multi - self.continue_on_error = continue_on_error - self.errors = [] - - def _get_question(self, section_number, qcount): - """Read the next *qcount* records from the wire data and add them to - the question section. - """ - assert self.message is not None - section = self.message.sections[section_number] - for _ in range(qcount): - qname = self.parser.get_name(self.message.origin) - (rdtype, rdclass) = self.parser.get_struct("!HH") - (rdclass, rdtype, _, _) = self.message._parse_rr_header( - section_number, qname, rdclass, rdtype - ) - self.message.find_rrset( - section, qname, rdclass, rdtype, create=True, force_unique=True - ) - - def _add_error(self, e): - self.errors.append(MessageError(e, self.parser.current)) - - def _get_section(self, section_number, count): - """Read the next I{count} records from the wire data and add them to - the specified section. - - section_number: the section of the message to which to add records - count: the number of records to read - """ - assert self.message is not None - section = self.message.sections[section_number] - force_unique = self.one_rr_per_rrset - for i in range(count): - rr_start = self.parser.current - absolute_name = self.parser.get_name() - if self.message.origin is not None: - name = absolute_name.relativize(self.message.origin) - else: - name = absolute_name - (rdtype, rdclass, ttl, rdlen) = self.parser.get_struct("!HHIH") - if rdtype in (dns.rdatatype.OPT, dns.rdatatype.TSIG): - ( - rdclass, - rdtype, - deleting, - empty, - ) = self.message._parse_special_rr_header( - section_number, count, i, name, rdclass, rdtype - ) - else: - (rdclass, rdtype, deleting, empty) = self.message._parse_rr_header( - section_number, name, rdclass, rdtype - ) - rdata_start = self.parser.current - try: - if empty: - if rdlen > 0: - raise dns.exception.FormError - rd = None - covers = dns.rdatatype.NONE - else: - with self.parser.restrict_to(rdlen): - rd = dns.rdata.from_wire_parser( - rdclass, rdtype, self.parser, self.message.origin - ) - covers = rd.covers() - if self.message.xfr and rdtype == dns.rdatatype.SOA: - force_unique = True - if rdtype == dns.rdatatype.OPT: - self.message.opt = dns.rrset.from_rdata(name, ttl, rd) - elif rdtype == dns.rdatatype.TSIG: - if self.keyring is None or self.keyring is True: - raise UnknownTSIGKey("got signed message without keyring") - elif isinstance(self.keyring, dict): - key = self.keyring.get(absolute_name) - if isinstance(key, bytes): - key = dns.tsig.Key(absolute_name, key, rd.algorithm) - elif callable(self.keyring): - key = self.keyring(self.message, absolute_name) - else: - key = self.keyring - if key is None: - raise UnknownTSIGKey(f"key '{name}' unknown") - if key: - self.message.keyring = key - self.message.tsig_ctx = dns.tsig.validate( - self.parser.wire, - key, - absolute_name, - rd, - int(time.time()), - self.message.request_mac, - rr_start, - self.message.tsig_ctx, - self.multi, - ) - self.message.tsig = dns.rrset.from_rdata(absolute_name, 0, rd) - else: - rrset = self.message.find_rrset( - section, - name, - rdclass, - rdtype, - covers, - deleting, - True, - force_unique, - ) - if rd is not None: - if ttl > 0x7FFFFFFF: - ttl = 0 - rrset.add(rd, ttl) - except Exception as e: - if self.continue_on_error: - self._add_error(e) - self.parser.seek(rdata_start + rdlen) - else: - raise - - def read(self): - """Read a wire format DNS message and build a dns.message.Message - object.""" - - if self.parser.remaining() < 12: - raise ShortHeader - (id, flags, qcount, ancount, aucount, adcount) = self.parser.get_struct( - "!HHHHHH" - ) - factory = _message_factory_from_opcode(dns.opcode.from_flags(flags)) - self.message = factory(id=id) - self.message.flags = dns.flags.Flag(flags) - self.message.wire = self.parser.wire - self.initialize_message(self.message) - self.one_rr_per_rrset = self.message._get_one_rr_per_rrset( - self.one_rr_per_rrset - ) - try: - self._get_question(MessageSection.QUESTION, qcount) - if self.question_only: - return self.message - self._get_section(MessageSection.ANSWER, ancount) - self._get_section(MessageSection.AUTHORITY, aucount) - self._get_section(MessageSection.ADDITIONAL, adcount) - if not self.ignore_trailing and self.parser.remaining() != 0: - raise TrailingJunk - if self.multi and self.message.tsig_ctx and not self.message.had_tsig: - self.message.tsig_ctx.update(self.parser.wire) - except Exception as e: - if self.continue_on_error: - self._add_error(e) - else: - raise - return self.message - - -def from_wire( - wire: bytes, - keyring: Optional[Any] = None, - request_mac: Optional[bytes] = b"", - xfr: bool = False, - origin: Optional[dns.name.Name] = None, - tsig_ctx: Optional[Union[dns.tsig.HMACTSig, dns.tsig.GSSTSig]] = None, - multi: bool = False, - question_only: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - raise_on_truncation: bool = False, - continue_on_error: bool = False, -) -> Message: - """Convert a DNS wire format message into a message object. - - *keyring*, a ``dns.tsig.Key``, ``dict``, ``bool``, or ``None``, the key or keyring - to use if the message is signed. If ``None`` or ``True``, then trying to decode - a message with a TSIG will fail as it cannot be validated. If ``False``, then - TSIG validation is disabled. - - *request_mac*, a ``bytes`` or ``None``. If the message is a response to a - TSIG-signed request, *request_mac* should be set to the MAC of that request. - - *xfr*, a ``bool``, should be set to ``True`` if this message is part of a zone - transfer. - - *origin*, a ``dns.name.Name`` or ``None``. If the message is part of a zone - transfer, *origin* should be the origin name of the zone. If not ``None``, names - will be relativized to the origin. - - *tsig_ctx*, a ``dns.tsig.HMACTSig`` or ``dns.tsig.GSSTSig`` object, the ongoing TSIG - context, used when validating zone transfers. - - *multi*, a ``bool``, should be set to ``True`` if this message is part of a multiple - message sequence. - - *question_only*, a ``bool``. If ``True``, read only up to the end of the question - section. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the - message. - - *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if the TC bit is - set. - - *continue_on_error*, a ``bool``. If ``True``, try to continue parsing even if - errors occur. Erroneous rdata will be ignored. Errors will be accumulated as a - list of MessageError objects in the message's ``errors`` attribute. This option is - recommended only for DNS analysis tools, or for use in a server as part of an error - handling path. The default is ``False``. - - Raises ``dns.message.ShortHeader`` if the message is less than 12 octets long. - - Raises ``dns.message.TrailingJunk`` if there were octets in the message past the end - of the proper DNS message, and *ignore_trailing* is ``False``. - - Raises ``dns.message.BadEDNS`` if an OPT record was in the wrong section, or - occurred more than once. - - Raises ``dns.message.BadTSIG`` if a TSIG record was not the last record of the - additional data section. - - Raises ``dns.message.Truncated`` if the TC flag is set and *raise_on_truncation* is - ``True``. - - Returns a ``dns.message.Message``. - """ - - # We permit None for request_mac solely for backwards compatibility - if request_mac is None: - request_mac = b"" - - def initialize_message(message): - message.request_mac = request_mac - message.xfr = xfr - message.origin = origin - message.tsig_ctx = tsig_ctx - - reader = _WireReader( - wire, - initialize_message, - question_only, - one_rr_per_rrset, - ignore_trailing, - keyring, - multi, - continue_on_error, - ) - try: - m = reader.read() - except dns.exception.FormError: - if ( - reader.message - and (reader.message.flags & dns.flags.TC) - and raise_on_truncation - ): - raise Truncated(message=reader.message) - else: - raise - # Reading a truncated message might not have any errors, so we - # have to do this check here too. - if m.flags & dns.flags.TC and raise_on_truncation: - raise Truncated(message=m) - if continue_on_error: - m.errors = reader.errors - - return m - - -class _TextReader: - """Text format reader. - - tok: the tokenizer. - message: The message object being built. - DNS dynamic updates. - last_name: The most recently read name when building a message object. - one_rr_per_rrset: Put each RR into its own RRset? - origin: The origin for relative names - relativize: relativize names? - relativize_to: the origin to relativize to. - """ - - def __init__( - self, - text, - idna_codec, - one_rr_per_rrset=False, - origin=None, - relativize=True, - relativize_to=None, - ): - self.message = None - self.tok = dns.tokenizer.Tokenizer(text, idna_codec=idna_codec) - self.last_name = None - self.one_rr_per_rrset = one_rr_per_rrset - self.origin = origin - self.relativize = relativize - self.relativize_to = relativize_to - self.id = None - self.edns = -1 - self.ednsflags = 0 - self.payload = DEFAULT_EDNS_PAYLOAD - self.rcode = None - self.opcode = dns.opcode.QUERY - self.flags = 0 - - def _header_line(self, _): - """Process one line from the text format header section.""" - - token = self.tok.get() - what = token.value - if what == "id": - self.id = self.tok.get_int() - elif what == "flags": - while True: - token = self.tok.get() - if not token.is_identifier(): - self.tok.unget(token) - break - self.flags = self.flags | dns.flags.from_text(token.value) - elif what == "edns": - self.edns = self.tok.get_int() - self.ednsflags = self.ednsflags | (self.edns << 16) - elif what == "eflags": - if self.edns < 0: - self.edns = 0 - while True: - token = self.tok.get() - if not token.is_identifier(): - self.tok.unget(token) - break - self.ednsflags = self.ednsflags | dns.flags.edns_from_text(token.value) - elif what == "payload": - self.payload = self.tok.get_int() - if self.edns < 0: - self.edns = 0 - elif what == "opcode": - text = self.tok.get_string() - self.opcode = dns.opcode.from_text(text) - self.flags = self.flags | dns.opcode.to_flags(self.opcode) - elif what == "rcode": - text = self.tok.get_string() - self.rcode = dns.rcode.from_text(text) - else: - raise UnknownHeaderField - self.tok.get_eol() - - def _question_line(self, section_number): - """Process one line from the text format question section.""" - - section = self.message.sections[section_number] - token = self.tok.get(want_leading=True) - if not token.is_whitespace(): - self.last_name = self.tok.as_name( - token, self.message.origin, self.relativize, self.relativize_to - ) - name = self.last_name - if name is None: - raise NoPreviousName - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - # Class - try: - rdclass = dns.rdataclass.from_text(token.value) - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except dns.exception.SyntaxError: - raise dns.exception.SyntaxError - except Exception: - rdclass = dns.rdataclass.IN - # Type - rdtype = dns.rdatatype.from_text(token.value) - (rdclass, rdtype, _, _) = self.message._parse_rr_header( - section_number, name, rdclass, rdtype - ) - self.message.find_rrset( - section, name, rdclass, rdtype, create=True, force_unique=True - ) - self.tok.get_eol() - - def _rr_line(self, section_number): - """Process one line from the text format answer, authority, or - additional data sections. - """ - - section = self.message.sections[section_number] - # Name - token = self.tok.get(want_leading=True) - if not token.is_whitespace(): - self.last_name = self.tok.as_name( - token, self.message.origin, self.relativize, self.relativize_to - ) - name = self.last_name - if name is None: - raise NoPreviousName - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - # TTL - try: - ttl = int(token.value, 0) - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except dns.exception.SyntaxError: - raise dns.exception.SyntaxError - except Exception: - ttl = 0 - # Class - try: - rdclass = dns.rdataclass.from_text(token.value) - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except dns.exception.SyntaxError: - raise dns.exception.SyntaxError - except Exception: - rdclass = dns.rdataclass.IN - # Type - rdtype = dns.rdatatype.from_text(token.value) - (rdclass, rdtype, deleting, empty) = self.message._parse_rr_header( - section_number, name, rdclass, rdtype - ) - token = self.tok.get() - if empty and not token.is_eol_or_eof(): - raise dns.exception.SyntaxError - if not empty and token.is_eol_or_eof(): - raise dns.exception.UnexpectedEnd - if not token.is_eol_or_eof(): - self.tok.unget(token) - rd = dns.rdata.from_text( - rdclass, - rdtype, - self.tok, - self.message.origin, - self.relativize, - self.relativize_to, - ) - covers = rd.covers() - else: - rd = None - covers = dns.rdatatype.NONE - rrset = self.message.find_rrset( - section, - name, - rdclass, - rdtype, - covers, - deleting, - True, - self.one_rr_per_rrset, - ) - if rd is not None: - rrset.add(rd, ttl) - - def _make_message(self): - factory = _message_factory_from_opcode(self.opcode) - message = factory(id=self.id) - message.flags = self.flags - if self.edns >= 0: - message.use_edns(self.edns, self.ednsflags, self.payload) - if self.rcode: - message.set_rcode(self.rcode) - if self.origin: - message.origin = self.origin - return message - - def read(self): - """Read a text format DNS message and build a dns.message.Message - object.""" - - line_method = self._header_line - section_number = None - while 1: - token = self.tok.get(True, True) - if token.is_eol_or_eof(): - break - if token.is_comment(): - u = token.value.upper() - if u == "HEADER": - line_method = self._header_line - - if self.message: - message = self.message - else: - # If we don't have a message, create one with the current - # opcode, so that we know which section names to parse. - message = self._make_message() - try: - section_number = message._section_enum.from_text(u) - # We found a section name. If we don't have a message, - # use the one we just created. - if not self.message: - self.message = message - self.one_rr_per_rrset = message._get_one_rr_per_rrset( - self.one_rr_per_rrset - ) - if section_number == MessageSection.QUESTION: - line_method = self._question_line - else: - line_method = self._rr_line - except Exception: - # It's just a comment. - pass - self.tok.get_eol() - continue - self.tok.unget(token) - line_method(section_number) - if not self.message: - self.message = self._make_message() - return self.message - - -def from_text( - text: str, - idna_codec: Optional[dns.name.IDNACodec] = None, - one_rr_per_rrset: bool = False, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - relativize_to: Optional[dns.name.Name] = None, -) -> Message: - """Convert the text format message into a message object. - - The reader stops after reading the first blank line in the input to - facilitate reading multiple messages from a single file with - ``dns.message.from_file()``. - - *text*, a ``str``, the text format message. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put - into its own rrset. The default is ``False``. - - *origin*, a ``dns.name.Name`` (or ``None``), the - origin to use for relative names. - - *relativize*, a ``bool``. If true, name will be relativized. - - *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use - when relativizing names. If not set, the *origin* value will be used. - - Raises ``dns.message.UnknownHeaderField`` if a header is unknown. - - Raises ``dns.exception.SyntaxError`` if the text is badly formed. - - Returns a ``dns.message.Message object`` - """ - - # 'text' can also be a file, but we don't publish that fact - # since it's an implementation detail. The official file - # interface is from_file(). - - reader = _TextReader( - text, idna_codec, one_rr_per_rrset, origin, relativize, relativize_to - ) - return reader.read() - - -def from_file( - f: Any, - idna_codec: Optional[dns.name.IDNACodec] = None, - one_rr_per_rrset: bool = False, -) -> Message: - """Read the next text format message from the specified file. - - Message blocks are separated by a single blank line. - - *f*, a ``file`` or ``str``. If *f* is text, it is treated as the - pathname of a file to open. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - *one_rr_per_rrset*, a ``bool``. If ``True``, then each RR is put - into its own rrset. The default is ``False``. - - Raises ``dns.message.UnknownHeaderField`` if a header is unknown. - - Raises ``dns.exception.SyntaxError`` if the text is badly formed. - - Returns a ``dns.message.Message object`` - """ - - if isinstance(f, str): - cm: contextlib.AbstractContextManager = open(f) - else: - cm = contextlib.nullcontext(f) - with cm as f: - return from_text(f, idna_codec, one_rr_per_rrset) - assert False # for mypy lgtm[py/unreachable-statement] - - -def make_query( - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - use_edns: Optional[Union[int, bool]] = None, - want_dnssec: bool = False, - ednsflags: Optional[int] = None, - payload: Optional[int] = None, - request_payload: Optional[int] = None, - options: Optional[List[dns.edns.Option]] = None, - idna_codec: Optional[dns.name.IDNACodec] = None, - id: Optional[int] = None, - flags: int = dns.flags.RD, - pad: int = 0, -) -> QueryMessage: - """Make a query message. - - The query name, type, and class may all be specified either - as objects of the appropriate type, or as strings. - - The query will have a randomly chosen query id, and its DNS flags - will be set to dns.flags.RD. - - qname, a ``dns.name.Name`` or ``str``, the query name. - - *rdtype*, an ``int`` or ``str``, the desired rdata type. - - *rdclass*, an ``int`` or ``str``, the desired rdata class; the default - is class IN. - - *use_edns*, an ``int``, ``bool`` or ``None``. The EDNS level to use; the - default is ``None``. If ``None``, EDNS will be enabled only if other - parameters (*ednsflags*, *payload*, *request_payload*, or *options*) are - set. - See the description of dns.message.Message.use_edns() for the possible - values for use_edns and their meanings. - - *want_dnssec*, a ``bool``. If ``True``, DNSSEC data is desired. - - *ednsflags*, an ``int``, the EDNS flag values. - - *payload*, an ``int``, is the EDNS sender's payload field, which is the - maximum size of UDP datagram the sender can handle. I.e. how big - a response to this message can be. - - *request_payload*, an ``int``, is the EDNS payload size to use when - sending this message. If not specified, defaults to the value of - *payload*. - - *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS - options. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - *id*, an ``int`` or ``None``, the desired query id. The default is - ``None``, which generates a random query id. - - *flags*, an ``int``, the desired query flags. The default is - ``dns.flags.RD``. - - *pad*, a non-negative ``int``. If 0, the default, do not pad; otherwise add - padding bytes to make the message size a multiple of *pad*. Note that if - padding is non-zero, an EDNS PADDING option will always be added to the - message. - - Returns a ``dns.message.QueryMessage`` - """ - - if isinstance(qname, str): - qname = dns.name.from_text(qname, idna_codec=idna_codec) - rdtype = dns.rdatatype.RdataType.make(rdtype) - rdclass = dns.rdataclass.RdataClass.make(rdclass) - m = QueryMessage(id=id) - m.flags = dns.flags.Flag(flags) - m.find_rrset(m.question, qname, rdclass, rdtype, create=True, force_unique=True) - # only pass keywords on to use_edns if they have been set to a - # non-None value. Setting a field will turn EDNS on if it hasn't - # been configured. - kwargs: Dict[str, Any] = {} - if ednsflags is not None: - kwargs["ednsflags"] = ednsflags - if payload is not None: - kwargs["payload"] = payload - if request_payload is not None: - kwargs["request_payload"] = request_payload - if options is not None: - kwargs["options"] = options - if kwargs and use_edns is None: - use_edns = 0 - kwargs["edns"] = use_edns - kwargs["pad"] = pad - m.use_edns(**kwargs) - m.want_dnssec(want_dnssec) - return m - - -class CopyMode(enum.Enum): - """ - How should sections be copied when making an update response? - """ - - NOTHING = 0 - QUESTION = 1 - EVERYTHING = 2 - - -def make_response( - query: Message, - recursion_available: bool = False, - our_payload: int = 8192, - fudge: int = 300, - tsig_error: int = 0, - pad: Optional[int] = None, - copy_mode: Optional[CopyMode] = None, -) -> Message: - """Make a message which is a response for the specified query. - The message returned is really a response skeleton; it has all of the infrastructure - required of a response, but none of the content. - - Response section(s) which are copied are shallow copies of the matching section(s) - in the query, so the query's RRsets should not be changed. - - *query*, a ``dns.message.Message``, the query to respond to. - - *recursion_available*, a ``bool``, should RA be set in the response? - - *our_payload*, an ``int``, the payload size to advertise in EDNS responses. - - *fudge*, an ``int``, the TSIG time fudge. - - *tsig_error*, an ``int``, the TSIG error. - - *pad*, a non-negative ``int`` or ``None``. If 0, the default, do not pad; otherwise - if not ``None`` add padding bytes to make the message size a multiple of *pad*. Note - that if padding is non-zero, an EDNS PADDING option will always be added to the - message. If ``None``, add padding following RFC 8467, namely if the request is - padded, pad the response to 468 otherwise do not pad. - - *copy_mode*, a ``dns.message.CopyMode`` or ``None``, determines how sections are - copied. The default, ``None`` copies sections according to the default for the - message's opcode, which is currently ``dns.message.CopyMode.QUESTION`` for all - opcodes. ``dns.message.CopyMode.QUESTION`` copies only the question section. - ``dns.message.CopyMode.EVERYTHING`` copies all sections other than OPT or TSIG - records, which are created appropriately if needed. ``dns.message.CopyMode.NOTHING`` - copies no sections; note that this mode is for server testing purposes and is - otherwise not recommended for use. In particular, ``dns.message.is_response()`` - will be ``False`` if you create a response this way and the rcode is not - ``FORMERR``, ``SERVFAIL``, ``NOTIMP``, or ``REFUSED``. - - Returns a ``dns.message.Message`` object whose specific class is appropriate for the - query. For example, if query is a ``dns.update.UpdateMessage``, the response will - be one too. - """ - - if query.flags & dns.flags.QR: - raise dns.exception.FormError("specified query message is not a query") - opcode = query.opcode() - factory = _message_factory_from_opcode(opcode) - response = factory(id=query.id) - response.flags = dns.flags.QR | (query.flags & dns.flags.RD) - if recursion_available: - response.flags |= dns.flags.RA - response.set_opcode(opcode) - if copy_mode is None: - copy_mode = CopyMode.QUESTION - if copy_mode != CopyMode.NOTHING: - response.question = list(query.question) - if copy_mode == CopyMode.EVERYTHING: - response.answer = list(query.answer) - response.authority = list(query.authority) - response.additional = list(query.additional) - if query.edns >= 0: - if pad is None: - # Set response padding per RFC 8467 - pad = 0 - for option in query.options: - if option.otype == dns.edns.OptionType.PADDING: - pad = 468 - response.use_edns(0, 0, our_payload, query.payload, pad=pad) - if query.had_tsig: - response.use_tsig( - query.keyring, - query.keyname, - fudge, - None, - tsig_error, - b"", - query.keyalgorithm, - ) - response.request_mac = query.mac - return response - - -### BEGIN generated MessageSection constants - -QUESTION = MessageSection.QUESTION -ANSWER = MessageSection.ANSWER -AUTHORITY = MessageSection.AUTHORITY -ADDITIONAL = MessageSection.ADDITIONAL - -### END generated MessageSection constants diff --git a/venv/Lib/site-packages/dns/name.py b/venv/Lib/site-packages/dns/name.py deleted file mode 100644 index f79f0d0..0000000 --- a/venv/Lib/site-packages/dns/name.py +++ /dev/null @@ -1,1284 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Names. -""" - -import copy -import encodings.idna # type: ignore -import functools -import struct -from typing import Any, Callable, Dict, Iterable, Optional, Tuple, Union - -import dns._features -import dns.enum -import dns.exception -import dns.immutable -import dns.wire - -if dns._features.have("idna"): - import idna # type: ignore - - have_idna_2008 = True -else: # pragma: no cover - have_idna_2008 = False - -CompressType = Dict["Name", int] - - -class NameRelation(dns.enum.IntEnum): - """Name relation result from fullcompare().""" - - # This is an IntEnum for backwards compatibility in case anyone - # has hardwired the constants. - - #: The compared names have no relationship to each other. - NONE = 0 - #: the first name is a superdomain of the second. - SUPERDOMAIN = 1 - #: The first name is a subdomain of the second. - SUBDOMAIN = 2 - #: The compared names are equal. - EQUAL = 3 - #: The compared names have a common ancestor. - COMMONANCESTOR = 4 - - @classmethod - def _maximum(cls): - return cls.COMMONANCESTOR # pragma: no cover - - @classmethod - def _short_name(cls): - return cls.__name__ # pragma: no cover - - -# Backwards compatibility -NAMERELN_NONE = NameRelation.NONE -NAMERELN_SUPERDOMAIN = NameRelation.SUPERDOMAIN -NAMERELN_SUBDOMAIN = NameRelation.SUBDOMAIN -NAMERELN_EQUAL = NameRelation.EQUAL -NAMERELN_COMMONANCESTOR = NameRelation.COMMONANCESTOR - - -class EmptyLabel(dns.exception.SyntaxError): - """A DNS label is empty.""" - - -class BadEscape(dns.exception.SyntaxError): - """An escaped code in a text format of DNS name is invalid.""" - - -class BadPointer(dns.exception.FormError): - """A DNS compression pointer points forward instead of backward.""" - - -class BadLabelType(dns.exception.FormError): - """The label type in DNS name wire format is unknown.""" - - -class NeedAbsoluteNameOrOrigin(dns.exception.DNSException): - """An attempt was made to convert a non-absolute name to - wire when there was also a non-absolute (or missing) origin.""" - - -class NameTooLong(dns.exception.FormError): - """A DNS name is > 255 octets long.""" - - -class LabelTooLong(dns.exception.SyntaxError): - """A DNS label is > 63 octets long.""" - - -class AbsoluteConcatenation(dns.exception.DNSException): - """An attempt was made to append anything other than the - empty name to an absolute DNS name.""" - - -class NoParent(dns.exception.DNSException): - """An attempt was made to get the parent of the root name - or the empty name.""" - - -class NoIDNA2008(dns.exception.DNSException): - """IDNA 2008 processing was requested but the idna module is not - available.""" - - -class IDNAException(dns.exception.DNSException): - """IDNA processing raised an exception.""" - - supp_kwargs = {"idna_exception"} - fmt = "IDNA processing exception: {idna_exception}" - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - -class NeedSubdomainOfOrigin(dns.exception.DNSException): - """An absolute name was provided that is not a subdomain of the specified origin.""" - - -_escaped = b'"().;\\@$' -_escaped_text = '"().;\\@$' - - -def _escapify(label: Union[bytes, str]) -> str: - """Escape the characters in label which need it. - @returns: the escaped string - @rtype: string""" - if isinstance(label, bytes): - # Ordinary DNS label mode. Escape special characters and values - # < 0x20 or > 0x7f. - text = "" - for c in label: - if c in _escaped: - text += "\\" + chr(c) - elif c > 0x20 and c < 0x7F: - text += chr(c) - else: - text += "\\%03d" % c - return text - - # Unicode label mode. Escape only special characters and values < 0x20 - text = "" - for uc in label: - if uc in _escaped_text: - text += "\\" + uc - elif uc <= "\x20": - text += "\\%03d" % ord(uc) - else: - text += uc - return text - - -class IDNACodec: - """Abstract base class for IDNA encoder/decoders.""" - - def __init__(self): - pass - - def is_idna(self, label: bytes) -> bool: - return label.lower().startswith(b"xn--") - - def encode(self, label: str) -> bytes: - raise NotImplementedError # pragma: no cover - - def decode(self, label: bytes) -> str: - # We do not apply any IDNA policy on decode. - if self.is_idna(label): - try: - slabel = label[4:].decode("punycode") - return _escapify(slabel) - except Exception as e: - raise IDNAException(idna_exception=e) - else: - return _escapify(label) - - -class IDNA2003Codec(IDNACodec): - """IDNA 2003 encoder/decoder.""" - - def __init__(self, strict_decode: bool = False): - """Initialize the IDNA 2003 encoder/decoder. - - *strict_decode* is a ``bool``. If `True`, then IDNA2003 checking - is done when decoding. This can cause failures if the name - was encoded with IDNA2008. The default is `False`. - """ - - super().__init__() - self.strict_decode = strict_decode - - def encode(self, label: str) -> bytes: - """Encode *label*.""" - - if label == "": - return b"" - try: - return encodings.idna.ToASCII(label) - except UnicodeError: - raise LabelTooLong - - def decode(self, label: bytes) -> str: - """Decode *label*.""" - if not self.strict_decode: - return super().decode(label) - if label == b"": - return "" - try: - return _escapify(encodings.idna.ToUnicode(label)) - except Exception as e: - raise IDNAException(idna_exception=e) - - -class IDNA2008Codec(IDNACodec): - """IDNA 2008 encoder/decoder.""" - - def __init__( - self, - uts_46: bool = False, - transitional: bool = False, - allow_pure_ascii: bool = False, - strict_decode: bool = False, - ): - """Initialize the IDNA 2008 encoder/decoder. - - *uts_46* is a ``bool``. If True, apply Unicode IDNA - compatibility processing as described in Unicode Technical - Standard #46 (https://unicode.org/reports/tr46/). - If False, do not apply the mapping. The default is False. - - *transitional* is a ``bool``: If True, use the - "transitional" mode described in Unicode Technical Standard - #46. The default is False. - - *allow_pure_ascii* is a ``bool``. If True, then a label which - consists of only ASCII characters is allowed. This is less - strict than regular IDNA 2008, but is also necessary for mixed - names, e.g. a name with starting with "_sip._tcp." and ending - in an IDN suffix which would otherwise be disallowed. The - default is False. - - *strict_decode* is a ``bool``: If True, then IDNA2008 checking - is done when decoding. This can cause failures if the name - was encoded with IDNA2003. The default is False. - """ - super().__init__() - self.uts_46 = uts_46 - self.transitional = transitional - self.allow_pure_ascii = allow_pure_ascii - self.strict_decode = strict_decode - - def encode(self, label: str) -> bytes: - if label == "": - return b"" - if self.allow_pure_ascii and is_all_ascii(label): - encoded = label.encode("ascii") - if len(encoded) > 63: - raise LabelTooLong - return encoded - if not have_idna_2008: - raise NoIDNA2008 - try: - if self.uts_46: - # pylint: disable=possibly-used-before-assignment - label = idna.uts46_remap(label, False, self.transitional) - return idna.alabel(label) - except idna.IDNAError as e: - if e.args[0] == "Label too long": - raise LabelTooLong - else: - raise IDNAException(idna_exception=e) - - def decode(self, label: bytes) -> str: - if not self.strict_decode: - return super().decode(label) - if label == b"": - return "" - if not have_idna_2008: - raise NoIDNA2008 - try: - ulabel = idna.ulabel(label) - if self.uts_46: - ulabel = idna.uts46_remap(ulabel, False, self.transitional) - return _escapify(ulabel) - except (idna.IDNAError, UnicodeError) as e: - raise IDNAException(idna_exception=e) - - -IDNA_2003_Practical = IDNA2003Codec(False) -IDNA_2003_Strict = IDNA2003Codec(True) -IDNA_2003 = IDNA_2003_Practical -IDNA_2008_Practical = IDNA2008Codec(True, False, True, False) -IDNA_2008_UTS_46 = IDNA2008Codec(True, False, False, False) -IDNA_2008_Strict = IDNA2008Codec(False, False, False, True) -IDNA_2008_Transitional = IDNA2008Codec(True, True, False, False) -IDNA_2008 = IDNA_2008_Practical - - -def _validate_labels(labels: Tuple[bytes, ...]) -> None: - """Check for empty labels in the middle of a label sequence, - labels that are too long, and for too many labels. - - Raises ``dns.name.NameTooLong`` if the name as a whole is too long. - - Raises ``dns.name.EmptyLabel`` if a label is empty (i.e. the root - label) and appears in a position other than the end of the label - sequence - - """ - - l = len(labels) - total = 0 - i = -1 - j = 0 - for label in labels: - ll = len(label) - total += ll + 1 - if ll > 63: - raise LabelTooLong - if i < 0 and label == b"": - i = j - j += 1 - if total > 255: - raise NameTooLong - if i >= 0 and i != l - 1: - raise EmptyLabel - - -def _maybe_convert_to_binary(label: Union[bytes, str]) -> bytes: - """If label is ``str``, convert it to ``bytes``. If it is already - ``bytes`` just return it. - - """ - - if isinstance(label, bytes): - return label - if isinstance(label, str): - return label.encode() - raise ValueError # pragma: no cover - - -@dns.immutable.immutable -class Name: - """A DNS name. - - The dns.name.Name class represents a DNS name as a tuple of - labels. Each label is a ``bytes`` in DNS wire format. Instances - of the class are immutable. - """ - - __slots__ = ["labels"] - - def __init__(self, labels: Iterable[Union[bytes, str]]): - """*labels* is any iterable whose values are ``str`` or ``bytes``.""" - - blabels = [_maybe_convert_to_binary(x) for x in labels] - self.labels = tuple(blabels) - _validate_labels(self.labels) - - def __copy__(self): - return Name(self.labels) - - def __deepcopy__(self, memo): - return Name(copy.deepcopy(self.labels, memo)) - - def __getstate__(self): - # Names can be pickled - return {"labels": self.labels} - - def __setstate__(self, state): - super().__setattr__("labels", state["labels"]) - _validate_labels(self.labels) - - def is_absolute(self) -> bool: - """Is the most significant label of this name the root label? - - Returns a ``bool``. - """ - - return len(self.labels) > 0 and self.labels[-1] == b"" - - def is_wild(self) -> bool: - """Is this name wild? (I.e. Is the least significant label '*'?) - - Returns a ``bool``. - """ - - return len(self.labels) > 0 and self.labels[0] == b"*" - - def __hash__(self) -> int: - """Return a case-insensitive hash of the name. - - Returns an ``int``. - """ - - h = 0 - for label in self.labels: - for c in label.lower(): - h += (h << 3) + c - return h - - def fullcompare(self, other: "Name") -> Tuple[NameRelation, int, int]: - """Compare two names, returning a 3-tuple - ``(relation, order, nlabels)``. - - *relation* describes the relation ship between the names, - and is one of: ``dns.name.NameRelation.NONE``, - ``dns.name.NameRelation.SUPERDOMAIN``, ``dns.name.NameRelation.SUBDOMAIN``, - ``dns.name.NameRelation.EQUAL``, or ``dns.name.NameRelation.COMMONANCESTOR``. - - *order* is < 0 if *self* < *other*, > 0 if *self* > *other*, and == - 0 if *self* == *other*. A relative name is always less than an - absolute name. If both names have the same relativity, then - the DNSSEC order relation is used to order them. - - *nlabels* is the number of significant labels that the two names - have in common. - - Here are some examples. Names ending in "." are absolute names, - those not ending in "." are relative names. - - ============= ============= =========== ===== ======= - self other relation order nlabels - ============= ============= =========== ===== ======= - www.example. www.example. equal 0 3 - www.example. example. subdomain > 0 2 - example. www.example. superdomain < 0 2 - example1.com. example2.com. common anc. < 0 2 - example1 example2. none < 0 0 - example1. example2 none > 0 0 - ============= ============= =========== ===== ======= - """ - - sabs = self.is_absolute() - oabs = other.is_absolute() - if sabs != oabs: - if sabs: - return (NameRelation.NONE, 1, 0) - else: - return (NameRelation.NONE, -1, 0) - l1 = len(self.labels) - l2 = len(other.labels) - ldiff = l1 - l2 - if ldiff < 0: - l = l1 - else: - l = l2 - - order = 0 - nlabels = 0 - namereln = NameRelation.NONE - while l > 0: - l -= 1 - l1 -= 1 - l2 -= 1 - label1 = self.labels[l1].lower() - label2 = other.labels[l2].lower() - if label1 < label2: - order = -1 - if nlabels > 0: - namereln = NameRelation.COMMONANCESTOR - return (namereln, order, nlabels) - elif label1 > label2: - order = 1 - if nlabels > 0: - namereln = NameRelation.COMMONANCESTOR - return (namereln, order, nlabels) - nlabels += 1 - order = ldiff - if ldiff < 0: - namereln = NameRelation.SUPERDOMAIN - elif ldiff > 0: - namereln = NameRelation.SUBDOMAIN - else: - namereln = NameRelation.EQUAL - return (namereln, order, nlabels) - - def is_subdomain(self, other: "Name") -> bool: - """Is self a subdomain of other? - - Note that the notion of subdomain includes equality, e.g. - "dnspython.org" is a subdomain of itself. - - Returns a ``bool``. - """ - - (nr, _, _) = self.fullcompare(other) - if nr == NameRelation.SUBDOMAIN or nr == NameRelation.EQUAL: - return True - return False - - def is_superdomain(self, other: "Name") -> bool: - """Is self a superdomain of other? - - Note that the notion of superdomain includes equality, e.g. - "dnspython.org" is a superdomain of itself. - - Returns a ``bool``. - """ - - (nr, _, _) = self.fullcompare(other) - if nr == NameRelation.SUPERDOMAIN or nr == NameRelation.EQUAL: - return True - return False - - def canonicalize(self) -> "Name": - """Return a name which is equal to the current name, but is in - DNSSEC canonical form. - """ - - return Name([x.lower() for x in self.labels]) - - def __eq__(self, other): - if isinstance(other, Name): - return self.fullcompare(other)[1] == 0 - else: - return False - - def __ne__(self, other): - if isinstance(other, Name): - return self.fullcompare(other)[1] != 0 - else: - return True - - def __lt__(self, other): - if isinstance(other, Name): - return self.fullcompare(other)[1] < 0 - else: - return NotImplemented - - def __le__(self, other): - if isinstance(other, Name): - return self.fullcompare(other)[1] <= 0 - else: - return NotImplemented - - def __ge__(self, other): - if isinstance(other, Name): - return self.fullcompare(other)[1] >= 0 - else: - return NotImplemented - - def __gt__(self, other): - if isinstance(other, Name): - return self.fullcompare(other)[1] > 0 - else: - return NotImplemented - - def __repr__(self): - return "" - - def __str__(self): - return self.to_text(False) - - def to_text(self, omit_final_dot: bool = False) -> str: - """Convert name to DNS text format. - - *omit_final_dot* is a ``bool``. If True, don't emit the final - dot (denoting the root label) for absolute names. The default - is False. - - Returns a ``str``. - """ - - if len(self.labels) == 0: - return "@" - if len(self.labels) == 1 and self.labels[0] == b"": - return "." - if omit_final_dot and self.is_absolute(): - l = self.labels[:-1] - else: - l = self.labels - s = ".".join(map(_escapify, l)) - return s - - def to_unicode( - self, omit_final_dot: bool = False, idna_codec: Optional[IDNACodec] = None - ) -> str: - """Convert name to Unicode text format. - - IDN ACE labels are converted to Unicode. - - *omit_final_dot* is a ``bool``. If True, don't emit the final - dot (denoting the root label) for absolute names. The default - is False. - *idna_codec* specifies the IDNA encoder/decoder. If None, the - dns.name.IDNA_2003_Practical encoder/decoder is used. - The IDNA_2003_Practical decoder does - not impose any policy, it just decodes punycode, so if you - don't want checking for compliance, you can use this decoder - for IDNA2008 as well. - - Returns a ``str``. - """ - - if len(self.labels) == 0: - return "@" - if len(self.labels) == 1 and self.labels[0] == b"": - return "." - if omit_final_dot and self.is_absolute(): - l = self.labels[:-1] - else: - l = self.labels - if idna_codec is None: - idna_codec = IDNA_2003_Practical - return ".".join([idna_codec.decode(x) for x in l]) - - def to_digestable(self, origin: Optional["Name"] = None) -> bytes: - """Convert name to a format suitable for digesting in hashes. - - The name is canonicalized and converted to uncompressed wire - format. All names in wire format are absolute. If the name - is a relative name, then an origin must be supplied. - - *origin* is a ``dns.name.Name`` or ``None``. If the name is - relative and origin is not ``None``, then origin will be appended - to the name. - - Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is - relative and no origin was provided. - - Returns a ``bytes``. - """ - - digest = self.to_wire(origin=origin, canonicalize=True) - assert digest is not None - return digest - - def to_wire( - self, - file: Optional[Any] = None, - compress: Optional[CompressType] = None, - origin: Optional["Name"] = None, - canonicalize: bool = False, - ) -> Optional[bytes]: - """Convert name to wire format, possibly compressing it. - - *file* is the file where the name is emitted (typically an - io.BytesIO file). If ``None`` (the default), a ``bytes`` - containing the wire name will be returned. - - *compress*, a ``dict``, is the compression table to use. If - ``None`` (the default), names will not be compressed. Note that - the compression code assumes that compression offset 0 is the - start of *file*, and thus compression will not be correct - if this is not the case. - - *origin* is a ``dns.name.Name`` or ``None``. If the name is - relative and origin is not ``None``, then *origin* will be appended - to it. - - *canonicalize*, a ``bool``, indicates whether the name should - be canonicalized; that is, converted to a format suitable for - digesting in hashes. - - Raises ``dns.name.NeedAbsoluteNameOrOrigin`` if the name is - relative and no origin was provided. - - Returns a ``bytes`` or ``None``. - """ - - if file is None: - out = bytearray() - for label in self.labels: - out.append(len(label)) - if canonicalize: - out += label.lower() - else: - out += label - if not self.is_absolute(): - if origin is None or not origin.is_absolute(): - raise NeedAbsoluteNameOrOrigin - for label in origin.labels: - out.append(len(label)) - if canonicalize: - out += label.lower() - else: - out += label - return bytes(out) - - labels: Iterable[bytes] - if not self.is_absolute(): - if origin is None or not origin.is_absolute(): - raise NeedAbsoluteNameOrOrigin - labels = list(self.labels) - labels.extend(list(origin.labels)) - else: - labels = self.labels - i = 0 - for label in labels: - n = Name(labels[i:]) - i += 1 - if compress is not None: - pos = compress.get(n) - else: - pos = None - if pos is not None: - value = 0xC000 + pos - s = struct.pack("!H", value) - file.write(s) - break - else: - if compress is not None and len(n) > 1: - pos = file.tell() - if pos <= 0x3FFF: - compress[n] = pos - l = len(label) - file.write(struct.pack("!B", l)) - if l > 0: - if canonicalize: - file.write(label.lower()) - else: - file.write(label) - return None - - def __len__(self) -> int: - """The length of the name (in labels). - - Returns an ``int``. - """ - - return len(self.labels) - - def __getitem__(self, index): - return self.labels[index] - - def __add__(self, other): - return self.concatenate(other) - - def __sub__(self, other): - return self.relativize(other) - - def split(self, depth: int) -> Tuple["Name", "Name"]: - """Split a name into a prefix and suffix names at the specified depth. - - *depth* is an ``int`` specifying the number of labels in the suffix - - Raises ``ValueError`` if *depth* was not >= 0 and <= the length of the - name. - - Returns the tuple ``(prefix, suffix)``. - """ - - l = len(self.labels) - if depth == 0: - return (self, dns.name.empty) - elif depth == l: - return (dns.name.empty, self) - elif depth < 0 or depth > l: - raise ValueError("depth must be >= 0 and <= the length of the name") - return (Name(self[:-depth]), Name(self[-depth:])) - - def concatenate(self, other: "Name") -> "Name": - """Return a new name which is the concatenation of self and other. - - Raises ``dns.name.AbsoluteConcatenation`` if the name is - absolute and *other* is not the empty name. - - Returns a ``dns.name.Name``. - """ - - if self.is_absolute() and len(other) > 0: - raise AbsoluteConcatenation - labels = list(self.labels) - labels.extend(list(other.labels)) - return Name(labels) - - def relativize(self, origin: "Name") -> "Name": - """If the name is a subdomain of *origin*, return a new name which is - the name relative to origin. Otherwise return the name. - - For example, relativizing ``www.dnspython.org.`` to origin - ``dnspython.org.`` returns the name ``www``. Relativizing ``example.`` - to origin ``dnspython.org.`` returns ``example.``. - - Returns a ``dns.name.Name``. - """ - - if origin is not None and self.is_subdomain(origin): - return Name(self[: -len(origin)]) - else: - return self - - def derelativize(self, origin: "Name") -> "Name": - """If the name is a relative name, return a new name which is the - concatenation of the name and origin. Otherwise return the name. - - For example, derelativizing ``www`` to origin ``dnspython.org.`` - returns the name ``www.dnspython.org.``. Derelativizing ``example.`` - to origin ``dnspython.org.`` returns ``example.``. - - Returns a ``dns.name.Name``. - """ - - if not self.is_absolute(): - return self.concatenate(origin) - else: - return self - - def choose_relativity( - self, origin: Optional["Name"] = None, relativize: bool = True - ) -> "Name": - """Return a name with the relativity desired by the caller. - - If *origin* is ``None``, then the name is returned. - Otherwise, if *relativize* is ``True`` the name is - relativized, and if *relativize* is ``False`` the name is - derelativized. - - Returns a ``dns.name.Name``. - """ - - if origin: - if relativize: - return self.relativize(origin) - else: - return self.derelativize(origin) - else: - return self - - def parent(self) -> "Name": - """Return the parent of the name. - - For example, the parent of ``www.dnspython.org.`` is ``dnspython.org``. - - Raises ``dns.name.NoParent`` if the name is either the root name or the - empty name, and thus has no parent. - - Returns a ``dns.name.Name``. - """ - - if self == root or self == empty: - raise NoParent - return Name(self.labels[1:]) - - def predecessor(self, origin: "Name", prefix_ok: bool = True) -> "Name": - """Return the maximal predecessor of *name* in the DNSSEC ordering in the zone - whose origin is *origin*, or return the longest name under *origin* if the - name is origin (i.e. wrap around to the longest name, which may still be - *origin* due to length considerations. - - The relativity of the name is preserved, so if this name is relative - then the method will return a relative name, and likewise if this name - is absolute then the predecessor will be absolute. - - *prefix_ok* indicates if prefixing labels is allowed, and - defaults to ``True``. Normally it is good to allow this, but if computing - a maximal predecessor at a zone cut point then ``False`` must be specified. - """ - return _handle_relativity_and_call( - _absolute_predecessor, self, origin, prefix_ok - ) - - def successor(self, origin: "Name", prefix_ok: bool = True) -> "Name": - """Return the minimal successor of *name* in the DNSSEC ordering in the zone - whose origin is *origin*, or return *origin* if the successor cannot be - computed due to name length limitations. - - Note that *origin* is returned in the "too long" cases because wrapping - around to the origin is how NSEC records express "end of the zone". - - The relativity of the name is preserved, so if this name is relative - then the method will return a relative name, and likewise if this name - is absolute then the successor will be absolute. - - *prefix_ok* indicates if prefixing a new minimal label is allowed, and - defaults to ``True``. Normally it is good to allow this, but if computing - a minimal successor at a zone cut point then ``False`` must be specified. - """ - return _handle_relativity_and_call(_absolute_successor, self, origin, prefix_ok) - - -#: The root name, '.' -root = Name([b""]) - -#: The empty name. -empty = Name([]) - - -def from_unicode( - text: str, origin: Optional[Name] = root, idna_codec: Optional[IDNACodec] = None -) -> Name: - """Convert unicode text into a Name object. - - Labels are encoded in IDN ACE form according to rules specified by - the IDNA codec. - - *text*, a ``str``, is the text to convert into a name. - - *origin*, a ``dns.name.Name``, specifies the origin to - append to non-absolute names. The default is the root name. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - Returns a ``dns.name.Name``. - """ - - if not isinstance(text, str): - raise ValueError("input to from_unicode() must be a unicode string") - if not (origin is None or isinstance(origin, Name)): - raise ValueError("origin must be a Name or None") - labels = [] - label = "" - escaping = False - edigits = 0 - total = 0 - if idna_codec is None: - idna_codec = IDNA_2003 - if text == "@": - text = "" - if text: - if text in [".", "\u3002", "\uff0e", "\uff61"]: - return Name([b""]) # no Unicode "u" on this constant! - for c in text: - if escaping: - if edigits == 0: - if c.isdigit(): - total = int(c) - edigits += 1 - else: - label += c - escaping = False - else: - if not c.isdigit(): - raise BadEscape - total *= 10 - total += int(c) - edigits += 1 - if edigits == 3: - escaping = False - label += chr(total) - elif c in [".", "\u3002", "\uff0e", "\uff61"]: - if len(label) == 0: - raise EmptyLabel - labels.append(idna_codec.encode(label)) - label = "" - elif c == "\\": - escaping = True - edigits = 0 - total = 0 - else: - label += c - if escaping: - raise BadEscape - if len(label) > 0: - labels.append(idna_codec.encode(label)) - else: - labels.append(b"") - - if (len(labels) == 0 or labels[-1] != b"") and origin is not None: - labels.extend(list(origin.labels)) - return Name(labels) - - -def is_all_ascii(text: str) -> bool: - for c in text: - if ord(c) > 0x7F: - return False - return True - - -def from_text( - text: Union[bytes, str], - origin: Optional[Name] = root, - idna_codec: Optional[IDNACodec] = None, -) -> Name: - """Convert text into a Name object. - - *text*, a ``bytes`` or ``str``, is the text to convert into a name. - - *origin*, a ``dns.name.Name``, specifies the origin to - append to non-absolute names. The default is the root name. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - Returns a ``dns.name.Name``. - """ - - if isinstance(text, str): - if not is_all_ascii(text): - # Some codepoint in the input text is > 127, so IDNA applies. - return from_unicode(text, origin, idna_codec) - # The input is all ASCII, so treat this like an ordinary non-IDNA - # domain name. Note that "all ASCII" is about the input text, - # not the codepoints in the domain name. E.g. if text has value - # - # r'\150\151\152\153\154\155\156\157\158\159' - # - # then it's still "all ASCII" even though the domain name has - # codepoints > 127. - text = text.encode("ascii") - if not isinstance(text, bytes): - raise ValueError("input to from_text() must be a string") - if not (origin is None or isinstance(origin, Name)): - raise ValueError("origin must be a Name or None") - labels = [] - label = b"" - escaping = False - edigits = 0 - total = 0 - if text == b"@": - text = b"" - if text: - if text == b".": - return Name([b""]) - for c in text: - byte_ = struct.pack("!B", c) - if escaping: - if edigits == 0: - if byte_.isdigit(): - total = int(byte_) - edigits += 1 - else: - label += byte_ - escaping = False - else: - if not byte_.isdigit(): - raise BadEscape - total *= 10 - total += int(byte_) - edigits += 1 - if edigits == 3: - escaping = False - label += struct.pack("!B", total) - elif byte_ == b".": - if len(label) == 0: - raise EmptyLabel - labels.append(label) - label = b"" - elif byte_ == b"\\": - escaping = True - edigits = 0 - total = 0 - else: - label += byte_ - if escaping: - raise BadEscape - if len(label) > 0: - labels.append(label) - else: - labels.append(b"") - if (len(labels) == 0 or labels[-1] != b"") and origin is not None: - labels.extend(list(origin.labels)) - return Name(labels) - - -# we need 'dns.wire.Parser' quoted as dns.name and dns.wire depend on each other. - - -def from_wire_parser(parser: "dns.wire.Parser") -> Name: - """Convert possibly compressed wire format into a Name. - - *parser* is a dns.wire.Parser. - - Raises ``dns.name.BadPointer`` if a compression pointer did not - point backwards in the message. - - Raises ``dns.name.BadLabelType`` if an invalid label type was encountered. - - Returns a ``dns.name.Name`` - """ - - labels = [] - biggest_pointer = parser.current - with parser.restore_furthest(): - count = parser.get_uint8() - while count != 0: - if count < 64: - labels.append(parser.get_bytes(count)) - elif count >= 192: - current = (count & 0x3F) * 256 + parser.get_uint8() - if current >= biggest_pointer: - raise BadPointer - biggest_pointer = current - parser.seek(current) - else: - raise BadLabelType - count = parser.get_uint8() - labels.append(b"") - return Name(labels) - - -def from_wire(message: bytes, current: int) -> Tuple[Name, int]: - """Convert possibly compressed wire format into a Name. - - *message* is a ``bytes`` containing an entire DNS message in DNS - wire form. - - *current*, an ``int``, is the offset of the beginning of the name - from the start of the message - - Raises ``dns.name.BadPointer`` if a compression pointer did not - point backwards in the message. - - Raises ``dns.name.BadLabelType`` if an invalid label type was encountered. - - Returns a ``(dns.name.Name, int)`` tuple consisting of the name - that was read and the number of bytes of the wire format message - which were consumed reading it. - """ - - if not isinstance(message, bytes): - raise ValueError("input to from_wire() must be a byte string") - parser = dns.wire.Parser(message, current) - name = from_wire_parser(parser) - return (name, parser.current - current) - - -# RFC 4471 Support - -_MINIMAL_OCTET = b"\x00" -_MINIMAL_OCTET_VALUE = ord(_MINIMAL_OCTET) -_SUCCESSOR_PREFIX = Name([_MINIMAL_OCTET]) -_MAXIMAL_OCTET = b"\xff" -_MAXIMAL_OCTET_VALUE = ord(_MAXIMAL_OCTET) -_AT_SIGN_VALUE = ord("@") -_LEFT_SQUARE_BRACKET_VALUE = ord("[") - - -def _wire_length(labels): - return functools.reduce(lambda v, x: v + len(x) + 1, labels, 0) - - -def _pad_to_max_name(name): - needed = 255 - _wire_length(name.labels) - new_labels = [] - while needed > 64: - new_labels.append(_MAXIMAL_OCTET * 63) - needed -= 64 - if needed >= 2: - new_labels.append(_MAXIMAL_OCTET * (needed - 1)) - # Note we're already maximal in the needed == 1 case as while we'd like - # to add one more byte as a new label, we can't, as adding a new non-empty - # label requires at least 2 bytes. - new_labels = list(reversed(new_labels)) - new_labels.extend(name.labels) - return Name(new_labels) - - -def _pad_to_max_label(label, suffix_labels): - length = len(label) - # We have to subtract one here to account for the length byte of label. - remaining = 255 - _wire_length(suffix_labels) - length - 1 - if remaining <= 0: - # Shouldn't happen! - return label - needed = min(63 - length, remaining) - return label + _MAXIMAL_OCTET * needed - - -def _absolute_predecessor(name: Name, origin: Name, prefix_ok: bool) -> Name: - # This is the RFC 4471 predecessor algorithm using the "absolute method" of section - # 3.1.1. - # - # Our caller must ensure that the name and origin are absolute, and that name is a - # subdomain of origin. - if name == origin: - return _pad_to_max_name(name) - least_significant_label = name[0] - if least_significant_label == _MINIMAL_OCTET: - return name.parent() - least_octet = least_significant_label[-1] - suffix_labels = name.labels[1:] - if least_octet == _MINIMAL_OCTET_VALUE: - new_labels = [least_significant_label[:-1]] - else: - octets = bytearray(least_significant_label) - octet = octets[-1] - if octet == _LEFT_SQUARE_BRACKET_VALUE: - octet = _AT_SIGN_VALUE - else: - octet -= 1 - octets[-1] = octet - least_significant_label = bytes(octets) - new_labels = [_pad_to_max_label(least_significant_label, suffix_labels)] - new_labels.extend(suffix_labels) - name = Name(new_labels) - if prefix_ok: - return _pad_to_max_name(name) - else: - return name - - -def _absolute_successor(name: Name, origin: Name, prefix_ok: bool) -> Name: - # This is the RFC 4471 successor algorithm using the "absolute method" of section - # 3.1.2. - # - # Our caller must ensure that the name and origin are absolute, and that name is a - # subdomain of origin. - if prefix_ok: - # Try prefixing \000 as new label - try: - return _SUCCESSOR_PREFIX.concatenate(name) - except NameTooLong: - pass - while name != origin: - # Try extending the least significant label. - least_significant_label = name[0] - if len(least_significant_label) < 63: - # We may be able to extend the least label with a minimal additional byte. - # This is only "may" because we could have a maximal length name even though - # the least significant label isn't maximally long. - new_labels = [least_significant_label + _MINIMAL_OCTET] - new_labels.extend(name.labels[1:]) - try: - return dns.name.Name(new_labels) - except dns.name.NameTooLong: - pass - # We can't extend the label either, so we'll try to increment the least - # signficant non-maximal byte in it. - octets = bytearray(least_significant_label) - # We do this reversed iteration with an explicit indexing variable because - # if we find something to increment, we're going to want to truncate everything - # to the right of it. - for i in range(len(octets) - 1, -1, -1): - octet = octets[i] - if octet == _MAXIMAL_OCTET_VALUE: - # We can't increment this, so keep looking. - continue - # Finally, something we can increment. We have to apply a special rule for - # incrementing "@", sending it to "[", because RFC 4034 6.1 says that when - # comparing names, uppercase letters compare as if they were their - # lower-case equivalents. If we increment "@" to "A", then it would compare - # as "a", which is after "[", "\", "]", "^", "_", and "`", so we would have - # skipped the most minimal successor, namely "[". - if octet == _AT_SIGN_VALUE: - octet = _LEFT_SQUARE_BRACKET_VALUE - else: - octet += 1 - octets[i] = octet - # We can now truncate all of the maximal values we skipped (if any) - new_labels = [bytes(octets[: i + 1])] - new_labels.extend(name.labels[1:]) - # We haven't changed the length of the name, so the Name constructor will - # always work. - return Name(new_labels) - # We couldn't increment, so chop off the least significant label and try - # again. - name = name.parent() - - # We couldn't increment at all, so return the origin, as wrapping around is the - # DNSSEC way. - return origin - - -def _handle_relativity_and_call( - function: Callable[[Name, Name, bool], Name], - name: Name, - origin: Name, - prefix_ok: bool, -) -> Name: - # Make "name" absolute if needed, ensure that the origin is absolute, - # call function(), and then relativize the result if needed. - if not origin.is_absolute(): - raise NeedAbsoluteNameOrOrigin - relative = not name.is_absolute() - if relative: - name = name.derelativize(origin) - elif not name.is_subdomain(origin): - raise NeedSubdomainOfOrigin - result_name = function(name, origin, prefix_ok) - if relative: - result_name = result_name.relativize(origin) - return result_name diff --git a/venv/Lib/site-packages/dns/namedict.py b/venv/Lib/site-packages/dns/namedict.py deleted file mode 100644 index ca8b197..0000000 --- a/venv/Lib/site-packages/dns/namedict.py +++ /dev/null @@ -1,109 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# Copyright (C) 2016 Coresec Systems AB -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND CORESEC SYSTEMS AB DISCLAIMS ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CORESEC -# SYSTEMS AB BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, -# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION -# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS name dictionary""" - -# pylint seems to be confused about this one! -from collections.abc import MutableMapping # pylint: disable=no-name-in-module - -import dns.name - - -class NameDict(MutableMapping): - """A dictionary whose keys are dns.name.Name objects. - - In addition to being like a regular Python dictionary, this - dictionary can also get the deepest match for a given key. - """ - - __slots__ = ["max_depth", "max_depth_items", "__store"] - - def __init__(self, *args, **kwargs): - super().__init__() - self.__store = dict() - #: the maximum depth of the keys that have ever been added - self.max_depth = 0 - #: the number of items of maximum depth - self.max_depth_items = 0 - self.update(dict(*args, **kwargs)) - - def __update_max_depth(self, key): - if len(key) == self.max_depth: - self.max_depth_items = self.max_depth_items + 1 - elif len(key) > self.max_depth: - self.max_depth = len(key) - self.max_depth_items = 1 - - def __getitem__(self, key): - return self.__store[key] - - def __setitem__(self, key, value): - if not isinstance(key, dns.name.Name): - raise ValueError("NameDict key must be a name") - self.__store[key] = value - self.__update_max_depth(key) - - def __delitem__(self, key): - self.__store.pop(key) - if len(key) == self.max_depth: - self.max_depth_items = self.max_depth_items - 1 - if self.max_depth_items == 0: - self.max_depth = 0 - for k in self.__store: - self.__update_max_depth(k) - - def __iter__(self): - return iter(self.__store) - - def __len__(self): - return len(self.__store) - - def has_key(self, key): - return key in self.__store - - def get_deepest_match(self, name): - """Find the deepest match to *name* in the dictionary. - - The deepest match is the longest name in the dictionary which is - a superdomain of *name*. Note that *superdomain* includes matching - *name* itself. - - *name*, a ``dns.name.Name``, the name to find. - - Returns a ``(key, value)`` where *key* is the deepest - ``dns.name.Name``, and *value* is the value associated with *key*. - """ - - depth = len(name) - if depth > self.max_depth: - depth = self.max_depth - for i in range(-depth, 0): - n = dns.name.Name(name[i:]) - if n in self: - return (n, self[n]) - v = self[dns.name.empty] - return (dns.name.empty, v) diff --git a/venv/Lib/site-packages/dns/nameserver.py b/venv/Lib/site-packages/dns/nameserver.py deleted file mode 100644 index b02a239..0000000 --- a/venv/Lib/site-packages/dns/nameserver.py +++ /dev/null @@ -1,363 +0,0 @@ -from typing import Optional, Union -from urllib.parse import urlparse - -import dns.asyncbackend -import dns.asyncquery -import dns.inet -import dns.message -import dns.query - - -class Nameserver: - def __init__(self): - pass - - def __str__(self): - raise NotImplementedError - - def kind(self) -> str: - raise NotImplementedError - - def is_always_max_size(self) -> bool: - raise NotImplementedError - - def answer_nameserver(self) -> str: - raise NotImplementedError - - def answer_port(self) -> int: - raise NotImplementedError - - def query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - raise NotImplementedError - - async def async_query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - backend: dns.asyncbackend.Backend, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - raise NotImplementedError - - -class AddressAndPortNameserver(Nameserver): - def __init__(self, address: str, port: int): - super().__init__() - self.address = address - self.port = port - - def kind(self) -> str: - raise NotImplementedError - - def is_always_max_size(self) -> bool: - return False - - def __str__(self): - ns_kind = self.kind() - return f"{ns_kind}:{self.address}@{self.port}" - - def answer_nameserver(self) -> str: - return self.address - - def answer_port(self) -> int: - return self.port - - -class Do53Nameserver(AddressAndPortNameserver): - def __init__(self, address: str, port: int = 53): - super().__init__(address, port) - - def kind(self): - return "Do53" - - def query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - if max_size: - response = dns.query.tcp( - request, - self.address, - timeout=timeout, - port=self.port, - source=source, - source_port=source_port, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - else: - response = dns.query.udp( - request, - self.address, - timeout=timeout, - port=self.port, - source=source, - source_port=source_port, - raise_on_truncation=True, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ignore_errors=True, - ignore_unexpected=True, - ) - return response - - async def async_query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - backend: dns.asyncbackend.Backend, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - if max_size: - response = await dns.asyncquery.tcp( - request, - self.address, - timeout=timeout, - port=self.port, - source=source, - source_port=source_port, - backend=backend, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - else: - response = await dns.asyncquery.udp( - request, - self.address, - timeout=timeout, - port=self.port, - source=source, - source_port=source_port, - raise_on_truncation=True, - backend=backend, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ignore_errors=True, - ignore_unexpected=True, - ) - return response - - -class DoHNameserver(Nameserver): - def __init__( - self, - url: str, - bootstrap_address: Optional[str] = None, - verify: Union[bool, str] = True, - want_get: bool = False, - http_version: dns.query.HTTPVersion = dns.query.HTTPVersion.DEFAULT, - ): - super().__init__() - self.url = url - self.bootstrap_address = bootstrap_address - self.verify = verify - self.want_get = want_get - self.http_version = http_version - - def kind(self): - return "DoH" - - def is_always_max_size(self) -> bool: - return True - - def __str__(self): - return self.url - - def answer_nameserver(self) -> str: - return self.url - - def answer_port(self) -> int: - port = urlparse(self.url).port - if port is None: - port = 443 - return port - - def query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - return dns.query.https( - request, - self.url, - timeout=timeout, - source=source, - source_port=source_port, - bootstrap_address=self.bootstrap_address, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - verify=self.verify, - post=(not self.want_get), - http_version=self.http_version, - ) - - async def async_query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - backend: dns.asyncbackend.Backend, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - return await dns.asyncquery.https( - request, - self.url, - timeout=timeout, - source=source, - source_port=source_port, - bootstrap_address=self.bootstrap_address, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - verify=self.verify, - post=(not self.want_get), - http_version=self.http_version, - ) - - -class DoTNameserver(AddressAndPortNameserver): - def __init__( - self, - address: str, - port: int = 853, - hostname: Optional[str] = None, - verify: Union[bool, str] = True, - ): - super().__init__(address, port) - self.hostname = hostname - self.verify = verify - - def kind(self): - return "DoT" - - def query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - return dns.query.tls( - request, - self.address, - port=self.port, - timeout=timeout, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - server_hostname=self.hostname, - verify=self.verify, - ) - - async def async_query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - backend: dns.asyncbackend.Backend, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - return await dns.asyncquery.tls( - request, - self.address, - port=self.port, - timeout=timeout, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - server_hostname=self.hostname, - verify=self.verify, - ) - - -class DoQNameserver(AddressAndPortNameserver): - def __init__( - self, - address: str, - port: int = 853, - verify: Union[bool, str] = True, - server_hostname: Optional[str] = None, - ): - super().__init__(address, port) - self.verify = verify - self.server_hostname = server_hostname - - def kind(self): - return "DoQ" - - def query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - return dns.query.quic( - request, - self.address, - port=self.port, - timeout=timeout, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - verify=self.verify, - server_hostname=self.server_hostname, - ) - - async def async_query( - self, - request: dns.message.QueryMessage, - timeout: float, - source: Optional[str], - source_port: int, - max_size: bool, - backend: dns.asyncbackend.Backend, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - ) -> dns.message.Message: - return await dns.asyncquery.quic( - request, - self.address, - port=self.port, - timeout=timeout, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - verify=self.verify, - server_hostname=self.server_hostname, - ) diff --git a/venv/Lib/site-packages/dns/node.py b/venv/Lib/site-packages/dns/node.py deleted file mode 100644 index de85a82..0000000 --- a/venv/Lib/site-packages/dns/node.py +++ /dev/null @@ -1,359 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS nodes. A node is a set of rdatasets.""" - -import enum -import io -from typing import Any, Dict, Optional - -import dns.immutable -import dns.name -import dns.rdataclass -import dns.rdataset -import dns.rdatatype -import dns.renderer -import dns.rrset - -_cname_types = { - dns.rdatatype.CNAME, -} - -# "neutral" types can coexist with a CNAME and thus are not "other data" -_neutral_types = { - dns.rdatatype.NSEC, # RFC 4035 section 2.5 - dns.rdatatype.NSEC3, # This is not likely to happen, but not impossible! - dns.rdatatype.KEY, # RFC 4035 section 2.5, RFC 3007 -} - - -def _matches_type_or_its_signature(rdtypes, rdtype, covers): - return rdtype in rdtypes or (rdtype == dns.rdatatype.RRSIG and covers in rdtypes) - - -@enum.unique -class NodeKind(enum.Enum): - """Rdatasets in nodes""" - - REGULAR = 0 # a.k.a "other data" - NEUTRAL = 1 - CNAME = 2 - - @classmethod - def classify( - cls, rdtype: dns.rdatatype.RdataType, covers: dns.rdatatype.RdataType - ) -> "NodeKind": - if _matches_type_or_its_signature(_cname_types, rdtype, covers): - return NodeKind.CNAME - elif _matches_type_or_its_signature(_neutral_types, rdtype, covers): - return NodeKind.NEUTRAL - else: - return NodeKind.REGULAR - - @classmethod - def classify_rdataset(cls, rdataset: dns.rdataset.Rdataset) -> "NodeKind": - return cls.classify(rdataset.rdtype, rdataset.covers) - - -class Node: - """A Node is a set of rdatasets. - - A node is either a CNAME node or an "other data" node. A CNAME - node contains only CNAME, KEY, NSEC, and NSEC3 rdatasets along with their - covering RRSIG rdatasets. An "other data" node contains any - rdataset other than a CNAME or RRSIG(CNAME) rdataset. When - changes are made to a node, the CNAME or "other data" state is - always consistent with the update, i.e. the most recent change - wins. For example, if you have a node which contains a CNAME - rdataset, and then add an MX rdataset to it, then the CNAME - rdataset will be deleted. Likewise if you have a node containing - an MX rdataset and add a CNAME rdataset, the MX rdataset will be - deleted. - """ - - __slots__ = ["rdatasets"] - - def __init__(self): - # the set of rdatasets, represented as a list. - self.rdatasets = [] - - def to_text(self, name: dns.name.Name, **kw: Dict[str, Any]) -> str: - """Convert a node to text format. - - Each rdataset at the node is printed. Any keyword arguments - to this method are passed on to the rdataset's to_text() method. - - *name*, a ``dns.name.Name``, the owner name of the - rdatasets. - - Returns a ``str``. - - """ - - s = io.StringIO() - for rds in self.rdatasets: - if len(rds) > 0: - s.write(rds.to_text(name, **kw)) # type: ignore[arg-type] - s.write("\n") - return s.getvalue()[:-1] - - def __repr__(self): - return "" - - def __eq__(self, other): - # - # This is inefficient. Good thing we don't need to do it much. - # - for rd in self.rdatasets: - if rd not in other.rdatasets: - return False - for rd in other.rdatasets: - if rd not in self.rdatasets: - return False - return True - - def __ne__(self, other): - return not self.__eq__(other) - - def __len__(self): - return len(self.rdatasets) - - def __iter__(self): - return iter(self.rdatasets) - - def _append_rdataset(self, rdataset): - """Append rdataset to the node with special handling for CNAME and - other data conditions. - - Specifically, if the rdataset being appended has ``NodeKind.CNAME``, - then all rdatasets other than KEY, NSEC, NSEC3, and their covering - RRSIGs are deleted. If the rdataset being appended has - ``NodeKind.REGULAR`` then CNAME and RRSIG(CNAME) are deleted. - """ - # Make having just one rdataset at the node fast. - if len(self.rdatasets) > 0: - kind = NodeKind.classify_rdataset(rdataset) - if kind == NodeKind.CNAME: - self.rdatasets = [ - rds - for rds in self.rdatasets - if NodeKind.classify_rdataset(rds) != NodeKind.REGULAR - ] - elif kind == NodeKind.REGULAR: - self.rdatasets = [ - rds - for rds in self.rdatasets - if NodeKind.classify_rdataset(rds) != NodeKind.CNAME - ] - # Otherwise the rdataset is NodeKind.NEUTRAL and we do not need to - # edit self.rdatasets. - self.rdatasets.append(rdataset) - - def find_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - create: bool = False, - ) -> dns.rdataset.Rdataset: - """Find an rdataset matching the specified properties in the - current node. - - *rdclass*, a ``dns.rdataclass.RdataClass``, the class of the rdataset. - - *rdtype*, a ``dns.rdatatype.RdataType``, the type of the rdataset. - - *covers*, a ``dns.rdatatype.RdataType``, the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - - *create*, a ``bool``. If True, create the rdataset if it is not found. - - Raises ``KeyError`` if an rdataset of the desired type and class does - not exist and *create* is not ``True``. - - Returns a ``dns.rdataset.Rdataset``. - """ - - for rds in self.rdatasets: - if rds.match(rdclass, rdtype, covers): - return rds - if not create: - raise KeyError - rds = dns.rdataset.Rdataset(rdclass, rdtype, covers) - self._append_rdataset(rds) - return rds - - def get_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - create: bool = False, - ) -> Optional[dns.rdataset.Rdataset]: - """Get an rdataset matching the specified properties in the - current node. - - None is returned if an rdataset of the specified type and - class does not exist and *create* is not ``True``. - - *rdclass*, an ``int``, the class of the rdataset. - - *rdtype*, an ``int``, the type of the rdataset. - - *covers*, an ``int``, the covered type. Usually this value is - dns.rdatatype.NONE, but if the rdtype is dns.rdatatype.SIG or - dns.rdatatype.RRSIG, then the covers value will be the rdata - type the SIG/RRSIG covers. The library treats the SIG and RRSIG - types as if they were a family of - types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This makes RRSIGs much - easier to work with than if RRSIGs covering different rdata - types were aggregated into a single RRSIG rdataset. - - *create*, a ``bool``. If True, create the rdataset if it is not found. - - Returns a ``dns.rdataset.Rdataset`` or ``None``. - """ - - try: - rds = self.find_rdataset(rdclass, rdtype, covers, create) - except KeyError: - rds = None - return rds - - def delete_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - ) -> None: - """Delete the rdataset matching the specified properties in the - current node. - - If a matching rdataset does not exist, it is not an error. - - *rdclass*, an ``int``, the class of the rdataset. - - *rdtype*, an ``int``, the type of the rdataset. - - *covers*, an ``int``, the covered type. - """ - - rds = self.get_rdataset(rdclass, rdtype, covers) - if rds is not None: - self.rdatasets.remove(rds) - - def replace_rdataset(self, replacement: dns.rdataset.Rdataset) -> None: - """Replace an rdataset. - - It is not an error if there is no rdataset matching *replacement*. - - Ownership of the *replacement* object is transferred to the node; - in other words, this method does not store a copy of *replacement* - at the node, it stores *replacement* itself. - - *replacement*, a ``dns.rdataset.Rdataset``. - - Raises ``ValueError`` if *replacement* is not a - ``dns.rdataset.Rdataset``. - """ - - if not isinstance(replacement, dns.rdataset.Rdataset): - raise ValueError("replacement is not an rdataset") - if isinstance(replacement, dns.rrset.RRset): - # RRsets are not good replacements as the match() method - # is not compatible. - replacement = replacement.to_rdataset() - self.delete_rdataset( - replacement.rdclass, replacement.rdtype, replacement.covers - ) - self._append_rdataset(replacement) - - def classify(self) -> NodeKind: - """Classify a node. - - A node which contains a CNAME or RRSIG(CNAME) is a - ``NodeKind.CNAME`` node. - - A node which contains only "neutral" types, i.e. types allowed to - co-exist with a CNAME, is a ``NodeKind.NEUTRAL`` node. The neutral - types are NSEC, NSEC3, KEY, and their associated RRSIGS. An empty node - is also considered neutral. - - A node which contains some rdataset which is not a CNAME, RRSIG(CNAME), - or a neutral type is a a ``NodeKind.REGULAR`` node. Regular nodes are - also commonly referred to as "other data". - """ - for rdataset in self.rdatasets: - kind = NodeKind.classify(rdataset.rdtype, rdataset.covers) - if kind != NodeKind.NEUTRAL: - return kind - return NodeKind.NEUTRAL - - def is_immutable(self) -> bool: - return False - - -@dns.immutable.immutable -class ImmutableNode(Node): - def __init__(self, node): - super().__init__() - self.rdatasets = tuple( - [dns.rdataset.ImmutableRdataset(rds) for rds in node.rdatasets] - ) - - def find_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - create: bool = False, - ) -> dns.rdataset.Rdataset: - if create: - raise TypeError("immutable") - return super().find_rdataset(rdclass, rdtype, covers, False) - - def get_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - create: bool = False, - ) -> Optional[dns.rdataset.Rdataset]: - if create: - raise TypeError("immutable") - return super().get_rdataset(rdclass, rdtype, covers, False) - - def delete_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - ) -> None: - raise TypeError("immutable") - - def replace_rdataset(self, replacement: dns.rdataset.Rdataset) -> None: - raise TypeError("immutable") - - def is_immutable(self) -> bool: - return True diff --git a/venv/Lib/site-packages/dns/opcode.py b/venv/Lib/site-packages/dns/opcode.py deleted file mode 100644 index 78b43d2..0000000 --- a/venv/Lib/site-packages/dns/opcode.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Opcodes.""" - -import dns.enum -import dns.exception - - -class Opcode(dns.enum.IntEnum): - #: Query - QUERY = 0 - #: Inverse Query (historical) - IQUERY = 1 - #: Server Status (unspecified and unimplemented anywhere) - STATUS = 2 - #: Notify - NOTIFY = 4 - #: Dynamic Update - UPDATE = 5 - - @classmethod - def _maximum(cls): - return 15 - - @classmethod - def _unknown_exception_class(cls): - return UnknownOpcode - - -class UnknownOpcode(dns.exception.DNSException): - """An DNS opcode is unknown.""" - - -def from_text(text: str) -> Opcode: - """Convert text into an opcode. - - *text*, a ``str``, the textual opcode - - Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. - - Returns an ``int``. - """ - - return Opcode.from_text(text) - - -def from_flags(flags: int) -> Opcode: - """Extract an opcode from DNS message flags. - - *flags*, an ``int``, the DNS flags. - - Returns an ``int``. - """ - - return Opcode((flags & 0x7800) >> 11) - - -def to_flags(value: Opcode) -> int: - """Convert an opcode to a value suitable for ORing into DNS message - flags. - - *value*, an ``int``, the DNS opcode value. - - Returns an ``int``. - """ - - return (value << 11) & 0x7800 - - -def to_text(value: Opcode) -> str: - """Convert an opcode to text. - - *value*, an ``int`` the opcode value, - - Raises ``dns.opcode.UnknownOpcode`` if the opcode is unknown. - - Returns a ``str``. - """ - - return Opcode.to_text(value) - - -def is_update(flags: int) -> bool: - """Is the opcode in flags UPDATE? - - *flags*, an ``int``, the DNS message flags. - - Returns a ``bool``. - """ - - return from_flags(flags) == Opcode.UPDATE - - -### BEGIN generated Opcode constants - -QUERY = Opcode.QUERY -IQUERY = Opcode.IQUERY -STATUS = Opcode.STATUS -NOTIFY = Opcode.NOTIFY -UPDATE = Opcode.UPDATE - -### END generated Opcode constants diff --git a/venv/Lib/site-packages/dns/py.typed b/venv/Lib/site-packages/dns/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/Lib/site-packages/dns/query.py b/venv/Lib/site-packages/dns/query.py deleted file mode 100644 index 0d8a977..0000000 --- a/venv/Lib/site-packages/dns/query.py +++ /dev/null @@ -1,1665 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Talk to a DNS server.""" - -import base64 -import contextlib -import enum -import errno -import os -import os.path -import random -import selectors -import socket -import struct -import time -import urllib.parse -from typing import Any, Dict, Optional, Tuple, Union, cast - -import dns._features -import dns.exception -import dns.inet -import dns.message -import dns.name -import dns.quic -import dns.rcode -import dns.rdataclass -import dns.rdatatype -import dns.serial -import dns.transaction -import dns.tsig -import dns.xfr - - -def _remaining(expiration): - if expiration is None: - return None - timeout = expiration - time.time() - if timeout <= 0.0: - raise dns.exception.Timeout - return timeout - - -def _expiration_for_this_attempt(timeout, expiration): - if expiration is None: - return None - return min(time.time() + timeout, expiration) - - -_have_httpx = dns._features.have("doh") -if _have_httpx: - import httpcore._backends.sync - import httpx - - _CoreNetworkBackend = httpcore.NetworkBackend - _CoreSyncStream = httpcore._backends.sync.SyncStream - - class _NetworkBackend(_CoreNetworkBackend): - def __init__(self, resolver, local_port, bootstrap_address, family): - super().__init__() - self._local_port = local_port - self._resolver = resolver - self._bootstrap_address = bootstrap_address - self._family = family - - def connect_tcp( - self, host, port, timeout, local_address, socket_options=None - ): # pylint: disable=signature-differs - addresses = [] - _, expiration = _compute_times(timeout) - if dns.inet.is_address(host): - addresses.append(host) - elif self._bootstrap_address is not None: - addresses.append(self._bootstrap_address) - else: - timeout = _remaining(expiration) - family = self._family - if local_address: - family = dns.inet.af_for_address(local_address) - answers = self._resolver.resolve_name( - host, family=family, lifetime=timeout - ) - addresses = answers.addresses() - for address in addresses: - af = dns.inet.af_for_address(address) - if local_address is not None or self._local_port != 0: - source = dns.inet.low_level_address_tuple( - (local_address, self._local_port), af - ) - else: - source = None - sock = _make_socket(af, socket.SOCK_STREAM, source) - attempt_expiration = _expiration_for_this_attempt(2.0, expiration) - try: - _connect( - sock, - dns.inet.low_level_address_tuple((address, port), af), - attempt_expiration, - ) - return _CoreSyncStream(sock) - except Exception: - pass - raise httpcore.ConnectError - - def connect_unix_socket( - self, path, timeout, socket_options=None - ): # pylint: disable=signature-differs - raise NotImplementedError - - class _HTTPTransport(httpx.HTTPTransport): - def __init__( - self, - *args, - local_port=0, - bootstrap_address=None, - resolver=None, - family=socket.AF_UNSPEC, - **kwargs, - ): - if resolver is None and bootstrap_address is None: - # pylint: disable=import-outside-toplevel,redefined-outer-name - import dns.resolver - - resolver = dns.resolver.Resolver() - super().__init__(*args, **kwargs) - self._pool._network_backend = _NetworkBackend( - resolver, local_port, bootstrap_address, family - ) - -else: - - class _HTTPTransport: # type: ignore - def connect_tcp(self, host, port, timeout, local_address): - raise NotImplementedError - - -have_doh = _have_httpx - -try: - import ssl -except ImportError: # pragma: no cover - - class ssl: # type: ignore - CERT_NONE = 0 - - class WantReadException(Exception): - pass - - class WantWriteException(Exception): - pass - - class SSLContext: - pass - - class SSLSocket: - pass - - @classmethod - def create_default_context(cls, *args, **kwargs): - raise Exception("no ssl support") # pylint: disable=broad-exception-raised - - -# Function used to create a socket. Can be overridden if needed in special -# situations. -socket_factory = socket.socket - - -class UnexpectedSource(dns.exception.DNSException): - """A DNS query response came from an unexpected address or port.""" - - -class BadResponse(dns.exception.FormError): - """A DNS query response does not respond to the question asked.""" - - -class NoDOH(dns.exception.DNSException): - """DNS over HTTPS (DOH) was requested but the httpx module is not - available.""" - - -class NoDOQ(dns.exception.DNSException): - """DNS over QUIC (DOQ) was requested but the aioquic module is not - available.""" - - -# for backwards compatibility -TransferError = dns.xfr.TransferError - - -def _compute_times(timeout): - now = time.time() - if timeout is None: - return (now, None) - else: - return (now, now + timeout) - - -def _wait_for(fd, readable, writable, _, expiration): - # Use the selected selector class to wait for any of the specified - # events. An "expiration" absolute time is converted into a relative - # timeout. - # - # The unused parameter is 'error', which is always set when - # selecting for read or write, and we have no error-only selects. - - if readable and isinstance(fd, ssl.SSLSocket) and fd.pending() > 0: - return True - sel = selectors.DefaultSelector() - events = 0 - if readable: - events |= selectors.EVENT_READ - if writable: - events |= selectors.EVENT_WRITE - if events: - sel.register(fd, events) - if expiration is None: - timeout = None - else: - timeout = expiration - time.time() - if timeout <= 0.0: - raise dns.exception.Timeout - if not sel.select(timeout): - raise dns.exception.Timeout - - -def _wait_for_readable(s, expiration): - _wait_for(s, True, False, True, expiration) - - -def _wait_for_writable(s, expiration): - _wait_for(s, False, True, True, expiration) - - -def _addresses_equal(af, a1, a2): - # Convert the first value of the tuple, which is a textual format - # address into binary form, so that we are not confused by different - # textual representations of the same address - try: - n1 = dns.inet.inet_pton(af, a1[0]) - n2 = dns.inet.inet_pton(af, a2[0]) - except dns.exception.SyntaxError: - return False - return n1 == n2 and a1[1:] == a2[1:] - - -def _matches_destination(af, from_address, destination, ignore_unexpected): - # Check that from_address is appropriate for a response to a query - # sent to destination. - if not destination: - return True - if _addresses_equal(af, from_address, destination) or ( - dns.inet.is_multicast(destination[0]) and from_address[1:] == destination[1:] - ): - return True - elif ignore_unexpected: - return False - raise UnexpectedSource( - f"got a response from {from_address} instead of " f"{destination}" - ) - - -def _destination_and_source( - where, port, source, source_port, where_must_be_address=True -): - # Apply defaults and compute destination and source tuples - # suitable for use in connect(), sendto(), or bind(). - af = None - destination = None - try: - af = dns.inet.af_for_address(where) - destination = where - except Exception: - if where_must_be_address: - raise - # URLs are ok so eat the exception - if source: - saf = dns.inet.af_for_address(source) - if af: - # We know the destination af, so source had better agree! - if saf != af: - raise ValueError( - "different address families for source and destination" - ) - else: - # We didn't know the destination af, but we know the source, - # so that's our af. - af = saf - if source_port and not source: - # Caller has specified a source_port but not an address, so we - # need to return a source, and we need to use the appropriate - # wildcard address as the address. - try: - source = dns.inet.any_for_af(af) - except Exception: - # we catch this and raise ValueError for backwards compatibility - raise ValueError("source_port specified but address family is unknown") - # Convert high-level (address, port) tuples into low-level address - # tuples. - if destination: - destination = dns.inet.low_level_address_tuple((destination, port), af) - if source: - source = dns.inet.low_level_address_tuple((source, source_port), af) - return (af, destination, source) - - -def _make_socket(af, type, source, ssl_context=None, server_hostname=None): - s = socket_factory(af, type) - try: - s.setblocking(False) - if source is not None: - s.bind(source) - if ssl_context: - # LGTM gets a false positive here, as our default context is OK - return ssl_context.wrap_socket( - s, - do_handshake_on_connect=False, # lgtm[py/insecure-protocol] - server_hostname=server_hostname, - ) - else: - return s - except Exception: - s.close() - raise - - -def _maybe_get_resolver( - resolver: Optional["dns.resolver.Resolver"], -) -> "dns.resolver.Resolver": - # We need a separate method for this to avoid overriding the global - # variable "dns" with the as-yet undefined local variable "dns" - # in https(). - if resolver is None: - # pylint: disable=import-outside-toplevel,redefined-outer-name - import dns.resolver - - resolver = dns.resolver.Resolver() - return resolver - - -class HTTPVersion(enum.IntEnum): - """Which version of HTTP should be used? - - DEFAULT will select the first version from the list [2, 1.1, 3] that - is available. - """ - - DEFAULT = 0 - HTTP_1 = 1 - H1 = 1 - HTTP_2 = 2 - H2 = 2 - HTTP_3 = 3 - H3 = 3 - - -def https( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 443, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - session: Optional[Any] = None, - path: str = "/dns-query", - post: bool = True, - bootstrap_address: Optional[str] = None, - verify: Union[bool, str] = True, - resolver: Optional["dns.resolver.Resolver"] = None, - family: int = socket.AF_UNSPEC, - http_version: HTTPVersion = HTTPVersion.DEFAULT, -) -> dns.message.Message: - """Return the response obtained after sending a query via DNS-over-HTTPS. - - *q*, a ``dns.message.Message``, the query to send. - - *where*, a ``str``, the nameserver IP address or the full URL. If an IP address is - given, the URL will be constructed using the following schema: - https://:/. - - *timeout*, a ``float`` or ``None``, the number of seconds to wait before the query - times out. If ``None``, the default, wait forever. - - *port*, a ``int``, the port to send the query to. The default is 443. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying the source - address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. The default is - 0. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the - received message. - - *session*, an ``httpx.Client``. If provided, the client session to use to send the - queries. - - *path*, a ``str``. If *where* is an IP address, then *path* will be used to - construct the URL to send the DNS query to. - - *post*, a ``bool``. If ``True``, the default, POST method will be used. - - *bootstrap_address*, a ``str``, the IP address to use to bypass resolution. - - *verify*, a ``bool`` or ``str``. If a ``True``, then TLS certificate verification - of the server is done using the default CA bundle; if ``False``, then no - verification is done; if a `str` then it specifies the path to a certificate file or - directory which will be used for verification. - - *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use for - resolution of hostnames in URLs. If not specified, a new resolver with a default - configuration will be used; note this is *not* the default resolver as that resolver - might have been configured to use DoH causing a chicken-and-egg problem. This - parameter only has an effect if the HTTP library is httpx. - - *family*, an ``int``, the address family. If socket.AF_UNSPEC (the default), both A - and AAAA records will be retrieved. - - *http_version*, a ``dns.query.HTTPVersion``, indicating which HTTP version to use. - - Returns a ``dns.message.Message``. - """ - - (af, _, the_source) = _destination_and_source( - where, port, source, source_port, False - ) - if af is not None and dns.inet.is_address(where): - if af == socket.AF_INET: - url = f"https://{where}:{port}{path}" - elif af == socket.AF_INET6: - url = f"https://[{where}]:{port}{path}" - else: - url = where - - extensions = {} - if bootstrap_address is None: - # pylint: disable=possibly-used-before-assignment - parsed = urllib.parse.urlparse(url) - if parsed.hostname is None: - raise ValueError("no hostname in URL") - if dns.inet.is_address(parsed.hostname): - bootstrap_address = parsed.hostname - extensions["sni_hostname"] = parsed.hostname - if parsed.port is not None: - port = parsed.port - - if http_version == HTTPVersion.H3 or ( - http_version == HTTPVersion.DEFAULT and not have_doh - ): - if bootstrap_address is None: - resolver = _maybe_get_resolver(resolver) - assert parsed.hostname is not None # for mypy - answers = resolver.resolve_name(parsed.hostname, family) - bootstrap_address = random.choice(list(answers.addresses())) - return _http3( - q, - bootstrap_address, - url, - timeout, - port, - source, - source_port, - one_rr_per_rrset, - ignore_trailing, - verify=verify, - post=post, - ) - - if not have_doh: - raise NoDOH # pragma: no cover - if session and not isinstance(session, httpx.Client): - raise ValueError("session parameter must be an httpx.Client") - - wire = q.to_wire() - headers = {"accept": "application/dns-message"} - - h1 = http_version in (HTTPVersion.H1, HTTPVersion.DEFAULT) - h2 = http_version in (HTTPVersion.H2, HTTPVersion.DEFAULT) - - # set source port and source address - - if the_source is None: - local_address = None - local_port = 0 - else: - local_address = the_source[0] - local_port = the_source[1] - - if session: - cm: contextlib.AbstractContextManager = contextlib.nullcontext(session) - else: - transport = _HTTPTransport( - local_address=local_address, - http1=h1, - http2=h2, - verify=verify, - local_port=local_port, - bootstrap_address=bootstrap_address, - resolver=resolver, - family=family, - ) - - cm = httpx.Client(http1=h1, http2=h2, verify=verify, transport=transport) - with cm as session: - # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH - # GET and POST examples - if post: - headers.update( - { - "content-type": "application/dns-message", - "content-length": str(len(wire)), - } - ) - response = session.post( - url, - headers=headers, - content=wire, - timeout=timeout, - extensions=extensions, - ) - else: - wire = base64.urlsafe_b64encode(wire).rstrip(b"=") - twire = wire.decode() # httpx does a repr() if we give it bytes - response = session.get( - url, - headers=headers, - timeout=timeout, - params={"dns": twire}, - extensions=extensions, - ) - - # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH - # status codes - if response.status_code < 200 or response.status_code > 299: - raise ValueError( - f"{where} responded with status code {response.status_code}" - f"\nResponse body: {response.content}" - ) - r = dns.message.from_wire( - response.content, - keyring=q.keyring, - request_mac=q.request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - r.time = response.elapsed.total_seconds() - if not q.is_response(r): - raise BadResponse - return r - - -def _find_header(headers: dns.quic.Headers, name: bytes) -> bytes: - if headers is None: - raise KeyError - for header, value in headers: - if header == name: - return value - raise KeyError - - -def _check_status(headers: dns.quic.Headers, peer: str, wire: bytes) -> None: - value = _find_header(headers, b":status") - if value is None: - raise SyntaxError("no :status header in response") - status = int(value) - if status < 0: - raise SyntaxError("status is negative") - if status < 200 or status > 299: - error = "" - if len(wire) > 0: - try: - error = ": " + wire.decode() - except Exception: - pass - raise ValueError(f"{peer} responded with status code {status}{error}") - - -def _http3( - q: dns.message.Message, - where: str, - url: str, - timeout: Optional[float] = None, - port: int = 853, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - verify: Union[bool, str] = True, - hostname: Optional[str] = None, - post: bool = True, -) -> dns.message.Message: - if not dns.quic.have_quic: - raise NoDOH("DNS-over-HTTP3 is not available.") # pragma: no cover - - url_parts = urllib.parse.urlparse(url) - hostname = url_parts.hostname - if url_parts.port is not None: - port = url_parts.port - - q.id = 0 - wire = q.to_wire() - manager = dns.quic.SyncQuicManager( - verify_mode=verify, server_name=hostname, h3=True - ) - - with manager: - connection = manager.connect(where, port, source, source_port) - (start, expiration) = _compute_times(timeout) - with connection.make_stream(timeout) as stream: - stream.send_h3(url, wire, post) - wire = stream.receive(_remaining(expiration)) - _check_status(stream.headers(), where, wire) - finish = time.time() - r = dns.message.from_wire( - wire, - keyring=q.keyring, - request_mac=q.request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - r.time = max(finish - start, 0.0) - if not q.is_response(r): - raise BadResponse - return r - - -def _udp_recv(sock, max_size, expiration): - """Reads a datagram from the socket. - A Timeout exception will be raised if the operation is not completed - by the expiration time. - """ - while True: - try: - return sock.recvfrom(max_size) - except BlockingIOError: - _wait_for_readable(sock, expiration) - - -def _udp_send(sock, data, destination, expiration): - """Sends the specified datagram to destination over the socket. - A Timeout exception will be raised if the operation is not completed - by the expiration time. - """ - while True: - try: - if destination: - return sock.sendto(data, destination) - else: - return sock.send(data) - except BlockingIOError: # pragma: no cover - _wait_for_writable(sock, expiration) - - -def send_udp( - sock: Any, - what: Union[dns.message.Message, bytes], - destination: Any, - expiration: Optional[float] = None, -) -> Tuple[int, float]: - """Send a DNS message to the specified UDP socket. - - *sock*, a ``socket``. - - *what*, a ``bytes`` or ``dns.message.Message``, the message to send. - - *destination*, a destination tuple appropriate for the address family - of the socket, specifying where to send the query. - - *expiration*, a ``float`` or ``None``, the absolute time at which - a timeout exception should be raised. If ``None``, no timeout will - occur. - - Returns an ``(int, float)`` tuple of bytes sent and the sent time. - """ - - if isinstance(what, dns.message.Message): - what = what.to_wire() - sent_time = time.time() - n = _udp_send(sock, what, destination, expiration) - return (n, sent_time) - - -def receive_udp( - sock: Any, - destination: Optional[Any] = None, - expiration: Optional[float] = None, - ignore_unexpected: bool = False, - one_rr_per_rrset: bool = False, - keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None, - request_mac: Optional[bytes] = b"", - ignore_trailing: bool = False, - raise_on_truncation: bool = False, - ignore_errors: bool = False, - query: Optional[dns.message.Message] = None, -) -> Any: - """Read a DNS message from a UDP socket. - - *sock*, a ``socket``. - - *destination*, a destination tuple appropriate for the address family - of the socket, specifying where the message is expected to arrive from. - When receiving a response, this would be where the associated query was - sent. - - *expiration*, a ``float`` or ``None``, the absolute time at which - a timeout exception should be raised. If ``None``, no timeout will - occur. - - *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from - unexpected sources. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own - RRset. - - *keyring*, a ``dict``, the keyring to use for TSIG. - - *request_mac*, a ``bytes`` or ``None``, the MAC of the request (for TSIG). - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing - junk at end of the received message. - - *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if - the TC bit is set. - - Raises if the message is malformed, if network errors occur, of if - there is a timeout. - - If *destination* is not ``None``, returns a ``(dns.message.Message, float)`` - tuple of the received message and the received time. - - If *destination* is ``None``, returns a - ``(dns.message.Message, float, tuple)`` - tuple of the received message, the received time, and the address where - the message arrived from. - - *ignore_errors*, a ``bool``. If various format errors or response - mismatches occur, ignore them and keep listening for a valid response. - The default is ``False``. - - *query*, a ``dns.message.Message`` or ``None``. If not ``None`` and - *ignore_errors* is ``True``, check that the received message is a response - to this query, and if not keep listening for a valid response. - """ - - wire = b"" - while True: - (wire, from_address) = _udp_recv(sock, 65535, expiration) - if not _matches_destination( - sock.family, from_address, destination, ignore_unexpected - ): - continue - received_time = time.time() - try: - r = dns.message.from_wire( - wire, - keyring=keyring, - request_mac=request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - raise_on_truncation=raise_on_truncation, - ) - except dns.message.Truncated as e: - # If we got Truncated and not FORMERR, we at least got the header with TC - # set, and very likely the question section, so we'll re-raise if the - # message seems to be a response as we need to know when truncation happens. - # We need to check that it seems to be a response as we don't want a random - # injected message with TC set to cause us to bail out. - if ( - ignore_errors - and query is not None - and not query.is_response(e.message()) - ): - continue - else: - raise - except Exception: - if ignore_errors: - continue - else: - raise - if ignore_errors and query is not None and not query.is_response(r): - continue - if destination: - return (r, received_time) - else: - return (r, received_time, from_address) - - -def udp( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 53, - source: Optional[str] = None, - source_port: int = 0, - ignore_unexpected: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - raise_on_truncation: bool = False, - sock: Optional[Any] = None, - ignore_errors: bool = False, -) -> dns.message.Message: - """Return the response obtained after sending a query via UDP. - - *q*, a ``dns.message.Message``, the query to send - - *where*, a ``str`` containing an IPv4 or IPv6 address, where - to send the message. - - *timeout*, a ``float`` or ``None``, the number of seconds to wait before the - query times out. If ``None``, the default, wait forever. - - *port*, an ``int``, the port send the message to. The default is 53. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying - the source address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. - The default is 0. - - *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from - unexpected sources. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own - RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing - junk at end of the received message. - - *raise_on_truncation*, a ``bool``. If ``True``, raise an exception if - the TC bit is set. - - *sock*, a ``socket.socket``, or ``None``, the socket to use for the - query. If ``None``, the default, a socket is created. Note that - if a socket is provided, it must be a nonblocking datagram socket, - and the *source* and *source_port* are ignored. - - *ignore_errors*, a ``bool``. If various format errors or response - mismatches occur, ignore them and keep listening for a valid response. - The default is ``False``. - - Returns a ``dns.message.Message``. - """ - - wire = q.to_wire() - (af, destination, source) = _destination_and_source( - where, port, source, source_port - ) - (begin_time, expiration) = _compute_times(timeout) - if sock: - cm: contextlib.AbstractContextManager = contextlib.nullcontext(sock) - else: - cm = _make_socket(af, socket.SOCK_DGRAM, source) - with cm as s: - send_udp(s, wire, destination, expiration) - (r, received_time) = receive_udp( - s, - destination, - expiration, - ignore_unexpected, - one_rr_per_rrset, - q.keyring, - q.mac, - ignore_trailing, - raise_on_truncation, - ignore_errors, - q, - ) - r.time = received_time - begin_time - # We don't need to check q.is_response() if we are in ignore_errors mode - # as receive_udp() will have checked it. - if not (ignore_errors or q.is_response(r)): - raise BadResponse - return r - assert ( - False # help mypy figure out we can't get here lgtm[py/unreachable-statement] - ) - - -def udp_with_fallback( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 53, - source: Optional[str] = None, - source_port: int = 0, - ignore_unexpected: bool = False, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - udp_sock: Optional[Any] = None, - tcp_sock: Optional[Any] = None, - ignore_errors: bool = False, -) -> Tuple[dns.message.Message, bool]: - """Return the response to the query, trying UDP first and falling back - to TCP if UDP results in a truncated response. - - *q*, a ``dns.message.Message``, the query to send - - *where*, a ``str`` containing an IPv4 or IPv6 address, where to send the message. - - *timeout*, a ``float`` or ``None``, the number of seconds to wait before the query - times out. If ``None``, the default, wait forever. - - *port*, an ``int``, the port send the message to. The default is 53. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying the source - address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. The default is - 0. - - *ignore_unexpected*, a ``bool``. If ``True``, ignore responses from unexpected - sources. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the - received message. - - *udp_sock*, a ``socket.socket``, or ``None``, the socket to use for the UDP query. - If ``None``, the default, a socket is created. Note that if a socket is provided, - it must be a nonblocking datagram socket, and the *source* and *source_port* are - ignored for the UDP query. - - *tcp_sock*, a ``socket.socket``, or ``None``, the connected socket to use for the - TCP query. If ``None``, the default, a socket is created. Note that if a socket is - provided, it must be a nonblocking connected stream socket, and *where*, *source* - and *source_port* are ignored for the TCP query. - - *ignore_errors*, a ``bool``. If various format errors or response mismatches occur - while listening for UDP, ignore them and keep listening for a valid response. The - default is ``False``. - - Returns a (``dns.message.Message``, tcp) tuple where tcp is ``True`` if and only if - TCP was used. - """ - try: - response = udp( - q, - where, - timeout, - port, - source, - source_port, - ignore_unexpected, - one_rr_per_rrset, - ignore_trailing, - True, - udp_sock, - ignore_errors, - ) - return (response, False) - except dns.message.Truncated: - response = tcp( - q, - where, - timeout, - port, - source, - source_port, - one_rr_per_rrset, - ignore_trailing, - tcp_sock, - ) - return (response, True) - - -def _net_read(sock, count, expiration): - """Read the specified number of bytes from sock. Keep trying until we - either get the desired amount, or we hit EOF. - A Timeout exception will be raised if the operation is not completed - by the expiration time. - """ - s = b"" - while count > 0: - try: - n = sock.recv(count) - if n == b"": - raise EOFError("EOF") - count -= len(n) - s += n - except (BlockingIOError, ssl.SSLWantReadError): - _wait_for_readable(sock, expiration) - except ssl.SSLWantWriteError: # pragma: no cover - _wait_for_writable(sock, expiration) - return s - - -def _net_write(sock, data, expiration): - """Write the specified data to the socket. - A Timeout exception will be raised if the operation is not completed - by the expiration time. - """ - current = 0 - l = len(data) - while current < l: - try: - current += sock.send(data[current:]) - except (BlockingIOError, ssl.SSLWantWriteError): - _wait_for_writable(sock, expiration) - except ssl.SSLWantReadError: # pragma: no cover - _wait_for_readable(sock, expiration) - - -def send_tcp( - sock: Any, - what: Union[dns.message.Message, bytes], - expiration: Optional[float] = None, -) -> Tuple[int, float]: - """Send a DNS message to the specified TCP socket. - - *sock*, a ``socket``. - - *what*, a ``bytes`` or ``dns.message.Message``, the message to send. - - *expiration*, a ``float`` or ``None``, the absolute time at which - a timeout exception should be raised. If ``None``, no timeout will - occur. - - Returns an ``(int, float)`` tuple of bytes sent and the sent time. - """ - - if isinstance(what, dns.message.Message): - tcpmsg = what.to_wire(prepend_length=True) - else: - # copying the wire into tcpmsg is inefficient, but lets us - # avoid writev() or doing a short write that would get pushed - # onto the net - tcpmsg = len(what).to_bytes(2, "big") + what - sent_time = time.time() - _net_write(sock, tcpmsg, expiration) - return (len(tcpmsg), sent_time) - - -def receive_tcp( - sock: Any, - expiration: Optional[float] = None, - one_rr_per_rrset: bool = False, - keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None, - request_mac: Optional[bytes] = b"", - ignore_trailing: bool = False, -) -> Tuple[dns.message.Message, float]: - """Read a DNS message from a TCP socket. - - *sock*, a ``socket``. - - *expiration*, a ``float`` or ``None``, the absolute time at which - a timeout exception should be raised. If ``None``, no timeout will - occur. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own - RRset. - - *keyring*, a ``dict``, the keyring to use for TSIG. - - *request_mac*, a ``bytes`` or ``None``, the MAC of the request (for TSIG). - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing - junk at end of the received message. - - Raises if the message is malformed, if network errors occur, of if - there is a timeout. - - Returns a ``(dns.message.Message, float)`` tuple of the received message - and the received time. - """ - - ldata = _net_read(sock, 2, expiration) - (l,) = struct.unpack("!H", ldata) - wire = _net_read(sock, l, expiration) - received_time = time.time() - r = dns.message.from_wire( - wire, - keyring=keyring, - request_mac=request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - return (r, received_time) - - -def _connect(s, address, expiration): - err = s.connect_ex(address) - if err == 0: - return - if err in (errno.EINPROGRESS, errno.EWOULDBLOCK, errno.EALREADY): - _wait_for_writable(s, expiration) - err = s.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR) - if err != 0: - raise OSError(err, os.strerror(err)) - - -def tcp( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 53, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - sock: Optional[Any] = None, -) -> dns.message.Message: - """Return the response obtained after sending a query via TCP. - - *q*, a ``dns.message.Message``, the query to send - - *where*, a ``str`` containing an IPv4 or IPv6 address, where - to send the message. - - *timeout*, a ``float`` or ``None``, the number of seconds to wait before the - query times out. If ``None``, the default, wait forever. - - *port*, an ``int``, the port send the message to. The default is 53. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying - the source address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. - The default is 0. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own - RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing - junk at end of the received message. - - *sock*, a ``socket.socket``, or ``None``, the connected socket to use for the - query. If ``None``, the default, a socket is created. Note that - if a socket is provided, it must be a nonblocking connected stream - socket, and *where*, *port*, *source* and *source_port* are ignored. - - Returns a ``dns.message.Message``. - """ - - wire = q.to_wire() - (begin_time, expiration) = _compute_times(timeout) - if sock: - cm: contextlib.AbstractContextManager = contextlib.nullcontext(sock) - else: - (af, destination, source) = _destination_and_source( - where, port, source, source_port - ) - cm = _make_socket(af, socket.SOCK_STREAM, source) - with cm as s: - if not sock: - # pylint: disable=possibly-used-before-assignment - _connect(s, destination, expiration) - send_tcp(s, wire, expiration) - (r, received_time) = receive_tcp( - s, expiration, one_rr_per_rrset, q.keyring, q.mac, ignore_trailing - ) - r.time = received_time - begin_time - if not q.is_response(r): - raise BadResponse - return r - assert ( - False # help mypy figure out we can't get here lgtm[py/unreachable-statement] - ) - - -def _tls_handshake(s, expiration): - while True: - try: - s.do_handshake() - return - except ssl.SSLWantReadError: - _wait_for_readable(s, expiration) - except ssl.SSLWantWriteError: # pragma: no cover - _wait_for_writable(s, expiration) - - -def _make_dot_ssl_context( - server_hostname: Optional[str], verify: Union[bool, str] -) -> ssl.SSLContext: - cafile: Optional[str] = None - capath: Optional[str] = None - if isinstance(verify, str): - if os.path.isfile(verify): - cafile = verify - elif os.path.isdir(verify): - capath = verify - else: - raise ValueError("invalid verify string") - ssl_context = ssl.create_default_context(cafile=cafile, capath=capath) - ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2 - if server_hostname is None: - ssl_context.check_hostname = False - ssl_context.set_alpn_protocols(["dot"]) - if verify is False: - ssl_context.verify_mode = ssl.CERT_NONE - return ssl_context - - -def tls( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 853, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - sock: Optional[ssl.SSLSocket] = None, - ssl_context: Optional[ssl.SSLContext] = None, - server_hostname: Optional[str] = None, - verify: Union[bool, str] = True, -) -> dns.message.Message: - """Return the response obtained after sending a query via TLS. - - *q*, a ``dns.message.Message``, the query to send - - *where*, a ``str`` containing an IPv4 or IPv6 address, where - to send the message. - - *timeout*, a ``float`` or ``None``, the number of seconds to wait before the - query times out. If ``None``, the default, wait forever. - - *port*, an ``int``, the port send the message to. The default is 853. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying - the source address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. - The default is 0. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own - RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing - junk at end of the received message. - - *sock*, an ``ssl.SSLSocket``, or ``None``, the socket to use for - the query. If ``None``, the default, a socket is created. Note - that if a socket is provided, it must be a nonblocking connected - SSL stream socket, and *where*, *port*, *source*, *source_port*, - and *ssl_context* are ignored. - - *ssl_context*, an ``ssl.SSLContext``, the context to use when establishing - a TLS connection. If ``None``, the default, creates one with the default - configuration. - - *server_hostname*, a ``str`` containing the server's hostname. The - default is ``None``, which means that no hostname is known, and if an - SSL context is created, hostname checking will be disabled. - - *verify*, a ``bool`` or ``str``. If a ``True``, then TLS certificate verification - of the server is done using the default CA bundle; if ``False``, then no - verification is done; if a `str` then it specifies the path to a certificate file or - directory which will be used for verification. - - Returns a ``dns.message.Message``. - - """ - - if sock: - # - # If a socket was provided, there's no special TLS handling needed. - # - return tcp( - q, - where, - timeout, - port, - source, - source_port, - one_rr_per_rrset, - ignore_trailing, - sock, - ) - - wire = q.to_wire() - (begin_time, expiration) = _compute_times(timeout) - (af, destination, source) = _destination_and_source( - where, port, source, source_port - ) - if ssl_context is None and not sock: - ssl_context = _make_dot_ssl_context(server_hostname, verify) - - with _make_socket( - af, - socket.SOCK_STREAM, - source, - ssl_context=ssl_context, - server_hostname=server_hostname, - ) as s: - _connect(s, destination, expiration) - _tls_handshake(s, expiration) - send_tcp(s, wire, expiration) - (r, received_time) = receive_tcp( - s, expiration, one_rr_per_rrset, q.keyring, q.mac, ignore_trailing - ) - r.time = received_time - begin_time - if not q.is_response(r): - raise BadResponse - return r - assert ( - False # help mypy figure out we can't get here lgtm[py/unreachable-statement] - ) - - -def quic( - q: dns.message.Message, - where: str, - timeout: Optional[float] = None, - port: int = 853, - source: Optional[str] = None, - source_port: int = 0, - one_rr_per_rrset: bool = False, - ignore_trailing: bool = False, - connection: Optional[dns.quic.SyncQuicConnection] = None, - verify: Union[bool, str] = True, - hostname: Optional[str] = None, - server_hostname: Optional[str] = None, -) -> dns.message.Message: - """Return the response obtained after sending a query via DNS-over-QUIC. - - *q*, a ``dns.message.Message``, the query to send. - - *where*, a ``str``, the nameserver IP address. - - *timeout*, a ``float`` or ``None``, the number of seconds to wait before the query - times out. If ``None``, the default, wait forever. - - *port*, a ``int``, the port to send the query to. The default is 853. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying the source - address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. The default is - 0. - - *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own RRset. - - *ignore_trailing*, a ``bool``. If ``True``, ignore trailing junk at end of the - received message. - - *connection*, a ``dns.quic.SyncQuicConnection``. If provided, the connection to use - to send the query. - - *verify*, a ``bool`` or ``str``. If a ``True``, then TLS certificate verification - of the server is done using the default CA bundle; if ``False``, then no - verification is done; if a `str` then it specifies the path to a certificate file or - directory which will be used for verification. - - *hostname*, a ``str`` containing the server's hostname or ``None``. The default is - ``None``, which means that no hostname is known, and if an SSL context is created, - hostname checking will be disabled. This value is ignored if *url* is not - ``None``. - - *server_hostname*, a ``str`` or ``None``. This item is for backwards compatibility - only, and has the same meaning as *hostname*. - - Returns a ``dns.message.Message``. - """ - - if not dns.quic.have_quic: - raise NoDOQ("DNS-over-QUIC is not available.") # pragma: no cover - - if server_hostname is not None and hostname is None: - hostname = server_hostname - - q.id = 0 - wire = q.to_wire() - the_connection: dns.quic.SyncQuicConnection - the_manager: dns.quic.SyncQuicManager - if connection: - manager: contextlib.AbstractContextManager = contextlib.nullcontext(None) - the_connection = connection - else: - manager = dns.quic.SyncQuicManager(verify_mode=verify, server_name=hostname) - the_manager = manager # for type checking happiness - - with manager: - if not connection: - the_connection = the_manager.connect(where, port, source, source_port) - (start, expiration) = _compute_times(timeout) - with the_connection.make_stream(timeout) as stream: - stream.send(wire, True) - wire = stream.receive(_remaining(expiration)) - finish = time.time() - r = dns.message.from_wire( - wire, - keyring=q.keyring, - request_mac=q.request_mac, - one_rr_per_rrset=one_rr_per_rrset, - ignore_trailing=ignore_trailing, - ) - r.time = max(finish - start, 0.0) - if not q.is_response(r): - raise BadResponse - return r - - -class UDPMode(enum.IntEnum): - """How should UDP be used in an IXFR from :py:func:`inbound_xfr()`? - - NEVER means "never use UDP; always use TCP" - TRY_FIRST means "try to use UDP but fall back to TCP if needed" - ONLY means "raise ``dns.xfr.UseTCP`` if trying UDP does not succeed" - """ - - NEVER = 0 - TRY_FIRST = 1 - ONLY = 2 - - -def _inbound_xfr( - txn_manager: dns.transaction.TransactionManager, - s: socket.socket, - query: dns.message.Message, - serial: Optional[int], - timeout: Optional[float], - expiration: float, -) -> Any: - """Given a socket, does the zone transfer.""" - rdtype = query.question[0].rdtype - is_ixfr = rdtype == dns.rdatatype.IXFR - origin = txn_manager.from_wire_origin() - wire = query.to_wire() - is_udp = s.type == socket.SOCK_DGRAM - if is_udp: - _udp_send(s, wire, None, expiration) - else: - tcpmsg = struct.pack("!H", len(wire)) + wire - _net_write(s, tcpmsg, expiration) - with dns.xfr.Inbound(txn_manager, rdtype, serial, is_udp) as inbound: - done = False - tsig_ctx = None - while not done: - (_, mexpiration) = _compute_times(timeout) - if mexpiration is None or ( - expiration is not None and mexpiration > expiration - ): - mexpiration = expiration - if is_udp: - (rwire, _) = _udp_recv(s, 65535, mexpiration) - else: - ldata = _net_read(s, 2, mexpiration) - (l,) = struct.unpack("!H", ldata) - rwire = _net_read(s, l, mexpiration) - r = dns.message.from_wire( - rwire, - keyring=query.keyring, - request_mac=query.mac, - xfr=True, - origin=origin, - tsig_ctx=tsig_ctx, - multi=(not is_udp), - one_rr_per_rrset=is_ixfr, - ) - done = inbound.process_message(r) - yield r - tsig_ctx = r.tsig_ctx - if query.keyring and not r.had_tsig: - raise dns.exception.FormError("missing TSIG") - - -def xfr( - where: str, - zone: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.AXFR, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - timeout: Optional[float] = None, - port: int = 53, - keyring: Optional[Dict[dns.name.Name, dns.tsig.Key]] = None, - keyname: Optional[Union[dns.name.Name, str]] = None, - relativize: bool = True, - lifetime: Optional[float] = None, - source: Optional[str] = None, - source_port: int = 0, - serial: int = 0, - use_udp: bool = False, - keyalgorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm, -) -> Any: - """Return a generator for the responses to a zone transfer. - - *where*, a ``str`` containing an IPv4 or IPv6 address, where - to send the message. - - *zone*, a ``dns.name.Name`` or ``str``, the name of the zone to transfer. - - *rdtype*, an ``int`` or ``str``, the type of zone transfer. The - default is ``dns.rdatatype.AXFR``. ``dns.rdatatype.IXFR`` can be - used to do an incremental transfer instead. - - *rdclass*, an ``int`` or ``str``, the class of the zone transfer. - The default is ``dns.rdataclass.IN``. - - *timeout*, a ``float``, the number of seconds to wait for each - response message. If None, the default, wait forever. - - *port*, an ``int``, the port send the message to. The default is 53. - - *keyring*, a ``dict``, the keyring to use for TSIG. - - *keyname*, a ``dns.name.Name`` or ``str``, the name of the TSIG - key to use. - - *relativize*, a ``bool``. If ``True``, all names in the zone will be - relativized to the zone origin. It is essential that the - relativize setting matches the one specified to - ``dns.zone.from_xfr()`` if using this generator to make a zone. - - *lifetime*, a ``float``, the total number of seconds to spend - doing the transfer. If ``None``, the default, then there is no - limit on the time the transfer may take. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying - the source address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. - The default is 0. - - *serial*, an ``int``, the SOA serial number to use as the base for - an IXFR diff sequence (only meaningful if *rdtype* is - ``dns.rdatatype.IXFR``). - - *use_udp*, a ``bool``. If ``True``, use UDP (only meaningful for IXFR). - - *keyalgorithm*, a ``dns.name.Name`` or ``str``, the TSIG algorithm to use. - - Raises on errors, and so does the generator. - - Returns a generator of ``dns.message.Message`` objects. - """ - - class DummyTransactionManager(dns.transaction.TransactionManager): - def __init__(self, origin, relativize): - self.info = (origin, relativize, dns.name.empty if relativize else origin) - - def origin_information(self): - return self.info - - def get_class(self) -> dns.rdataclass.RdataClass: - raise NotImplementedError # pragma: no cover - - def reader(self): - raise NotImplementedError # pragma: no cover - - def writer(self, replacement: bool = False) -> dns.transaction.Transaction: - class DummyTransaction: - def nop(self, *args, **kw): - pass - - def __getattr__(self, _): - return self.nop - - return cast(dns.transaction.Transaction, DummyTransaction()) - - if isinstance(zone, str): - zone = dns.name.from_text(zone) - rdtype = dns.rdatatype.RdataType.make(rdtype) - q = dns.message.make_query(zone, rdtype, rdclass) - if rdtype == dns.rdatatype.IXFR: - rrset = q.find_rrset( - q.authority, zone, dns.rdataclass.IN, dns.rdatatype.SOA, create=True - ) - soa = dns.rdata.from_text("IN", "SOA", ". . %u 0 0 0 0" % serial) - rrset.add(soa, 0) - if keyring is not None: - q.use_tsig(keyring, keyname, algorithm=keyalgorithm) - (af, destination, source) = _destination_and_source( - where, port, source, source_port - ) - (_, expiration) = _compute_times(lifetime) - tm = DummyTransactionManager(zone, relativize) - if use_udp and rdtype != dns.rdatatype.IXFR: - raise ValueError("cannot do a UDP AXFR") - sock_type = socket.SOCK_DGRAM if use_udp else socket.SOCK_STREAM - with _make_socket(af, sock_type, source) as s: - _connect(s, destination, expiration) - yield from _inbound_xfr(tm, s, q, serial, timeout, expiration) - - -def inbound_xfr( - where: str, - txn_manager: dns.transaction.TransactionManager, - query: Optional[dns.message.Message] = None, - port: int = 53, - timeout: Optional[float] = None, - lifetime: Optional[float] = None, - source: Optional[str] = None, - source_port: int = 0, - udp_mode: UDPMode = UDPMode.NEVER, -) -> None: - """Conduct an inbound transfer and apply it via a transaction from the - txn_manager. - - *where*, a ``str`` containing an IPv4 or IPv6 address, where - to send the message. - - *txn_manager*, a ``dns.transaction.TransactionManager``, the txn_manager - for this transfer (typically a ``dns.zone.Zone``). - - *query*, the query to send. If not supplied, a default query is - constructed using information from the *txn_manager*. - - *port*, an ``int``, the port send the message to. The default is 53. - - *timeout*, a ``float``, the number of seconds to wait for each - response message. If None, the default, wait forever. - - *lifetime*, a ``float``, the total number of seconds to spend - doing the transfer. If ``None``, the default, then there is no - limit on the time the transfer may take. - - *source*, a ``str`` containing an IPv4 or IPv6 address, specifying - the source address. The default is the wildcard address. - - *source_port*, an ``int``, the port from which to send the message. - The default is 0. - - *udp_mode*, a ``dns.query.UDPMode``, determines how UDP is used - for IXFRs. The default is ``dns.UDPMode.NEVER``, i.e. only use - TCP. Other possibilities are ``dns.UDPMode.TRY_FIRST``, which - means "try UDP but fallback to TCP if needed", and - ``dns.UDPMode.ONLY``, which means "try UDP and raise - ``dns.xfr.UseTCP`` if it does not succeed. - - Raises on errors. - """ - if query is None: - (query, serial) = dns.xfr.make_query(txn_manager) - else: - serial = dns.xfr.extract_serial_from_query(query) - - (af, destination, source) = _destination_and_source( - where, port, source, source_port - ) - (_, expiration) = _compute_times(lifetime) - if query.question[0].rdtype == dns.rdatatype.IXFR and udp_mode != UDPMode.NEVER: - with _make_socket(af, socket.SOCK_DGRAM, source) as s: - _connect(s, destination, expiration) - try: - for _ in _inbound_xfr( - txn_manager, s, query, serial, timeout, expiration - ): - pass - return - except dns.xfr.UseTCP: - if udp_mode == UDPMode.ONLY: - raise - - with _make_socket(af, socket.SOCK_STREAM, source) as s: - _connect(s, destination, expiration) - for _ in _inbound_xfr(txn_manager, s, query, serial, timeout, expiration): - pass diff --git a/venv/Lib/site-packages/dns/quic/__init__.py b/venv/Lib/site-packages/dns/quic/__init__.py deleted file mode 100644 index 0750e72..0000000 --- a/venv/Lib/site-packages/dns/quic/__init__.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -from typing import List, Tuple - -import dns._features -import dns.asyncbackend - -if dns._features.have("doq"): - import aioquic.quic.configuration # type: ignore - - from dns._asyncbackend import NullContext - from dns.quic._asyncio import ( - AsyncioQuicConnection, - AsyncioQuicManager, - AsyncioQuicStream, - ) - from dns.quic._common import AsyncQuicConnection, AsyncQuicManager - from dns.quic._sync import SyncQuicConnection, SyncQuicManager, SyncQuicStream - - have_quic = True - - def null_factory( - *args, # pylint: disable=unused-argument - **kwargs, # pylint: disable=unused-argument - ): - return NullContext(None) - - def _asyncio_manager_factory( - context, *args, **kwargs # pylint: disable=unused-argument - ): - return AsyncioQuicManager(*args, **kwargs) - - # We have a context factory and a manager factory as for trio we need to have - # a nursery. - - _async_factories = {"asyncio": (null_factory, _asyncio_manager_factory)} - - if dns._features.have("trio"): - import trio - - from dns.quic._trio import ( # pylint: disable=ungrouped-imports - TrioQuicConnection, - TrioQuicManager, - TrioQuicStream, - ) - - def _trio_context_factory(): - return trio.open_nursery() - - def _trio_manager_factory(context, *args, **kwargs): - return TrioQuicManager(context, *args, **kwargs) - - _async_factories["trio"] = (_trio_context_factory, _trio_manager_factory) - - def factories_for_backend(backend=None): - if backend is None: - backend = dns.asyncbackend.get_default_backend() - return _async_factories[backend.name()] - -else: # pragma: no cover - have_quic = False - - from typing import Any - - class AsyncQuicStream: # type: ignore - pass - - class AsyncQuicConnection: # type: ignore - async def make_stream(self) -> Any: - raise NotImplementedError - - class SyncQuicStream: # type: ignore - pass - - class SyncQuicConnection: # type: ignore - def make_stream(self) -> Any: - raise NotImplementedError - - -Headers = List[Tuple[bytes, bytes]] diff --git a/venv/Lib/site-packages/dns/quic/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/dns/quic/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index e9c7bddbf2417ac97512680356255842d489b316..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2548 zcmZ`*-ESL35Z~Q9eRr3n+=sh& z4j2UqXrB2S62wdX4*rXK0f{G`dE<$hJ)h&o?MXMgGdnjs^P3MlER|*nJoP`*qYnFY%IJ=4F4L&udxUtN2x3^=rJQ`GU9L*LmGvzgE0^jKBE7*Mq zn)>P`s@7ot+SQm%%%YBZ9X2OWZv&!cV)BBXv2*exiH#F-W}ZXuWmx1A0}6**ItS07 zmSiCKLQlrFkX>is#r8;;RMLcwP;h0Gn1SQVCQS+>m8lrgx&u|a8>-CEC*WC>2U4W7 z)S~JpY(EDp#=~GZl|_tc2i|`zAd+w@2xkK75qf8S+_h;5w4g4FwvA5Nb~0<*ekcYW z?k(GXIdHu6WWvjFrqyjQ{}AuN7AO*vYRQy42=5N6Vcss?kw%vZCX7=PM!yNp<sto$y?j=bY~x zNjuV`?Gc(o=h;st{b6Ga&E<^Tp3rVx3cu`*E!t359E!Y?!tjaVGOCd zhaX_ePI!Rm=~(wsp8)~P*0Wju7RVGf--MA%aL}ixc=!<#?V+BQcawZP?7Klv;S~x) z;U(y{ZM!QSC=3}XY*SuA*=r3rGuGhdbLUv{6~_&6xNmC$1F7rw2Fk(TK3*7|@v62x zX-MVJzLx6`vze^0|MVD9+79a?Ih@@oMkz&O)l9+B9HEvQju}o2x9Gk8s%1*XycUIV?1P}zk zy9?4pp_H=Jar4l=W+u}I;4SKO`WN&mdFn%-+L_MmOCI{9$JWzHC(|+eJLm4=lS)6p z*}M1dp1pg|x##0|&ayQ(=P39s|MJBLfAxx@{3{K{e+C9`;fQ{QCQt&kp}6v_x+;$~ zSL3tp>U=g_gU_aG@i~{C?ev^?9ll;j&qY3Kjk*1jTiTy@=l9EQd4IuO*k5!PRplKe z&;#R%5*XpaW8GcC*bFR;t#BUWWsGxyjjPD;C46AXi)lAC6i|_kQ|9&Wv(%XI%64jkpg#Laq zcefdS(gt}LY<_T~N-r4y>FFSPfKI58a9r&(WmgTB&SBU*+Et?Dz~88HFN{8SYs z48+o~S*Cjn5G16$+Y*^XU&7^x9@kFF>Y}=S+I{&9zNVj=*maT!&A<%)2|AC|JXq>0 z*md=x4(8Op)>8+nn5V@;8x&9P&c#OG1eFDi&<9$^=*LR4U?_3!_^Xn|*ska6&Zp{; z5@__?fmYGCwgm~bQb^XkxV9g*I$%k(_C1(PP57)bIqzO)cQ+KS@xVU}U5DH{ z0-jCmj3u#3!{WA_XH$rlNOY(`k`F(rhHW`ndbeV*R1?eJZ*`h+;*7sAUCETl1u4y! zaYWS7PBhg~i>jeos-|8*&sMclOVfUJmO5oitZH~P`;l!8rTvE(45bYTKZJ}(+5<(D zNY;?D-Zvm+6H4nXJMaLYm)Wi!! zLUt}*q=s~DeoGo^yXj4PUO9R$$|8YvhDf*FZL`*ruFSzR1|d}~57q=yy` z*26<|$k3pLlX6+ZHJvmwlLaIOO&pMBLK_42RoT5b*SAUUK#>nH&p_K@jqY1Lnqw$W zNdY~kc%W}RqYdk7mv2@acWq27rIx0Ok`%l#CuY_n@4+_(X$lKH$=wfQ&u=tX+=&Gr z*Qv&d)oGHSN_5;!wNXm>5*~zataZa_f#*b64Qq$t?|~v(M5CQJP{J~fMQsH(UsSv2 zXXTtebz{cVO-#WeeifZD5od<3)O8llgzu6{Ww=G`dev`7orWKW;tFO+%p(E!3kw~( z@yyKZz>od=0^!htbf7MYL06_3L_}x?8<;Ah-6!rYs@;`Yj)-i68#1M#XWqde{Q!R@GsMms5DKa23*#%cHBEa#&~W+D@5D(@zR3(5arBC4o~g^1ch6eT;I zUX97O-oqUZjI@yM>g)oTYUbVK#Od9i)4tKW(?}*?a@Ok{&-243G{^HkqzB35wG%@< zlj$L8mB_Lm^@p48VvsSN+5G=$+hOm+u>8uzw&TuIZR-a1^D17#dn~?z-cY#_UcC6Y z9VR*I0gogWU%EFfV?Y`|{Di>KHlB~lXta|OZ+Q9C&{n=MwC)SDG9Nz0w)a%MQ7IA3 zYWn*jU=}2~-wHYn>K8rlpyM~>9Y#9Ry;H=J9_ee;`)z7|hZ^SSThx0KO){5au4>q5 zc;49Z7l?#_hsdF!Si;WURuK0L{1qL?Dd23{W?5&NDrhEt+15pMT+Wbgu*z6h3-l*> zU|pbG;8Y{9f*j6fUCERy6Tx&_uQCBN7#LQgW#PZCiu9syqXK%-~&tbs)s4bVlSP>e9Fc;>KYp_k)pHq+#}br6IUufSe|ymqB1 zNMm_tlAIT{s(WE9VT`#65E~~;-UGiGL=Olh!@aZ{VH_s&DWz9MN`XW|kgGt{VJuBS z2x*6xx_RNnezXToASVg);?bNWZQ~MfQza)O`#jB(gZC0)6eUKxB@mXPR!3CBq#(~8 zU(D^xFbrT_ASg}VmNj_=NQlCbgERFeLjFkXXG3cWMMGQe!JRx(yMNpLQ7jQB z0ud0AiV@;FMQ@-Z4Ut=ofp$2m=V9wkpqi{QzwMt`_@qfA%e`xfK;hdOzPmk{63TDsVvZsrW4z6Of&|f4qiI@6I17)Do zy#3`-8UTutcw;shXcmS(r#tR*fSvQe&gYJQEK%JLmFChBB@;k^UTJ3T70DZ^+5d*- zH_vjURLm`j56P`Rqh`CZ%IMHFYRxcqOa3lr9+~Rc6qZPd+@eo8-#q{us9I7Wtw3Z0PwR`zoa(+egc$}|1uTp#q|;9Fn^^`RHt|%&l;~gccavPYKJgk&_kC)naBhBRTD!O# zT}MNaszm5te@QK#I(nIP9@kE<=$g8$mUR19ubvtw#R6dPsdi%NlxS-IWodM_zMyBj zUpmt*tq`6B6CmnEu@P7KWsCTdseiqZ3MY@NdyE)5=R0V#;#|?aPdbV`V>b* zegI6S$ff(@a~PAG@qD&2;5L?0uds!x(K6UnC>zRR`){DI&UkvwPWCh6mCzMs*u<@N^6D3k-u>!x`JI_!f_VZ0E;H{=L=>UHIhSK*@Iq~Laxy0xc8m)})BrRS08^eE9m8Er5`?guMy8u@{O zXN-p?l1Zlzr`RtJl%AQnJVL|lcIJ-X9l9MPlAtT~i~%YY=*^F|0PoO5kp#=aB~B`3 zHdw)O{Q)jW`&`KEGV=(xyml*nc44Q&hjv~t|F-EaoH|l2HdaQ{bL;64% zA_leH&r{+{yAMtH;GqFp1GElk3!wc7GzfS-tzH6^*)zr6o>@oH26MmFGwS7@>CHFu zxVFI8Zl%{2a9$+Z{u1hrV`=fh%VTd?#v8=U8w5Rt=g-j`Bb_>Uxw$n%`xi{BfmW-p zjA)zR9^-ixZ}|zHTo-iw7_Yv4(@m}cgr;{j&?ZgFA}l&rcAZl_bb zi#Ibkx{;#MfJ3PGm?)P=xNbWX`?V&cQ#SmYv>K~QQfRmZ$?xqDfjot~Q6mi7sih`n zm8)phO7Xn*v&QY ziI2WINR{UFXUoRoIDtQr6IJiFy}a#cwD z0VV?{-=#HvkD9lrp%^6%j=;KL1jSZIev>_fIHcYYHCL&*M$Jf6h278&&eP*^l~E)X{OU?vDyOfCCY;Qd`_>W40TPP*t~SH!z#$LyI7!v7FF^D*^jJ? zmcN066$KubKDhDHf!R$UdFx@WmlF#;tB)^^up=w;yBc&E>!y#?yuB4$7JN9nr4p}r zpPDT+?$VLpjDdQi2;Z}Tr@11Ocb#Q3-@;uu5k|jRCeiJWkm+KJ2cgwQ}bKY zP)6roNb&AE!QFN6zgxTCksoqJjR;n!3DW7%q2}l^O6>BZ zF6zM;a$$<;`PEcB#kUz*Bq9Y6}SArZXAt41fg| zv&)_VNo)-&iXi7wwsTK8_7m{PzmTd_xyn^}%3Gc?5Aj2uRFyYAIjNZWzMh%AVOdFK zQPb1i)0fkyPoMLh)994TMFqe4U%j~9`lh1%I}5`<1BI)2g8x9`Dz4gA8p&I2sIsgz zH2KyWx_lcAL%ws3oP3)N6K}1Z-?JLlUZGJ?lm5lVl>A;w-{tgON#E0rs;f6Btbf-|7LTM4Dl3PZpjM5TH6?Yn? zX>SQV&!Sv)XHcHO*K;V%x^pPadFSx;1y|irYV%)W#mah3i}h>%L2TXahOLh8v|Ea$ zC|}}Hz9e&+Y&HB-QMigHC?W9_atR#bh+16!*!LcHy=LgSt9RGdYkF+iw(snDwjCF3 zd#~f}x0x^5_Je(=oqTzs2=0+g{`1z2EB8JQJQ3XMZguv&dpEscH|%upy?=A{q0_$i z(DNVOd%t!6UeF4?OI@eA>uhS5f*p9CZ+pJ`M2(HWYi|yC zB&N`sjBWX?(6(PfNv_dUi)wE=Az>x^+SECA`eUAtqy?uziIg2hK#Vt#Gn5@QQr`rz zwi;<-E~OLSB$e8Fy{3t2bP^RLPjoSZS8TXW=)`6#Ag$vx>fQbDB3emNF;zpY;3=xc zvtBVJ6AhZ=PWEHI&#h$?Lei)nfwJA4C{WB$)-c(8(zn|JlZYSCIlrxZh8_E-Py{0D9a(~C? zv9g`~7Q1nA=3tw$ZzD|L7V+Uc!D~n&7-lNv712-4aWzm}k;IafvkPTVD7&>I0tp3ihc=PGq};k0Xp2*`@R7 zK>|;dz|6=yRHgKQFsg-hQAQik!=?#6$<|CHC6C!`r`^7S#*&;8Hilc%tE3x~HdwC} zM4ls(W>H`=%VdFxT)Ld^D=hMm46RwNp2tW~iLpgMp|%uDwG1ndKfPqiZ%tH>{J1e! z@dUq*Mnz5T(RDJAtmn>Ja(|(_7DpF5&|%~H zG&_WX`aKbLRa|6#(gD<3?sxd@MI^nMu{m1qh-7o*iKBn*d86l3e%$F#u`o78+Ti~- z&u=|%9xLPa2mOi0`IWUerA+!#vW&h|7W=9wh4Rcs>LQg0l!lwWQ+~!q*xK{5tHdH$`X9PCIR2R;gqywWJ!l@eF7A>tjrMUf)w|p*5F^ zk(^4`G7T%ChU&3;qAbC_9%-X1f(F_`WBDW8*>fI?S5V5d;tKNO5|dF;jhC_&B+D5r zuYtztie{g?qIC7+ed|pwA^TBxQHjYV{WCJODO^ZU2sJE4{ag+89pgAh{eNgg#*TTM zKT!^IkuJ`<+M(%JT>a3Da;_0t$Aw5cQICsm?gZQVCR({>WNvD19{r}+4|xmuQkpMB zIn)%la))`0cPGjpmkDXYN;n;9N0>cnw}nyFgt98=n~Bi6q@3ue(}gQ3o|W~QTV^d) zj06pp_1@Q-j_-HE5bPcDwCX zQ;P1Z82A!82SAT#NKFJkZ@eDQ;CtX~diMP{Ue7)W zD9u(kHj|~rrtgLAP7_@pgETkR@mX*saf#f_G_lltaY0rQjn%9K_vn}*wpg45*sp-xYL$P+$C;xc(2xj+jDsQ1DtB{gV$ z$`rGwJjH9sB&Qe#8T6{KIw<2b?;4#s`9){>MC~rJv}1gN^%zQ+JGh|2`l!mMa1S<= zM|2IOnXcE&1lvkz^D@RC!Z(z1F~?*~d(EWIknOlGd<8)5KSQg47^#9SThO#;re^%6 zq+5mOcI&jik1ysIzMC%qgll>iQG4UMo)ohc(V2h5fggdzA@+xwysTeJ0Y9 z-(_yVP??i}aTy=3;R(1G5-?hpF8}hyvUT1vO9jC;O*|t%Dz>Y5f{&17z_Fkfw1Vo+ zNk>zK!{P?Ko%vl&ybC*K_)}@k z8Pt5>8mQ621^7IM__rc+S~w$M+JAZBdW~ zG=3vzcRM14t1ZRJ1)|+^eAoejTmo7HsZHX%)9Ns&5Nq3)#n-{8M(Nh&0c#0`FH7(o z>o6y=(So{eRGdwFvm^Sm>9(^OFSa|6?6&vNYiIR#xZiDiq{YL;X3%NwdZ6jrntgkH zwH{k(=8br6y%XNvL)$$VCqz}Gsma?xXJ0hET3%{;NgT*c7Dz>p^W`U?Y`?J(}=y@Kts?_z=_l8DSzNifp+>C!9aU1|{!qRCmUy=5B#H_G!e?}U3&KRlhNMMrr4Bth48YU3mKz^Jr z>!|xjJaX!i+Iwlj)WdpgtvQVCm?w;(Rd`CTn!t;Nkp*aFWG$?N$>mw=JY{H zePnaU6&();2&i-uXC#Sc9BaV0dIXIEO#$uU(nZlj)I=KKy#{!1fRl!}5UJuqn1fEy zWt|=wn+ypV>#ZtmiPQ;OKmQqjPreNk`U)nJ+MrQj2!Z%q2*y`L9SQt`mJjR1m{DUU zQ4TibDnLB5<+Nkn?>rK86=JJ}qbLxL9NUz5#_o@6WbORMKzxC8r@m`y(0amAfGq zlWCnvZs*jVvzsBKm;+FeXrIArerW;~D?_c5-Oi6Qm{JqxHrpL16r@aanM~rTj}QNf zM^0%e=T*U)Qyk=gSJ{kbH{)PILlBDrbKsal4#>tVSy#+Wc zZ!CakquLOdaFM`~rQ$r(84UIU35lj6MKb$N5E5Y2@Qx&I+^kJ(%AcDgY{r+W}rMhA+m_q>Ay(-t=OeaJb_NuKcu zn%ubnS1@BzFAg|lPEH&bWdoU)(k>!SDzSQHR96dz?8Nt(+~WZGRD2V|_y|?C=>&J( zXB%of;WF`%H0B;TemF)*qbMtr$vLI?jLDxcIb!l-CSM?Ft_u^v$X86RCBz)L62t@9ay7}nEQt& zo$mQT45H6oVIUXpD4$470clqc<}%r&{(IC%k85t6>UVRJ4Q3mid zxEC^zG!!z*Xib`)iayY~@=TB10rXfgA$TBth&RzCxdiA(4YD~B_km_M`{j{gnNvKa zmCG(78G{WqTt>bKL`uMAoG3@|gTtJ>kIO~5o5~MNL}Ym{XTGC6SfFX*9UYa(+meam zs~8Y~bP=!Qh|Jx&_C0%Jbz|f9-F3Tu`^I~#^^MqQw*thmcD;ijo=rb)*!8>i&DHl; z>#Ldf*XMFATham)&@ zOgM@oKE*J@#9wh?!;9ph6%5^ozhUyXO#TkZsWl|0h6@lsWkRoXoa&#TZk3z)Gh}+_ zCQ>SoC1QkYK=hxZSsF;IKj+TyFF4I#GI^Z|`64*Y(9}|dr&uSD{2QL&91=^>wBj@E z#pLKo0Qx(YiTlGT*^Y{2E zV%{jQA#R8h7^sRrKsohjL|;kFok-E{zkhlBx}y?*UKYDsu0K zZecmj(AWdU{Tv@Y$JVZ4S@djeM8*E4}-?Jtcrk$9R}d1u{i!My$}T`^@9}#cBK6PZuYI_M%-~R*GerR3_jxE@1};lSJ8z6=JWkw2E-E&>l_qu4Xmc zvpU_g@-DN)u@nqcfz|A-C3;zm*r+8{hapYBX zRKC|7jjy_+^VM(+zUG`9Uri^^S1Y*|lB?|$xxK_!tySKwIF;QgXKJ_VRClMH>D?J; zMpb-uM|Ec3Qas%=9w?sSPv6&_Io#(w6ZfV+h5J*u&wCc`Ex(HUc~8Br)C!NWW@WvW zi>Kea@vUX|oh!fPu3Xu;^47I0@5D3TtcU)4on~XX9Rz+OYPN%TDs6kG9@Mve5m(ZN z>yhy5yK(tO;D5M>-oCf`?plMU&wljeCj0;uUm*fH+9%4E>ZzXgzyg7I6Ce;T9t1k& zSzh6R>X_cVSM*A#<-M|3d7wC!H|14vEqK%346e2}>&@X>{6sMnr-bb-#Fgs@L4)=n zm)A(&Ps^Y>F^{g{7g0pYeWj;%)vk7|sY;~v^kb!~xCUxDu9=>4U3sLg*Ya^L?CfFt zmg_cyX5_kYA-W9$c+FrtE`VTOlj&u-_v&|ix3d=;Z?_wF;+)&UrKZP5=(o0FyD=bb zA!G`=P4AH!7hJc|s)wQLK2n~pEq`_MM(B%hb8ox7>u;|3;hm_xxB2$U>VCbox$g)2 zn{PL7ZHCRre|fLoxC73Fn_dvUau+*)#SKA&rM&||a(sa{Yoe&AwpvjS7lsM6luHWuN?v`lpx{%7Is1sAf6gtFt_f}_X%NLGuyT0!`HgzB&54J^_o*Vb-%_!DE z#kk;q*zot5pZN_rXUz~*>Sfk<+npea?ZNbMK6$S=g&wk)r@j`==x(*eCESI?2n{^2 z)RL;H)z2(_@#mIN!o7B~cw*|>e~n`1?s z9_P#$Wnauv7Bd(LPmErUI3B(hnLFUh1fG07JMyk7XkE2}SipseE>5H7SfTF+t{-?z zXmN&~o~7a(6^kfpI#X8=jl>tI7$IdTB?V3M3Oa-|Op?=Pa%$@0iKVCH)IL2tHzMfS z8PE*oyXPCmX zz#FSqAUTHY+aBI_tZhQO#<+7eOJl4e-=%c`uXvtHvJRWHXTnOhv!iJx(3r<0PKVmX ztF@wYI-@62ZxUgSi*5$1a?Q}aeOX+@zyV|9{I(yt^;S!~fcDq~o^={gY<2>|q*%w( zL~SHbiMznT=Al2z-n{S|eskY{13j3tHWY7oyf%g_|j%3YN=heg6kxfvKp$!b_`C5Mi#CvfOi&q~?-m4^^ z>KOh)3eS%6p7<}fsXNnP@9u6paO<82leX81Bn+BCJ8Etnq#C(|7mJsv7|}?3F!0-W z9Fnae?JKD-o){;GXGXR+=-nW=PCr!dgW0d(1{+hPa`n__Y-@IOTXIX9gn1Kov>p17 zREa1ftIqMm-^7d9CXztCcyc&5vRLjkwoY0rNz)VJVK*hEq|0SAjZz3E-47r_uDd~_ zNa+mq@bt*L`kfjyZTcC4q_3fsq?hRNIgE#o2gaWsq7d31Y3pm?C=pm<@Gqm*mtj~t zH#*q!<2=>iVZiu3q|b0{nl)0|bZZM$L_s2NqAdo=KH=#w%e{6jQ9m+#6BH$2yZXTvYe zd*{58SB3{`dFR;Yt$0%p3h-a$UDcb$o$bwdv*=y)7UBEOqj!n>E_kQmAD6u|-dQ}Y zu#YUTmYWY&2`OVll)zRz{uFidFp+DqHE$F zfk{UduOCjKZuYFGuw(a%)J}bm+5X*Bg0i7RrGwYVk7JQEdu0;NkCl5Qpk}Xva*Awa zWb~@X$|m0APUAO&_L<(Sm)cP?tw(dcQ^y$V&U;iY;QlnwZ(y>yY(#?A#RNA>+ddq+g;(fChsPVROyI@9~-xt@J7f7ag1i*N6td4 zea~(A`+kdnO89WZqt0H-j|;1*E68#e=M$p{$9~U8JYdVI_v%dnAtn\~l$+S4 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 YQ8boH$Ps^;dl41zO1|=(^2<5(zg1cAW&i*H diff --git a/venv/Lib/site-packages/dns/quic/_asyncio.py b/venv/Lib/site-packages/dns/quic/_asyncio.py deleted file mode 100644 index f87515d..0000000 --- a/venv/Lib/site-packages/dns/quic/_asyncio.py +++ /dev/null @@ -1,267 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import asyncio -import socket -import ssl -import struct -import time - -import aioquic.quic.configuration # type: ignore -import aioquic.quic.connection # type: ignore -import aioquic.quic.events # type: ignore - -import dns.asyncbackend -import dns.exception -import dns.inet -from dns.quic._common import ( - QUIC_MAX_DATAGRAM, - AsyncQuicConnection, - AsyncQuicManager, - BaseQuicStream, - UnexpectedEOF, -) - - -class AsyncioQuicStream(BaseQuicStream): - def __init__(self, connection, stream_id): - super().__init__(connection, stream_id) - self._wake_up = asyncio.Condition() - - async def _wait_for_wake_up(self): - async with self._wake_up: - await self._wake_up.wait() - - async def wait_for(self, amount, expiration): - while True: - timeout = self._timeout_from_expiration(expiration) - if self._buffer.have(amount): - return - self._expecting = amount - try: - await asyncio.wait_for(self._wait_for_wake_up(), timeout) - except TimeoutError: - raise dns.exception.Timeout - self._expecting = 0 - - async def wait_for_end(self, expiration): - while True: - timeout = self._timeout_from_expiration(expiration) - if self._buffer.seen_end(): - return - try: - await asyncio.wait_for(self._wait_for_wake_up(), timeout) - except TimeoutError: - raise dns.exception.Timeout - - async def receive(self, timeout=None): - expiration = self._expiration_from_timeout(timeout) - if self._connection.is_h3(): - await self.wait_for_end(expiration) - return self._buffer.get_all() - else: - await self.wait_for(2, expiration) - (size,) = struct.unpack("!H", self._buffer.get(2)) - await self.wait_for(size, expiration) - return self._buffer.get(size) - - async def send(self, datagram, is_end=False): - data = self._encapsulate(datagram) - await self._connection.write(self._stream_id, data, is_end) - - async def _add_input(self, data, is_end): - if self._common_add_input(data, is_end): - async with self._wake_up: - self._wake_up.notify() - - async def close(self): - self._close() - - # Streams are async context managers - - async def __aenter__(self): - return self - - async def __aexit__(self, exc_type, exc_val, exc_tb): - await self.close() - async with self._wake_up: - self._wake_up.notify() - return False - - -class AsyncioQuicConnection(AsyncQuicConnection): - def __init__(self, connection, address, port, source, source_port, manager=None): - super().__init__(connection, address, port, source, source_port, manager) - self._socket = None - self._handshake_complete = asyncio.Event() - self._socket_created = asyncio.Event() - self._wake_timer = asyncio.Condition() - self._receiver_task = None - self._sender_task = None - self._wake_pending = False - - async def _receiver(self): - try: - af = dns.inet.af_for_address(self._address) - backend = dns.asyncbackend.get_backend("asyncio") - # Note that peer is a low-level address tuple, but make_socket() wants - # a high-level address tuple, so we convert. - self._socket = await backend.make_socket( - af, socket.SOCK_DGRAM, 0, self._source, (self._peer[0], self._peer[1]) - ) - self._socket_created.set() - async with self._socket: - while not self._done: - (datagram, address) = await self._socket.recvfrom( - QUIC_MAX_DATAGRAM, None - ) - if address[0] != self._peer[0] or address[1] != self._peer[1]: - continue - self._connection.receive_datagram(datagram, address, time.time()) - # Wake up the timer in case the sender is sleeping, as there may be - # stuff to send now. - await self._wakeup() - except Exception: - pass - finally: - self._done = True - await self._wakeup() - self._handshake_complete.set() - - async def _wakeup(self): - self._wake_pending = True - async with self._wake_timer: - self._wake_timer.notify_all() - - async def _wait_for_wake_timer(self): - async with self._wake_timer: - if not self._wake_pending: - await self._wake_timer.wait() - self._wake_pending = False - - async def _sender(self): - await self._socket_created.wait() - while not self._done: - datagrams = self._connection.datagrams_to_send(time.time()) - for datagram, address in datagrams: - assert address == self._peer - await self._socket.sendto(datagram, self._peer, None) - (expiration, interval) = self._get_timer_values() - try: - await asyncio.wait_for(self._wait_for_wake_timer(), interval) - except Exception: - pass - self._handle_timer(expiration) - await self._handle_events() - - async def _handle_events(self): - count = 0 - while True: - event = self._connection.next_event() - if event is None: - return - if isinstance(event, aioquic.quic.events.StreamDataReceived): - if self.is_h3(): - h3_events = self._h3_conn.handle_event(event) - for h3_event in h3_events: - if isinstance(h3_event, aioquic.h3.events.HeadersReceived): - stream = self._streams.get(event.stream_id) - if stream: - if stream._headers is None: - stream._headers = h3_event.headers - elif stream._trailers is None: - stream._trailers = h3_event.headers - if h3_event.stream_ended: - await stream._add_input(b"", True) - elif isinstance(h3_event, aioquic.h3.events.DataReceived): - stream = self._streams.get(event.stream_id) - if stream: - await stream._add_input( - h3_event.data, h3_event.stream_ended - ) - else: - stream = self._streams.get(event.stream_id) - if stream: - await stream._add_input(event.data, event.end_stream) - elif isinstance(event, aioquic.quic.events.HandshakeCompleted): - self._handshake_complete.set() - elif isinstance(event, aioquic.quic.events.ConnectionTerminated): - self._done = True - self._receiver_task.cancel() - elif isinstance(event, aioquic.quic.events.StreamReset): - stream = self._streams.get(event.stream_id) - if stream: - await stream._add_input(b"", True) - - count += 1 - if count > 10: - # yield - count = 0 - await asyncio.sleep(0) - - async def write(self, stream, data, is_end=False): - self._connection.send_stream_data(stream, data, is_end) - await self._wakeup() - - def run(self): - if self._closed: - return - self._receiver_task = asyncio.Task(self._receiver()) - self._sender_task = asyncio.Task(self._sender()) - - async def make_stream(self, timeout=None): - try: - await asyncio.wait_for(self._handshake_complete.wait(), timeout) - except TimeoutError: - raise dns.exception.Timeout - if self._done: - raise UnexpectedEOF - stream_id = self._connection.get_next_available_stream_id(False) - stream = AsyncioQuicStream(self, stream_id) - self._streams[stream_id] = stream - return stream - - async def close(self): - if not self._closed: - self._manager.closed(self._peer[0], self._peer[1]) - self._closed = True - self._connection.close() - # sender might be blocked on this, so set it - self._socket_created.set() - await self._wakeup() - try: - await self._receiver_task - except asyncio.CancelledError: - pass - try: - await self._sender_task - except asyncio.CancelledError: - pass - await self._socket.close() - - -class AsyncioQuicManager(AsyncQuicManager): - def __init__( - self, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None, h3=False - ): - super().__init__(conf, verify_mode, AsyncioQuicConnection, server_name, h3) - - def connect( - self, address, port=853, source=None, source_port=0, want_session_ticket=True - ): - (connection, start) = self._connect( - address, port, source, source_port, want_session_ticket - ) - if start: - connection.run() - return connection - - async def __aenter__(self): - return self - - async def __aexit__(self, exc_type, exc_val, exc_tb): - # Copy the iterator into a list as exiting things will mutate the connections - # table. - connections = list(self._connections.values()) - for connection in connections: - await connection.close() - return False diff --git a/venv/Lib/site-packages/dns/quic/_common.py b/venv/Lib/site-packages/dns/quic/_common.py deleted file mode 100644 index ce575b0..0000000 --- a/venv/Lib/site-packages/dns/quic/_common.py +++ /dev/null @@ -1,339 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import base64 -import copy -import functools -import socket -import struct -import time -import urllib -from typing import Any, Optional - -import aioquic.h3.connection # type: ignore -import aioquic.h3.events # type: ignore -import aioquic.quic.configuration # type: ignore -import aioquic.quic.connection # type: ignore - -import dns.inet - -QUIC_MAX_DATAGRAM = 2048 -MAX_SESSION_TICKETS = 8 -# If we hit the max sessions limit we will delete this many of the oldest connections. -# The value must be a integer > 0 and <= MAX_SESSION_TICKETS. -SESSIONS_TO_DELETE = MAX_SESSION_TICKETS // 4 - - -class UnexpectedEOF(Exception): - pass - - -class Buffer: - def __init__(self): - self._buffer = b"" - self._seen_end = False - - def put(self, data, is_end): - if self._seen_end: - return - self._buffer += data - if is_end: - self._seen_end = True - - def have(self, amount): - if len(self._buffer) >= amount: - return True - if self._seen_end: - raise UnexpectedEOF - return False - - def seen_end(self): - return self._seen_end - - def get(self, amount): - assert self.have(amount) - data = self._buffer[:amount] - self._buffer = self._buffer[amount:] - return data - - def get_all(self): - assert self.seen_end() - data = self._buffer - self._buffer = b"" - return data - - -class BaseQuicStream: - def __init__(self, connection, stream_id): - self._connection = connection - self._stream_id = stream_id - self._buffer = Buffer() - self._expecting = 0 - self._headers = None - self._trailers = None - - def id(self): - return self._stream_id - - def headers(self): - return self._headers - - def trailers(self): - return self._trailers - - def _expiration_from_timeout(self, timeout): - if timeout is not None: - expiration = time.time() + timeout - else: - expiration = None - return expiration - - def _timeout_from_expiration(self, expiration): - if expiration is not None: - timeout = max(expiration - time.time(), 0.0) - else: - timeout = None - return timeout - - # Subclass must implement receive() as sync / async and which returns a message - # or raises. - - # Subclass must implement send() as sync / async and which takes a message and - # an EOF indicator. - - def send_h3(self, url, datagram, post=True): - if not self._connection.is_h3(): - raise SyntaxError("cannot send H3 to a non-H3 connection") - url_parts = urllib.parse.urlparse(url) - path = url_parts.path.encode() - if post: - method = b"POST" - else: - method = b"GET" - path += b"?dns=" + base64.urlsafe_b64encode(datagram).rstrip(b"=") - headers = [ - (b":method", method), - (b":scheme", url_parts.scheme.encode()), - (b":authority", url_parts.netloc.encode()), - (b":path", path), - (b"accept", b"application/dns-message"), - ] - if post: - headers.extend( - [ - (b"content-type", b"application/dns-message"), - (b"content-length", str(len(datagram)).encode()), - ] - ) - self._connection.send_headers(self._stream_id, headers, not post) - if post: - self._connection.send_data(self._stream_id, datagram, True) - - def _encapsulate(self, datagram): - if self._connection.is_h3(): - return datagram - l = len(datagram) - return struct.pack("!H", l) + datagram - - def _common_add_input(self, data, is_end): - self._buffer.put(data, is_end) - try: - return ( - self._expecting > 0 and self._buffer.have(self._expecting) - ) or self._buffer.seen_end - except UnexpectedEOF: - return True - - def _close(self): - self._connection.close_stream(self._stream_id) - self._buffer.put(b"", True) # send EOF in case we haven't seen it. - - -class BaseQuicConnection: - def __init__( - self, - connection, - address, - port, - source=None, - source_port=0, - manager=None, - ): - self._done = False - self._connection = connection - self._address = address - self._port = port - self._closed = False - self._manager = manager - self._streams = {} - if manager.is_h3(): - self._h3_conn = aioquic.h3.connection.H3Connection(connection, False) - else: - self._h3_conn = None - self._af = dns.inet.af_for_address(address) - self._peer = dns.inet.low_level_address_tuple((address, port)) - if source is None and source_port != 0: - if self._af == socket.AF_INET: - source = "0.0.0.0" - elif self._af == socket.AF_INET6: - source = "::" - else: - raise NotImplementedError - if source: - self._source = (source, source_port) - else: - self._source = None - - def is_h3(self): - return self._h3_conn is not None - - def close_stream(self, stream_id): - del self._streams[stream_id] - - def send_headers(self, stream_id, headers, is_end=False): - self._h3_conn.send_headers(stream_id, headers, is_end) - - def send_data(self, stream_id, data, is_end=False): - self._h3_conn.send_data(stream_id, data, is_end) - - def _get_timer_values(self, closed_is_special=True): - now = time.time() - expiration = self._connection.get_timer() - if expiration is None: - expiration = now + 3600 # arbitrary "big" value - interval = max(expiration - now, 0) - if self._closed and closed_is_special: - # lower sleep interval to avoid a race in the closing process - # which can lead to higher latency closing due to sleeping when - # we have events. - interval = min(interval, 0.05) - return (expiration, interval) - - def _handle_timer(self, expiration): - now = time.time() - if expiration <= now: - self._connection.handle_timer(now) - - -class AsyncQuicConnection(BaseQuicConnection): - async def make_stream(self, timeout: Optional[float] = None) -> Any: - pass - - -class BaseQuicManager: - def __init__( - self, conf, verify_mode, connection_factory, server_name=None, h3=False - ): - self._connections = {} - self._connection_factory = connection_factory - self._session_tickets = {} - self._tokens = {} - self._h3 = h3 - if conf is None: - verify_path = None - if isinstance(verify_mode, str): - verify_path = verify_mode - verify_mode = True - if h3: - alpn_protocols = ["h3"] - else: - alpn_protocols = ["doq", "doq-i03"] - conf = aioquic.quic.configuration.QuicConfiguration( - alpn_protocols=alpn_protocols, - verify_mode=verify_mode, - server_name=server_name, - ) - if verify_path is not None: - conf.load_verify_locations(verify_path) - self._conf = conf - - def _connect( - self, - address, - port=853, - source=None, - source_port=0, - want_session_ticket=True, - want_token=True, - ): - connection = self._connections.get((address, port)) - if connection is not None: - return (connection, False) - conf = self._conf - if want_session_ticket: - try: - session_ticket = self._session_tickets.pop((address, port)) - # We found a session ticket, so make a configuration that uses it. - conf = copy.copy(conf) - conf.session_ticket = session_ticket - except KeyError: - # No session ticket. - pass - # Whether or not we found a session ticket, we want a handler to save - # one. - session_ticket_handler = functools.partial( - self.save_session_ticket, address, port - ) - else: - session_ticket_handler = None - if want_token: - try: - token = self._tokens.pop((address, port)) - # We found a token, so make a configuration that uses it. - conf = copy.copy(conf) - conf.token = token - except KeyError: - # No token - pass - # Whether or not we found a token, we want a handler to save # one. - token_handler = functools.partial(self.save_token, address, port) - else: - token_handler = None - - qconn = aioquic.quic.connection.QuicConnection( - configuration=conf, - session_ticket_handler=session_ticket_handler, - token_handler=token_handler, - ) - lladdress = dns.inet.low_level_address_tuple((address, port)) - qconn.connect(lladdress, time.time()) - connection = self._connection_factory( - qconn, address, port, source, source_port, self - ) - self._connections[(address, port)] = connection - return (connection, True) - - def closed(self, address, port): - try: - del self._connections[(address, port)] - except KeyError: - pass - - def is_h3(self): - return self._h3 - - def save_session_ticket(self, address, port, ticket): - # We rely on dictionaries keys() being in insertion order here. We - # can't just popitem() as that would be LIFO which is the opposite of - # what we want. - l = len(self._session_tickets) - if l >= MAX_SESSION_TICKETS: - keys_to_delete = list(self._session_tickets.keys())[0:SESSIONS_TO_DELETE] - for key in keys_to_delete: - del self._session_tickets[key] - self._session_tickets[(address, port)] = ticket - - def save_token(self, address, port, token): - # We rely on dictionaries keys() being in insertion order here. We - # can't just popitem() as that would be LIFO which is the opposite of - # what we want. - l = len(self._tokens) - if l >= MAX_SESSION_TICKETS: - keys_to_delete = list(self._tokens.keys())[0:SESSIONS_TO_DELETE] - for key in keys_to_delete: - del self._tokens[key] - self._tokens[(address, port)] = token - - -class AsyncQuicManager(BaseQuicManager): - def connect(self, address, port=853, source=None, source_port=0): - raise NotImplementedError diff --git a/venv/Lib/site-packages/dns/quic/_sync.py b/venv/Lib/site-packages/dns/quic/_sync.py deleted file mode 100644 index 473d1f4..0000000 --- a/venv/Lib/site-packages/dns/quic/_sync.py +++ /dev/null @@ -1,295 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import selectors -import socket -import ssl -import struct -import threading -import time - -import aioquic.quic.configuration # type: ignore -import aioquic.quic.connection # type: ignore -import aioquic.quic.events # type: ignore - -import dns.exception -import dns.inet -from dns.quic._common import ( - QUIC_MAX_DATAGRAM, - BaseQuicConnection, - BaseQuicManager, - BaseQuicStream, - UnexpectedEOF, -) - -# Function used to create a socket. Can be overridden if needed in special -# situations. -socket_factory = socket.socket - - -class SyncQuicStream(BaseQuicStream): - def __init__(self, connection, stream_id): - super().__init__(connection, stream_id) - self._wake_up = threading.Condition() - self._lock = threading.Lock() - - def wait_for(self, amount, expiration): - while True: - timeout = self._timeout_from_expiration(expiration) - with self._lock: - if self._buffer.have(amount): - return - self._expecting = amount - with self._wake_up: - if not self._wake_up.wait(timeout): - raise dns.exception.Timeout - self._expecting = 0 - - def wait_for_end(self, expiration): - while True: - timeout = self._timeout_from_expiration(expiration) - with self._lock: - if self._buffer.seen_end(): - return - with self._wake_up: - if not self._wake_up.wait(timeout): - raise dns.exception.Timeout - - def receive(self, timeout=None): - expiration = self._expiration_from_timeout(timeout) - if self._connection.is_h3(): - self.wait_for_end(expiration) - with self._lock: - return self._buffer.get_all() - else: - self.wait_for(2, expiration) - with self._lock: - (size,) = struct.unpack("!H", self._buffer.get(2)) - self.wait_for(size, expiration) - with self._lock: - return self._buffer.get(size) - - def send(self, datagram, is_end=False): - data = self._encapsulate(datagram) - self._connection.write(self._stream_id, data, is_end) - - def _add_input(self, data, is_end): - if self._common_add_input(data, is_end): - with self._wake_up: - self._wake_up.notify() - - def close(self): - with self._lock: - self._close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.close() - with self._wake_up: - self._wake_up.notify() - return False - - -class SyncQuicConnection(BaseQuicConnection): - def __init__(self, connection, address, port, source, source_port, manager): - super().__init__(connection, address, port, source, source_port, manager) - self._socket = socket_factory(self._af, socket.SOCK_DGRAM, 0) - if self._source is not None: - try: - self._socket.bind( - dns.inet.low_level_address_tuple(self._source, self._af) - ) - except Exception: - self._socket.close() - raise - self._socket.connect(self._peer) - (self._send_wakeup, self._receive_wakeup) = socket.socketpair() - self._receive_wakeup.setblocking(False) - self._socket.setblocking(False) - self._handshake_complete = threading.Event() - self._worker_thread = None - self._lock = threading.Lock() - - def _read(self): - count = 0 - while count < 10: - count += 1 - try: - datagram = self._socket.recv(QUIC_MAX_DATAGRAM) - except BlockingIOError: - return - with self._lock: - self._connection.receive_datagram(datagram, self._peer, time.time()) - - def _drain_wakeup(self): - while True: - try: - self._receive_wakeup.recv(32) - except BlockingIOError: - return - - def _worker(self): - try: - sel = selectors.DefaultSelector() - sel.register(self._socket, selectors.EVENT_READ, self._read) - sel.register(self._receive_wakeup, selectors.EVENT_READ, self._drain_wakeup) - while not self._done: - (expiration, interval) = self._get_timer_values(False) - items = sel.select(interval) - for key, _ in items: - key.data() - with self._lock: - self._handle_timer(expiration) - self._handle_events() - with self._lock: - datagrams = self._connection.datagrams_to_send(time.time()) - for datagram, _ in datagrams: - try: - self._socket.send(datagram) - except BlockingIOError: - # we let QUIC handle any lossage - pass - finally: - with self._lock: - self._done = True - self._socket.close() - # Ensure anyone waiting for this gets woken up. - self._handshake_complete.set() - - def _handle_events(self): - while True: - with self._lock: - event = self._connection.next_event() - if event is None: - return - if isinstance(event, aioquic.quic.events.StreamDataReceived): - if self.is_h3(): - h3_events = self._h3_conn.handle_event(event) - for h3_event in h3_events: - if isinstance(h3_event, aioquic.h3.events.HeadersReceived): - with self._lock: - stream = self._streams.get(event.stream_id) - if stream: - if stream._headers is None: - stream._headers = h3_event.headers - elif stream._trailers is None: - stream._trailers = h3_event.headers - if h3_event.stream_ended: - stream._add_input(b"", True) - elif isinstance(h3_event, aioquic.h3.events.DataReceived): - with self._lock: - stream = self._streams.get(event.stream_id) - if stream: - stream._add_input(h3_event.data, h3_event.stream_ended) - else: - with self._lock: - stream = self._streams.get(event.stream_id) - if stream: - stream._add_input(event.data, event.end_stream) - elif isinstance(event, aioquic.quic.events.HandshakeCompleted): - self._handshake_complete.set() - elif isinstance(event, aioquic.quic.events.ConnectionTerminated): - with self._lock: - self._done = True - elif isinstance(event, aioquic.quic.events.StreamReset): - with self._lock: - stream = self._streams.get(event.stream_id) - if stream: - stream._add_input(b"", True) - - def write(self, stream, data, is_end=False): - with self._lock: - self._connection.send_stream_data(stream, data, is_end) - self._send_wakeup.send(b"\x01") - - def send_headers(self, stream_id, headers, is_end=False): - with self._lock: - super().send_headers(stream_id, headers, is_end) - if is_end: - self._send_wakeup.send(b"\x01") - - def send_data(self, stream_id, data, is_end=False): - with self._lock: - super().send_data(stream_id, data, is_end) - if is_end: - self._send_wakeup.send(b"\x01") - - def run(self): - if self._closed: - return - self._worker_thread = threading.Thread(target=self._worker) - self._worker_thread.start() - - def make_stream(self, timeout=None): - if not self._handshake_complete.wait(timeout): - raise dns.exception.Timeout - with self._lock: - if self._done: - raise UnexpectedEOF - stream_id = self._connection.get_next_available_stream_id(False) - stream = SyncQuicStream(self, stream_id) - self._streams[stream_id] = stream - return stream - - def close_stream(self, stream_id): - with self._lock: - super().close_stream(stream_id) - - def close(self): - with self._lock: - if self._closed: - return - self._manager.closed(self._peer[0], self._peer[1]) - self._closed = True - self._connection.close() - self._send_wakeup.send(b"\x01") - self._worker_thread.join() - - -class SyncQuicManager(BaseQuicManager): - def __init__( - self, conf=None, verify_mode=ssl.CERT_REQUIRED, server_name=None, h3=False - ): - super().__init__(conf, verify_mode, SyncQuicConnection, server_name, h3) - self._lock = threading.Lock() - - def connect( - self, - address, - port=853, - source=None, - source_port=0, - want_session_ticket=True, - want_token=True, - ): - with self._lock: - (connection, start) = self._connect( - address, port, source, source_port, want_session_ticket, want_token - ) - if start: - connection.run() - return connection - - def closed(self, address, port): - with self._lock: - super().closed(address, port) - - def save_session_ticket(self, address, port, ticket): - with self._lock: - super().save_session_ticket(address, port, ticket) - - def save_token(self, address, port, token): - with self._lock: - super().save_token(address, port, token) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - # Copy the iterator into a list as exiting things will mutate the connections - # table. - connections = list(self._connections.values()) - for connection in connections: - connection.close() - return False diff --git a/venv/Lib/site-packages/dns/quic/_trio.py b/venv/Lib/site-packages/dns/quic/_trio.py deleted file mode 100644 index ae79f36..0000000 --- a/venv/Lib/site-packages/dns/quic/_trio.py +++ /dev/null @@ -1,246 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import socket -import ssl -import struct -import time - -import aioquic.quic.configuration # type: ignore -import aioquic.quic.connection # type: ignore -import aioquic.quic.events # type: ignore -import trio - -import dns.exception -import dns.inet -from dns._asyncbackend import NullContext -from dns.quic._common import ( - QUIC_MAX_DATAGRAM, - AsyncQuicConnection, - AsyncQuicManager, - BaseQuicStream, - UnexpectedEOF, -) - - -class TrioQuicStream(BaseQuicStream): - def __init__(self, connection, stream_id): - super().__init__(connection, stream_id) - self._wake_up = trio.Condition() - - async def wait_for(self, amount): - while True: - if self._buffer.have(amount): - return - self._expecting = amount - async with self._wake_up: - await self._wake_up.wait() - self._expecting = 0 - - async def wait_for_end(self): - while True: - if self._buffer.seen_end(): - return - async with self._wake_up: - await self._wake_up.wait() - - async def receive(self, timeout=None): - if timeout is None: - context = NullContext(None) - else: - context = trio.move_on_after(timeout) - with context: - if self._connection.is_h3(): - await self.wait_for_end() - return self._buffer.get_all() - else: - await self.wait_for(2) - (size,) = struct.unpack("!H", self._buffer.get(2)) - await self.wait_for(size) - return self._buffer.get(size) - raise dns.exception.Timeout - - async def send(self, datagram, is_end=False): - data = self._encapsulate(datagram) - await self._connection.write(self._stream_id, data, is_end) - - async def _add_input(self, data, is_end): - if self._common_add_input(data, is_end): - async with self._wake_up: - self._wake_up.notify() - - async def close(self): - self._close() - - # Streams are async context managers - - async def __aenter__(self): - return self - - async def __aexit__(self, exc_type, exc_val, exc_tb): - await self.close() - async with self._wake_up: - self._wake_up.notify() - return False - - -class TrioQuicConnection(AsyncQuicConnection): - def __init__(self, connection, address, port, source, source_port, manager=None): - super().__init__(connection, address, port, source, source_port, manager) - self._socket = trio.socket.socket(self._af, socket.SOCK_DGRAM, 0) - self._handshake_complete = trio.Event() - self._run_done = trio.Event() - self._worker_scope = None - self._send_pending = False - - async def _worker(self): - try: - if self._source: - await self._socket.bind( - dns.inet.low_level_address_tuple(self._source, self._af) - ) - await self._socket.connect(self._peer) - while not self._done: - (expiration, interval) = self._get_timer_values(False) - if self._send_pending: - # Do not block forever if sends are pending. Even though we - # have a wake-up mechanism if we've already started the blocking - # read, the possibility of context switching in send means that - # more writes can happen while we have no wake up context, so - # we need self._send_pending to avoid (effectively) a "lost wakeup" - # race. - interval = 0.0 - with trio.CancelScope( - deadline=trio.current_time() + interval - ) as self._worker_scope: - datagram = await self._socket.recv(QUIC_MAX_DATAGRAM) - self._connection.receive_datagram(datagram, self._peer, time.time()) - self._worker_scope = None - self._handle_timer(expiration) - await self._handle_events() - # We clear this now, before sending anything, as sending can cause - # context switches that do more sends. We want to know if that - # happens so we don't block a long time on the recv() above. - self._send_pending = False - datagrams = self._connection.datagrams_to_send(time.time()) - for datagram, _ in datagrams: - await self._socket.send(datagram) - finally: - self._done = True - self._socket.close() - self._handshake_complete.set() - - async def _handle_events(self): - count = 0 - while True: - event = self._connection.next_event() - if event is None: - return - if isinstance(event, aioquic.quic.events.StreamDataReceived): - if self.is_h3(): - h3_events = self._h3_conn.handle_event(event) - for h3_event in h3_events: - if isinstance(h3_event, aioquic.h3.events.HeadersReceived): - stream = self._streams.get(event.stream_id) - if stream: - if stream._headers is None: - stream._headers = h3_event.headers - elif stream._trailers is None: - stream._trailers = h3_event.headers - if h3_event.stream_ended: - await stream._add_input(b"", True) - elif isinstance(h3_event, aioquic.h3.events.DataReceived): - stream = self._streams.get(event.stream_id) - if stream: - await stream._add_input( - h3_event.data, h3_event.stream_ended - ) - else: - stream = self._streams.get(event.stream_id) - if stream: - await stream._add_input(event.data, event.end_stream) - elif isinstance(event, aioquic.quic.events.HandshakeCompleted): - self._handshake_complete.set() - elif isinstance(event, aioquic.quic.events.ConnectionTerminated): - self._done = True - self._socket.close() - elif isinstance(event, aioquic.quic.events.StreamReset): - stream = self._streams.get(event.stream_id) - if stream: - await stream._add_input(b"", True) - count += 1 - if count > 10: - # yield - count = 0 - await trio.sleep(0) - - async def write(self, stream, data, is_end=False): - self._connection.send_stream_data(stream, data, is_end) - self._send_pending = True - if self._worker_scope is not None: - self._worker_scope.cancel() - - async def run(self): - if self._closed: - return - async with trio.open_nursery() as nursery: - nursery.start_soon(self._worker) - self._run_done.set() - - async def make_stream(self, timeout=None): - if timeout is None: - context = NullContext(None) - else: - context = trio.move_on_after(timeout) - with context: - await self._handshake_complete.wait() - if self._done: - raise UnexpectedEOF - stream_id = self._connection.get_next_available_stream_id(False) - stream = TrioQuicStream(self, stream_id) - self._streams[stream_id] = stream - return stream - raise dns.exception.Timeout - - async def close(self): - if not self._closed: - self._manager.closed(self._peer[0], self._peer[1]) - self._closed = True - self._connection.close() - self._send_pending = True - if self._worker_scope is not None: - self._worker_scope.cancel() - await self._run_done.wait() - - -class TrioQuicManager(AsyncQuicManager): - def __init__( - self, - nursery, - conf=None, - verify_mode=ssl.CERT_REQUIRED, - server_name=None, - h3=False, - ): - super().__init__(conf, verify_mode, TrioQuicConnection, server_name, h3) - self._nursery = nursery - - def connect( - self, address, port=853, source=None, source_port=0, want_session_ticket=True - ): - (connection, start) = self._connect( - address, port, source, source_port, want_session_ticket - ) - if start: - self._nursery.start_soon(connection.run) - return connection - - async def __aenter__(self): - return self - - async def __aexit__(self, exc_type, exc_val, exc_tb): - # Copy the iterator into a list as exiting things will mutate the connections - # table. - connections = list(self._connections.values()) - for connection in connections: - await connection.close() - return False diff --git a/venv/Lib/site-packages/dns/rcode.py b/venv/Lib/site-packages/dns/rcode.py deleted file mode 100644 index 8e6386f..0000000 --- a/venv/Lib/site-packages/dns/rcode.py +++ /dev/null @@ -1,168 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Result Codes.""" - -from typing import Tuple - -import dns.enum -import dns.exception - - -class Rcode(dns.enum.IntEnum): - #: No error - NOERROR = 0 - #: Format error - FORMERR = 1 - #: Server failure - SERVFAIL = 2 - #: Name does not exist ("Name Error" in RFC 1025 terminology). - NXDOMAIN = 3 - #: Not implemented - NOTIMP = 4 - #: Refused - REFUSED = 5 - #: Name exists. - YXDOMAIN = 6 - #: RRset exists. - YXRRSET = 7 - #: RRset does not exist. - NXRRSET = 8 - #: Not authoritative. - NOTAUTH = 9 - #: Name not in zone. - NOTZONE = 10 - #: DSO-TYPE Not Implemented - DSOTYPENI = 11 - #: Bad EDNS version. - BADVERS = 16 - #: TSIG Signature Failure - BADSIG = 16 - #: Key not recognized. - BADKEY = 17 - #: Signature out of time window. - BADTIME = 18 - #: Bad TKEY Mode. - BADMODE = 19 - #: Duplicate key name. - BADNAME = 20 - #: Algorithm not supported. - BADALG = 21 - #: Bad Truncation - BADTRUNC = 22 - #: Bad/missing Server Cookie - BADCOOKIE = 23 - - @classmethod - def _maximum(cls): - return 4095 - - @classmethod - def _unknown_exception_class(cls): - return UnknownRcode - - -class UnknownRcode(dns.exception.DNSException): - """A DNS rcode is unknown.""" - - -def from_text(text: str) -> Rcode: - """Convert text into an rcode. - - *text*, a ``str``, the textual rcode or an integer in textual form. - - Raises ``dns.rcode.UnknownRcode`` if the rcode mnemonic is unknown. - - Returns a ``dns.rcode.Rcode``. - """ - - return Rcode.from_text(text) - - -def from_flags(flags: int, ednsflags: int) -> Rcode: - """Return the rcode value encoded by flags and ednsflags. - - *flags*, an ``int``, the DNS flags field. - - *ednsflags*, an ``int``, the EDNS flags field. - - Raises ``ValueError`` if rcode is < 0 or > 4095 - - Returns a ``dns.rcode.Rcode``. - """ - - value = (flags & 0x000F) | ((ednsflags >> 20) & 0xFF0) - return Rcode.make(value) - - -def to_flags(value: Rcode) -> Tuple[int, int]: - """Return a (flags, ednsflags) tuple which encodes the rcode. - - *value*, a ``dns.rcode.Rcode``, the rcode. - - Raises ``ValueError`` if rcode is < 0 or > 4095. - - Returns an ``(int, int)`` tuple. - """ - - if value < 0 or value > 4095: - raise ValueError("rcode must be >= 0 and <= 4095") - v = value & 0xF - ev = (value & 0xFF0) << 20 - return (v, ev) - - -def to_text(value: Rcode, tsig: bool = False) -> str: - """Convert rcode into text. - - *value*, a ``dns.rcode.Rcode``, the rcode. - - Raises ``ValueError`` if rcode is < 0 or > 4095. - - Returns a ``str``. - """ - - if tsig and value == Rcode.BADVERS: - return "BADSIG" - return Rcode.to_text(value) - - -### BEGIN generated Rcode constants - -NOERROR = Rcode.NOERROR -FORMERR = Rcode.FORMERR -SERVFAIL = Rcode.SERVFAIL -NXDOMAIN = Rcode.NXDOMAIN -NOTIMP = Rcode.NOTIMP -REFUSED = Rcode.REFUSED -YXDOMAIN = Rcode.YXDOMAIN -YXRRSET = Rcode.YXRRSET -NXRRSET = Rcode.NXRRSET -NOTAUTH = Rcode.NOTAUTH -NOTZONE = Rcode.NOTZONE -DSOTYPENI = Rcode.DSOTYPENI -BADVERS = Rcode.BADVERS -BADSIG = Rcode.BADSIG -BADKEY = Rcode.BADKEY -BADTIME = Rcode.BADTIME -BADMODE = Rcode.BADMODE -BADNAME = Rcode.BADNAME -BADALG = Rcode.BADALG -BADTRUNC = Rcode.BADTRUNC -BADCOOKIE = Rcode.BADCOOKIE - -### END generated Rcode constants diff --git a/venv/Lib/site-packages/dns/rdata.py b/venv/Lib/site-packages/dns/rdata.py deleted file mode 100644 index 8099c26..0000000 --- a/venv/Lib/site-packages/dns/rdata.py +++ /dev/null @@ -1,911 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS rdata.""" - -import base64 -import binascii -import inspect -import io -import itertools -import random -from importlib import import_module -from typing import Any, Dict, Optional, Tuple, Union - -import dns.exception -import dns.immutable -import dns.ipv4 -import dns.ipv6 -import dns.name -import dns.rdataclass -import dns.rdatatype -import dns.tokenizer -import dns.ttl -import dns.wire - -_chunksize = 32 - -# We currently allow comparisons for rdata with relative names for backwards -# compatibility, but in the future we will not, as these kinds of comparisons -# can lead to subtle bugs if code is not carefully written. -# -# This switch allows the future behavior to be turned on so code can be -# tested with it. -_allow_relative_comparisons = True - - -class NoRelativeRdataOrdering(dns.exception.DNSException): - """An attempt was made to do an ordered comparison of one or more - rdata with relative names. The only reliable way of sorting rdata - is to use non-relativized rdata. - - """ - - -def _wordbreak(data, chunksize=_chunksize, separator=b" "): - """Break a binary string into chunks of chunksize characters separated by - a space. - """ - - if not chunksize: - return data.decode() - return separator.join( - [data[i : i + chunksize] for i in range(0, len(data), chunksize)] - ).decode() - - -# pylint: disable=unused-argument - - -def _hexify(data, chunksize=_chunksize, separator=b" ", **kw): - """Convert a binary string into its hex encoding, broken up into chunks - of chunksize characters separated by a separator. - """ - - return _wordbreak(binascii.hexlify(data), chunksize, separator) - - -def _base64ify(data, chunksize=_chunksize, separator=b" ", **kw): - """Convert a binary string into its base64 encoding, broken up into chunks - of chunksize characters separated by a separator. - """ - - return _wordbreak(base64.b64encode(data), chunksize, separator) - - -# pylint: enable=unused-argument - -__escaped = b'"\\' - - -def _escapify(qstring): - """Escape the characters in a quoted string which need it.""" - - if isinstance(qstring, str): - qstring = qstring.encode() - if not isinstance(qstring, bytearray): - qstring = bytearray(qstring) - - text = "" - for c in qstring: - if c in __escaped: - text += "\\" + chr(c) - elif c >= 0x20 and c < 0x7F: - text += chr(c) - else: - text += "\\%03d" % c - return text - - -def _truncate_bitmap(what): - """Determine the index of greatest byte that isn't all zeros, and - return the bitmap that contains all the bytes less than that index. - """ - - for i in range(len(what) - 1, -1, -1): - if what[i] != 0: - return what[0 : i + 1] - return what[0:1] - - -# So we don't have to edit all the rdata classes... -_constify = dns.immutable.constify - - -@dns.immutable.immutable -class Rdata: - """Base class for all DNS rdata types.""" - - __slots__ = ["rdclass", "rdtype", "rdcomment"] - - def __init__(self, rdclass, rdtype): - """Initialize an rdata. - - *rdclass*, an ``int`` is the rdataclass of the Rdata. - - *rdtype*, an ``int`` is the rdatatype of the Rdata. - """ - - self.rdclass = self._as_rdataclass(rdclass) - self.rdtype = self._as_rdatatype(rdtype) - self.rdcomment = None - - def _get_all_slots(self): - return itertools.chain.from_iterable( - getattr(cls, "__slots__", []) for cls in self.__class__.__mro__ - ) - - def __getstate__(self): - # We used to try to do a tuple of all slots here, but it - # doesn't work as self._all_slots isn't available at - # __setstate__() time. Before that we tried to store a tuple - # of __slots__, but that didn't work as it didn't store the - # slots defined by ancestors. This older way didn't fail - # outright, but ended up with partially broken objects, e.g. - # if you unpickled an A RR it wouldn't have rdclass and rdtype - # attributes, and would compare badly. - state = {} - for slot in self._get_all_slots(): - state[slot] = getattr(self, slot) - return state - - def __setstate__(self, state): - for slot, val in state.items(): - object.__setattr__(self, slot, val) - if not hasattr(self, "rdcomment"): - # Pickled rdata from 2.0.x might not have a rdcomment, so add - # it if needed. - object.__setattr__(self, "rdcomment", None) - - def covers(self) -> dns.rdatatype.RdataType: - """Return the type a Rdata covers. - - DNS SIG/RRSIG rdatas apply to a specific type; this type is - returned by the covers() function. If the rdata type is not - SIG or RRSIG, dns.rdatatype.NONE is returned. This is useful when - creating rdatasets, allowing the rdataset to contain only RRSIGs - of a particular type, e.g. RRSIG(NS). - - Returns a ``dns.rdatatype.RdataType``. - """ - - return dns.rdatatype.NONE - - def extended_rdatatype(self) -> int: - """Return a 32-bit type value, the least significant 16 bits of - which are the ordinary DNS type, and the upper 16 bits of which are - the "covered" type, if any. - - Returns an ``int``. - """ - - return self.covers() << 16 | self.rdtype - - def to_text( - self, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - **kw: Dict[str, Any], - ) -> str: - """Convert an rdata to text format. - - Returns a ``str``. - """ - - raise NotImplementedError # pragma: no cover - - def _to_wire( - self, - file: Optional[Any], - compress: Optional[dns.name.CompressType] = None, - origin: Optional[dns.name.Name] = None, - canonicalize: bool = False, - ) -> None: - raise NotImplementedError # pragma: no cover - - def to_wire( - self, - file: Optional[Any] = None, - compress: Optional[dns.name.CompressType] = None, - origin: Optional[dns.name.Name] = None, - canonicalize: bool = False, - ) -> Optional[bytes]: - """Convert an rdata to wire format. - - Returns a ``bytes`` if no output file was specified, or ``None`` otherwise. - """ - - if file: - # We call _to_wire() and then return None explicitly instead of - # of just returning the None from _to_wire() as mypy's func-returns-value - # unhelpfully errors out with "error: "_to_wire" of "Rdata" does not return - # a value (it only ever returns None)" - self._to_wire(file, compress, origin, canonicalize) - return None - else: - f = io.BytesIO() - self._to_wire(f, compress, origin, canonicalize) - return f.getvalue() - - def to_generic( - self, origin: Optional[dns.name.Name] = None - ) -> "dns.rdata.GenericRdata": - """Creates a dns.rdata.GenericRdata equivalent of this rdata. - - Returns a ``dns.rdata.GenericRdata``. - """ - return dns.rdata.GenericRdata( - self.rdclass, self.rdtype, self.to_wire(origin=origin) - ) - - def to_digestable(self, origin: Optional[dns.name.Name] = None) -> bytes: - """Convert rdata to a format suitable for digesting in hashes. This - is also the DNSSEC canonical form. - - Returns a ``bytes``. - """ - wire = self.to_wire(origin=origin, canonicalize=True) - assert wire is not None # for mypy - return wire - - def __repr__(self): - covers = self.covers() - if covers == dns.rdatatype.NONE: - ctext = "" - else: - ctext = "(" + dns.rdatatype.to_text(covers) + ")" - return ( - "" - ) - - def __str__(self): - return self.to_text() - - def _cmp(self, other): - """Compare an rdata with another rdata of the same rdtype and - rdclass. - - For rdata with only absolute names: - Return < 0 if self < other in the DNSSEC ordering, 0 if self - == other, and > 0 if self > other. - For rdata with at least one relative names: - The rdata sorts before any rdata with only absolute names. - When compared with another relative rdata, all names are - made absolute as if they were relative to the root, as the - proper origin is not available. While this creates a stable - ordering, it is NOT guaranteed to be the DNSSEC ordering. - In the future, all ordering comparisons for rdata with - relative names will be disallowed. - """ - try: - our = self.to_digestable() - our_relative = False - except dns.name.NeedAbsoluteNameOrOrigin: - if _allow_relative_comparisons: - our = self.to_digestable(dns.name.root) - our_relative = True - try: - their = other.to_digestable() - their_relative = False - except dns.name.NeedAbsoluteNameOrOrigin: - if _allow_relative_comparisons: - their = other.to_digestable(dns.name.root) - their_relative = True - if _allow_relative_comparisons: - if our_relative != their_relative: - # For the purpose of comparison, all rdata with at least one - # relative name is less than an rdata with only absolute names. - if our_relative: - return -1 - else: - return 1 - elif our_relative or their_relative: - raise NoRelativeRdataOrdering - if our == their: - return 0 - elif our > their: - return 1 - else: - return -1 - - def __eq__(self, other): - if not isinstance(other, Rdata): - return False - if self.rdclass != other.rdclass or self.rdtype != other.rdtype: - return False - our_relative = False - their_relative = False - try: - our = self.to_digestable() - except dns.name.NeedAbsoluteNameOrOrigin: - our = self.to_digestable(dns.name.root) - our_relative = True - try: - their = other.to_digestable() - except dns.name.NeedAbsoluteNameOrOrigin: - their = other.to_digestable(dns.name.root) - their_relative = True - if our_relative != their_relative: - return False - return our == their - - def __ne__(self, other): - if not isinstance(other, Rdata): - return True - if self.rdclass != other.rdclass or self.rdtype != other.rdtype: - return True - return not self.__eq__(other) - - def __lt__(self, other): - if ( - not isinstance(other, Rdata) - or self.rdclass != other.rdclass - or self.rdtype != other.rdtype - ): - return NotImplemented - return self._cmp(other) < 0 - - def __le__(self, other): - if ( - not isinstance(other, Rdata) - or self.rdclass != other.rdclass - or self.rdtype != other.rdtype - ): - return NotImplemented - return self._cmp(other) <= 0 - - def __ge__(self, other): - if ( - not isinstance(other, Rdata) - or self.rdclass != other.rdclass - or self.rdtype != other.rdtype - ): - return NotImplemented - return self._cmp(other) >= 0 - - def __gt__(self, other): - if ( - not isinstance(other, Rdata) - or self.rdclass != other.rdclass - or self.rdtype != other.rdtype - ): - return NotImplemented - return self._cmp(other) > 0 - - def __hash__(self): - return hash(self.to_digestable(dns.name.root)) - - @classmethod - def from_text( - cls, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - tok: dns.tokenizer.Tokenizer, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - relativize_to: Optional[dns.name.Name] = None, - ) -> "Rdata": - raise NotImplementedError # pragma: no cover - - @classmethod - def from_wire_parser( - cls, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - parser: dns.wire.Parser, - origin: Optional[dns.name.Name] = None, - ) -> "Rdata": - raise NotImplementedError # pragma: no cover - - def replace(self, **kwargs: Any) -> "Rdata": - """ - Create a new Rdata instance based on the instance replace was - invoked on. It is possible to pass different parameters to - override the corresponding properties of the base Rdata. - - Any field specific to the Rdata type can be replaced, but the - *rdtype* and *rdclass* fields cannot. - - Returns an instance of the same Rdata subclass as *self*. - """ - - # Get the constructor parameters. - parameters = inspect.signature(self.__init__).parameters # type: ignore - - # Ensure that all of the arguments correspond to valid fields. - # Don't allow rdclass or rdtype to be changed, though. - for key in kwargs: - if key == "rdcomment": - continue - if key not in parameters: - raise AttributeError( - f"'{self.__class__.__name__}' object has no attribute '{key}'" - ) - if key in ("rdclass", "rdtype"): - raise AttributeError( - f"Cannot overwrite '{self.__class__.__name__}' attribute '{key}'" - ) - - # Construct the parameter list. For each field, use the value in - # kwargs if present, and the current value otherwise. - args = (kwargs.get(key, getattr(self, key)) for key in parameters) - - # Create, validate, and return the new object. - rd = self.__class__(*args) - # The comment is not set in the constructor, so give it special - # handling. - rdcomment = kwargs.get("rdcomment", self.rdcomment) - if rdcomment is not None: - object.__setattr__(rd, "rdcomment", rdcomment) - return rd - - # Type checking and conversion helpers. These are class methods as - # they don't touch object state and may be useful to others. - - @classmethod - def _as_rdataclass(cls, value): - return dns.rdataclass.RdataClass.make(value) - - @classmethod - def _as_rdatatype(cls, value): - return dns.rdatatype.RdataType.make(value) - - @classmethod - def _as_bytes( - cls, - value: Any, - encode: bool = False, - max_length: Optional[int] = None, - empty_ok: bool = True, - ) -> bytes: - if encode and isinstance(value, str): - bvalue = value.encode() - elif isinstance(value, bytearray): - bvalue = bytes(value) - elif isinstance(value, bytes): - bvalue = value - else: - raise ValueError("not bytes") - if max_length is not None and len(bvalue) > max_length: - raise ValueError("too long") - if not empty_ok and len(bvalue) == 0: - raise ValueError("empty bytes not allowed") - return bvalue - - @classmethod - def _as_name(cls, value): - # Note that proper name conversion (e.g. with origin and IDNA - # awareness) is expected to be done via from_text. This is just - # a simple thing for people invoking the constructor directly. - if isinstance(value, str): - return dns.name.from_text(value) - elif not isinstance(value, dns.name.Name): - raise ValueError("not a name") - return value - - @classmethod - def _as_uint8(cls, value): - if not isinstance(value, int): - raise ValueError("not an integer") - if value < 0 or value > 255: - raise ValueError("not a uint8") - return value - - @classmethod - def _as_uint16(cls, value): - if not isinstance(value, int): - raise ValueError("not an integer") - if value < 0 or value > 65535: - raise ValueError("not a uint16") - return value - - @classmethod - def _as_uint32(cls, value): - if not isinstance(value, int): - raise ValueError("not an integer") - if value < 0 or value > 4294967295: - raise ValueError("not a uint32") - return value - - @classmethod - def _as_uint48(cls, value): - if not isinstance(value, int): - raise ValueError("not an integer") - if value < 0 or value > 281474976710655: - raise ValueError("not a uint48") - return value - - @classmethod - def _as_int(cls, value, low=None, high=None): - if not isinstance(value, int): - raise ValueError("not an integer") - if low is not None and value < low: - raise ValueError("value too small") - if high is not None and value > high: - raise ValueError("value too large") - return value - - @classmethod - def _as_ipv4_address(cls, value): - if isinstance(value, str): - return dns.ipv4.canonicalize(value) - elif isinstance(value, bytes): - return dns.ipv4.inet_ntoa(value) - else: - raise ValueError("not an IPv4 address") - - @classmethod - def _as_ipv6_address(cls, value): - if isinstance(value, str): - return dns.ipv6.canonicalize(value) - elif isinstance(value, bytes): - return dns.ipv6.inet_ntoa(value) - else: - raise ValueError("not an IPv6 address") - - @classmethod - def _as_bool(cls, value): - if isinstance(value, bool): - return value - else: - raise ValueError("not a boolean") - - @classmethod - def _as_ttl(cls, value): - if isinstance(value, int): - return cls._as_int(value, 0, dns.ttl.MAX_TTL) - elif isinstance(value, str): - return dns.ttl.from_text(value) - else: - raise ValueError("not a TTL") - - @classmethod - def _as_tuple(cls, value, as_value): - try: - # For user convenience, if value is a singleton of the list - # element type, wrap it in a tuple. - return (as_value(value),) - except Exception: - # Otherwise, check each element of the iterable *value* - # against *as_value*. - return tuple(as_value(v) for v in value) - - # Processing order - - @classmethod - def _processing_order(cls, iterable): - items = list(iterable) - random.shuffle(items) - return items - - -@dns.immutable.immutable -class GenericRdata(Rdata): - """Generic Rdata Class - - This class is used for rdata types for which we have no better - implementation. It implements the DNS "unknown RRs" scheme. - """ - - __slots__ = ["data"] - - def __init__(self, rdclass, rdtype, data): - super().__init__(rdclass, rdtype) - self.data = data - - def to_text( - self, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - **kw: Dict[str, Any], - ) -> str: - return r"\# %d " % len(self.data) + _hexify(self.data, **kw) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - token = tok.get() - if not token.is_identifier() or token.value != r"\#": - raise dns.exception.SyntaxError(r"generic rdata does not start with \#") - length = tok.get_int() - hex = tok.concatenate_remaining_identifiers(True).encode() - data = binascii.unhexlify(hex) - if len(data) != length: - raise dns.exception.SyntaxError("generic rdata hex data has wrong length") - return cls(rdclass, rdtype, data) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(self.data) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - return cls(rdclass, rdtype, parser.get_remaining()) - - -_rdata_classes: Dict[Tuple[dns.rdataclass.RdataClass, dns.rdatatype.RdataType], Any] = ( - {} -) -_module_prefix = "dns.rdtypes" -_dynamic_load_allowed = True - - -def get_rdata_class(rdclass, rdtype, use_generic=True): - cls = _rdata_classes.get((rdclass, rdtype)) - if not cls: - cls = _rdata_classes.get((dns.rdatatype.ANY, rdtype)) - if not cls and _dynamic_load_allowed: - rdclass_text = dns.rdataclass.to_text(rdclass) - rdtype_text = dns.rdatatype.to_text(rdtype) - rdtype_text = rdtype_text.replace("-", "_") - try: - mod = import_module( - ".".join([_module_prefix, rdclass_text, rdtype_text]) - ) - cls = getattr(mod, rdtype_text) - _rdata_classes[(rdclass, rdtype)] = cls - except ImportError: - try: - mod = import_module(".".join([_module_prefix, "ANY", rdtype_text])) - cls = getattr(mod, rdtype_text) - _rdata_classes[(dns.rdataclass.ANY, rdtype)] = cls - _rdata_classes[(rdclass, rdtype)] = cls - except ImportError: - pass - if not cls and use_generic: - cls = GenericRdata - _rdata_classes[(rdclass, rdtype)] = cls - return cls - - -def load_all_types(disable_dynamic_load=True): - """Load all rdata types for which dnspython has a non-generic implementation. - - Normally dnspython loads DNS rdatatype implementations on demand, but in some - specialized cases loading all types at an application-controlled time is preferred. - - If *disable_dynamic_load*, a ``bool``, is ``True`` then dnspython will not attempt - to use its dynamic loading mechanism if an unknown type is subsequently encountered, - and will simply use the ``GenericRdata`` class. - """ - # Load class IN and ANY types. - for rdtype in dns.rdatatype.RdataType: - get_rdata_class(dns.rdataclass.IN, rdtype, False) - # Load the one non-ANY implementation we have in CH. Everything - # else in CH is an ANY type, and we'll discover those on demand but won't - # have to import anything. - get_rdata_class(dns.rdataclass.CH, dns.rdatatype.A, False) - if disable_dynamic_load: - # Now disable dynamic loading so any subsequent unknown type immediately becomes - # GenericRdata without a load attempt. - global _dynamic_load_allowed - _dynamic_load_allowed = False - - -def from_text( - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - tok: Union[dns.tokenizer.Tokenizer, str], - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - relativize_to: Optional[dns.name.Name] = None, - idna_codec: Optional[dns.name.IDNACodec] = None, -) -> Rdata: - """Build an rdata object from text format. - - This function attempts to dynamically load a class which - implements the specified rdata class and type. If there is no - class-and-type-specific implementation, the GenericRdata class - is used. - - Once a class is chosen, its from_text() class method is called - with the parameters to this function. - - If *tok* is a ``str``, then a tokenizer is created and the string - is used as its input. - - *rdclass*, a ``dns.rdataclass.RdataClass`` or ``str``, the rdataclass. - - *rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdatatype. - - *tok*, a ``dns.tokenizer.Tokenizer`` or a ``str``. - - *origin*, a ``dns.name.Name`` (or ``None``), the - origin to use for relative names. - - *relativize*, a ``bool``. If true, name will be relativized. - - *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use - when relativizing names. If not set, the *origin* value will be used. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder to use if a tokenizer needs to be created. If - ``None``, the default IDNA 2003 encoder/decoder is used. If a - tokenizer is not created, then the codec associated with the tokenizer - is the one that is used. - - Returns an instance of the chosen Rdata subclass. - - """ - if isinstance(tok, str): - tok = dns.tokenizer.Tokenizer(tok, idna_codec=idna_codec) - rdclass = dns.rdataclass.RdataClass.make(rdclass) - rdtype = dns.rdatatype.RdataType.make(rdtype) - cls = get_rdata_class(rdclass, rdtype) - with dns.exception.ExceptionWrapper(dns.exception.SyntaxError): - rdata = None - if cls != GenericRdata: - # peek at first token - token = tok.get() - tok.unget(token) - if token.is_identifier() and token.value == r"\#": - # - # Known type using the generic syntax. Extract the - # wire form from the generic syntax, and then run - # from_wire on it. - # - grdata = GenericRdata.from_text( - rdclass, rdtype, tok, origin, relativize, relativize_to - ) - rdata = from_wire( - rdclass, rdtype, grdata.data, 0, len(grdata.data), origin - ) - # - # If this comparison isn't equal, then there must have been - # compressed names in the wire format, which is an error, - # there being no reasonable context to decompress with. - # - rwire = rdata.to_wire() - if rwire != grdata.data: - raise dns.exception.SyntaxError( - "compressed data in " - "generic syntax form " - "of known rdatatype" - ) - if rdata is None: - rdata = cls.from_text( - rdclass, rdtype, tok, origin, relativize, relativize_to - ) - token = tok.get_eol_as_token() - if token.comment is not None: - object.__setattr__(rdata, "rdcomment", token.comment) - return rdata - - -def from_wire_parser( - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - parser: dns.wire.Parser, - origin: Optional[dns.name.Name] = None, -) -> Rdata: - """Build an rdata object from wire format - - This function attempts to dynamically load a class which - implements the specified rdata class and type. If there is no - class-and-type-specific implementation, the GenericRdata class - is used. - - Once a class is chosen, its from_wire() class method is called - with the parameters to this function. - - *rdclass*, a ``dns.rdataclass.RdataClass`` or ``str``, the rdataclass. - - *rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdatatype. - - *parser*, a ``dns.wire.Parser``, the parser, which should be - restricted to the rdata length. - - *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, - then names will be relativized to this origin. - - Returns an instance of the chosen Rdata subclass. - """ - - rdclass = dns.rdataclass.RdataClass.make(rdclass) - rdtype = dns.rdatatype.RdataType.make(rdtype) - cls = get_rdata_class(rdclass, rdtype) - with dns.exception.ExceptionWrapper(dns.exception.FormError): - return cls.from_wire_parser(rdclass, rdtype, parser, origin) - - -def from_wire( - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - wire: bytes, - current: int, - rdlen: int, - origin: Optional[dns.name.Name] = None, -) -> Rdata: - """Build an rdata object from wire format - - This function attempts to dynamically load a class which - implements the specified rdata class and type. If there is no - class-and-type-specific implementation, the GenericRdata class - is used. - - Once a class is chosen, its from_wire() class method is called - with the parameters to this function. - - *rdclass*, an ``int``, the rdataclass. - - *rdtype*, an ``int``, the rdatatype. - - *wire*, a ``bytes``, the wire-format message. - - *current*, an ``int``, the offset in wire of the beginning of - the rdata. - - *rdlen*, an ``int``, the length of the wire-format rdata - - *origin*, a ``dns.name.Name`` (or ``None``). If not ``None``, - then names will be relativized to this origin. - - Returns an instance of the chosen Rdata subclass. - """ - parser = dns.wire.Parser(wire, current) - with parser.restrict_to(rdlen): - return from_wire_parser(rdclass, rdtype, parser, origin) - - -class RdatatypeExists(dns.exception.DNSException): - """DNS rdatatype already exists.""" - - supp_kwargs = {"rdclass", "rdtype"} - fmt = ( - "The rdata type with class {rdclass:d} and rdtype {rdtype:d} " - + "already exists." - ) - - -def register_type( - implementation: Any, - rdtype: int, - rdtype_text: str, - is_singleton: bool = False, - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, -) -> None: - """Dynamically register a module to handle an rdatatype. - - *implementation*, a module implementing the type in the usual dnspython - way. - - *rdtype*, an ``int``, the rdatatype to register. - - *rdtype_text*, a ``str``, the textual form of the rdatatype. - - *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. - RRsets of the type can have only one member.) - - *rdclass*, the rdataclass of the type, or ``dns.rdataclass.ANY`` if - it applies to all classes. - """ - - rdtype = dns.rdatatype.RdataType.make(rdtype) - existing_cls = get_rdata_class(rdclass, rdtype) - if existing_cls != GenericRdata or dns.rdatatype.is_metatype(rdtype): - raise RdatatypeExists(rdclass=rdclass, rdtype=rdtype) - _rdata_classes[(rdclass, rdtype)] = getattr( - implementation, rdtype_text.replace("-", "_") - ) - dns.rdatatype.register_type(rdtype, rdtype_text, is_singleton) diff --git a/venv/Lib/site-packages/dns/rdataclass.py b/venv/Lib/site-packages/dns/rdataclass.py deleted file mode 100644 index 89b85a7..0000000 --- a/venv/Lib/site-packages/dns/rdataclass.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Rdata Classes.""" - -import dns.enum -import dns.exception - - -class RdataClass(dns.enum.IntEnum): - """DNS Rdata Class""" - - RESERVED0 = 0 - IN = 1 - INTERNET = IN - CH = 3 - CHAOS = CH - HS = 4 - HESIOD = HS - NONE = 254 - ANY = 255 - - @classmethod - def _maximum(cls): - return 65535 - - @classmethod - def _short_name(cls): - return "class" - - @classmethod - def _prefix(cls): - return "CLASS" - - @classmethod - def _unknown_exception_class(cls): - return UnknownRdataclass - - -_metaclasses = {RdataClass.NONE, RdataClass.ANY} - - -class UnknownRdataclass(dns.exception.DNSException): - """A DNS class is unknown.""" - - -def from_text(text: str) -> RdataClass: - """Convert text into a DNS rdata class value. - - The input text can be a defined DNS RR class mnemonic or - instance of the DNS generic class syntax. - - For example, "IN" and "CLASS1" will both result in a value of 1. - - Raises ``dns.rdatatype.UnknownRdataclass`` if the class is unknown. - - Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. - - Returns a ``dns.rdataclass.RdataClass``. - """ - - return RdataClass.from_text(text) - - -def to_text(value: RdataClass) -> str: - """Convert a DNS rdata class value to text. - - If the value has a known mnemonic, it will be used, otherwise the - DNS generic class syntax will be used. - - Raises ``ValueError`` if the rdata class value is not >= 0 and <= 65535. - - Returns a ``str``. - """ - - return RdataClass.to_text(value) - - -def is_metaclass(rdclass: RdataClass) -> bool: - """True if the specified class is a metaclass. - - The currently defined metaclasses are ANY and NONE. - - *rdclass* is a ``dns.rdataclass.RdataClass``. - """ - - if rdclass in _metaclasses: - return True - return False - - -### BEGIN generated RdataClass constants - -RESERVED0 = RdataClass.RESERVED0 -IN = RdataClass.IN -INTERNET = RdataClass.INTERNET -CH = RdataClass.CH -CHAOS = RdataClass.CHAOS -HS = RdataClass.HS -HESIOD = RdataClass.HESIOD -NONE = RdataClass.NONE -ANY = RdataClass.ANY - -### END generated RdataClass constants diff --git a/venv/Lib/site-packages/dns/rdataset.py b/venv/Lib/site-packages/dns/rdataset.py deleted file mode 100644 index 39cab23..0000000 --- a/venv/Lib/site-packages/dns/rdataset.py +++ /dev/null @@ -1,512 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS rdatasets (an rdataset is a set of rdatas of a given type and class)""" - -import io -import random -import struct -from typing import Any, Collection, Dict, List, Optional, Union, cast - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdataclass -import dns.rdatatype -import dns.renderer -import dns.set -import dns.ttl - -# define SimpleSet here for backwards compatibility -SimpleSet = dns.set.Set - - -class DifferingCovers(dns.exception.DNSException): - """An attempt was made to add a DNS SIG/RRSIG whose covered type - is not the same as that of the other rdatas in the rdataset.""" - - -class IncompatibleTypes(dns.exception.DNSException): - """An attempt was made to add DNS RR data of an incompatible type.""" - - -class Rdataset(dns.set.Set): - """A DNS rdataset.""" - - __slots__ = ["rdclass", "rdtype", "covers", "ttl"] - - def __init__( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - ttl: int = 0, - ): - """Create a new rdataset of the specified class and type. - - *rdclass*, a ``dns.rdataclass.RdataClass``, the rdataclass. - - *rdtype*, an ``dns.rdatatype.RdataType``, the rdatatype. - - *covers*, an ``dns.rdatatype.RdataType``, the covered rdatatype. - - *ttl*, an ``int``, the TTL. - """ - - super().__init__() - self.rdclass = rdclass - self.rdtype: dns.rdatatype.RdataType = rdtype - self.covers: dns.rdatatype.RdataType = covers - self.ttl = ttl - - def _clone(self): - obj = super()._clone() - obj.rdclass = self.rdclass - obj.rdtype = self.rdtype - obj.covers = self.covers - obj.ttl = self.ttl - return obj - - def update_ttl(self, ttl: int) -> None: - """Perform TTL minimization. - - Set the TTL of the rdataset to be the lesser of the set's current - TTL or the specified TTL. If the set contains no rdatas, set the TTL - to the specified TTL. - - *ttl*, an ``int`` or ``str``. - """ - ttl = dns.ttl.make(ttl) - if len(self) == 0: - self.ttl = ttl - elif ttl < self.ttl: - self.ttl = ttl - - def add( # pylint: disable=arguments-differ,arguments-renamed - self, rd: dns.rdata.Rdata, ttl: Optional[int] = None - ) -> None: - """Add the specified rdata to the rdataset. - - If the optional *ttl* parameter is supplied, then - ``self.update_ttl(ttl)`` will be called prior to adding the rdata. - - *rd*, a ``dns.rdata.Rdata``, the rdata - - *ttl*, an ``int``, the TTL. - - Raises ``dns.rdataset.IncompatibleTypes`` if the type and class - do not match the type and class of the rdataset. - - Raises ``dns.rdataset.DifferingCovers`` if the type is a signature - type and the covered type does not match that of the rdataset. - """ - - # - # If we're adding a signature, do some special handling to - # check that the signature covers the same type as the - # other rdatas in this rdataset. If this is the first rdata - # in the set, initialize the covers field. - # - if self.rdclass != rd.rdclass or self.rdtype != rd.rdtype: - raise IncompatibleTypes - if ttl is not None: - self.update_ttl(ttl) - if self.rdtype == dns.rdatatype.RRSIG or self.rdtype == dns.rdatatype.SIG: - covers = rd.covers() - if len(self) == 0 and self.covers == dns.rdatatype.NONE: - self.covers = covers - elif self.covers != covers: - raise DifferingCovers - if dns.rdatatype.is_singleton(rd.rdtype) and len(self) > 0: - self.clear() - super().add(rd) - - def union_update(self, other): - self.update_ttl(other.ttl) - super().union_update(other) - - def intersection_update(self, other): - self.update_ttl(other.ttl) - super().intersection_update(other) - - def update(self, other): - """Add all rdatas in other to self. - - *other*, a ``dns.rdataset.Rdataset``, the rdataset from which - to update. - """ - - self.update_ttl(other.ttl) - super().update(other) - - def _rdata_repr(self): - def maybe_truncate(s): - if len(s) > 100: - return s[:100] + "..." - return s - - return "[" + ", ".join(f"<{maybe_truncate(str(rr))}>" for rr in self) + "]" - - def __repr__(self): - if self.covers == 0: - ctext = "" - else: - ctext = "(" + dns.rdatatype.to_text(self.covers) + ")" - return ( - "" - ) - - def __str__(self): - return self.to_text() - - def __eq__(self, other): - if not isinstance(other, Rdataset): - return False - if ( - self.rdclass != other.rdclass - or self.rdtype != other.rdtype - or self.covers != other.covers - ): - return False - return super().__eq__(other) - - def __ne__(self, other): - return not self.__eq__(other) - - def to_text( - self, - name: Optional[dns.name.Name] = None, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - override_rdclass: Optional[dns.rdataclass.RdataClass] = None, - want_comments: bool = False, - **kw: Dict[str, Any], - ) -> str: - """Convert the rdataset into DNS zone file format. - - See ``dns.name.Name.choose_relativity`` for more information - on how *origin* and *relativize* determine the way names - are emitted. - - Any additional keyword arguments are passed on to the rdata - ``to_text()`` method. - - *name*, a ``dns.name.Name``. If name is not ``None``, emit RRs with - *name* as the owner name. - - *origin*, a ``dns.name.Name`` or ``None``, the origin for relative - names. - - *relativize*, a ``bool``. If ``True``, names will be relativized - to *origin*. - - *override_rdclass*, a ``dns.rdataclass.RdataClass`` or ``None``. - If not ``None``, use this class instead of the Rdataset's class. - - *want_comments*, a ``bool``. If ``True``, emit comments for rdata - which have them. The default is ``False``. - """ - - if name is not None: - name = name.choose_relativity(origin, relativize) - ntext = str(name) - pad = " " - else: - ntext = "" - pad = "" - s = io.StringIO() - if override_rdclass is not None: - rdclass = override_rdclass - else: - rdclass = self.rdclass - if len(self) == 0: - # - # Empty rdatasets are used for the question section, and in - # some dynamic updates, so we don't need to print out the TTL - # (which is meaningless anyway). - # - s.write( - f"{ntext}{pad}{dns.rdataclass.to_text(rdclass)} " - f"{dns.rdatatype.to_text(self.rdtype)}\n" - ) - else: - for rd in self: - extra = "" - if want_comments: - if rd.rdcomment: - extra = f" ;{rd.rdcomment}" - s.write( - "%s%s%d %s %s %s%s\n" - % ( - ntext, - pad, - self.ttl, - dns.rdataclass.to_text(rdclass), - dns.rdatatype.to_text(self.rdtype), - rd.to_text(origin=origin, relativize=relativize, **kw), - extra, - ) - ) - # - # We strip off the final \n for the caller's convenience in printing - # - return s.getvalue()[:-1] - - def to_wire( - self, - name: dns.name.Name, - file: Any, - compress: Optional[dns.name.CompressType] = None, - origin: Optional[dns.name.Name] = None, - override_rdclass: Optional[dns.rdataclass.RdataClass] = None, - want_shuffle: bool = True, - ) -> int: - """Convert the rdataset to wire format. - - *name*, a ``dns.name.Name`` is the owner name to use. - - *file* is the file where the name is emitted (typically a - BytesIO file). - - *compress*, a ``dict``, is the compression table to use. If - ``None`` (the default), names will not be compressed. - - *origin* is a ``dns.name.Name`` or ``None``. If the name is - relative and origin is not ``None``, then *origin* will be appended - to it. - - *override_rdclass*, an ``int``, is used as the class instead of the - class of the rdataset. This is useful when rendering rdatasets - associated with dynamic updates. - - *want_shuffle*, a ``bool``. If ``True``, then the order of the - Rdatas within the Rdataset will be shuffled before rendering. - - Returns an ``int``, the number of records emitted. - """ - - if override_rdclass is not None: - rdclass = override_rdclass - want_shuffle = False - else: - rdclass = self.rdclass - if len(self) == 0: - name.to_wire(file, compress, origin) - file.write(struct.pack("!HHIH", self.rdtype, rdclass, 0, 0)) - return 1 - else: - l: Union[Rdataset, List[dns.rdata.Rdata]] - if want_shuffle: - l = list(self) - random.shuffle(l) - else: - l = self - for rd in l: - name.to_wire(file, compress, origin) - file.write(struct.pack("!HHI", self.rdtype, rdclass, self.ttl)) - with dns.renderer.prefixed_length(file, 2): - rd.to_wire(file, compress, origin) - return len(self) - - def match( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType, - ) -> bool: - """Returns ``True`` if this rdataset matches the specified class, - type, and covers. - """ - if self.rdclass == rdclass and self.rdtype == rdtype and self.covers == covers: - return True - return False - - def processing_order(self) -> List[dns.rdata.Rdata]: - """Return rdatas in a valid processing order according to the type's - specification. For example, MX records are in preference order from - lowest to highest preferences, with items of the same preference - shuffled. - - For types that do not define a processing order, the rdatas are - simply shuffled. - """ - if len(self) == 0: - return [] - else: - return self[0]._processing_order(iter(self)) - - -@dns.immutable.immutable -class ImmutableRdataset(Rdataset): # lgtm[py/missing-equals] - """An immutable DNS rdataset.""" - - _clone_class = Rdataset - - def __init__(self, rdataset: Rdataset): - """Create an immutable rdataset from the specified rdataset.""" - - super().__init__( - rdataset.rdclass, rdataset.rdtype, rdataset.covers, rdataset.ttl - ) - self.items = dns.immutable.Dict(rdataset.items) - - def update_ttl(self, ttl): - raise TypeError("immutable") - - def add(self, rd, ttl=None): - raise TypeError("immutable") - - def union_update(self, other): - raise TypeError("immutable") - - def intersection_update(self, other): - raise TypeError("immutable") - - def update(self, other): - raise TypeError("immutable") - - def __delitem__(self, i): - raise TypeError("immutable") - - # lgtm complains about these not raising ArithmeticError, but there is - # precedent for overrides of these methods in other classes to raise - # TypeError, and it seems like the better exception. - - def __ior__(self, other): # lgtm[py/unexpected-raise-in-special-method] - raise TypeError("immutable") - - def __iand__(self, other): # lgtm[py/unexpected-raise-in-special-method] - raise TypeError("immutable") - - def __iadd__(self, other): # lgtm[py/unexpected-raise-in-special-method] - raise TypeError("immutable") - - def __isub__(self, other): # lgtm[py/unexpected-raise-in-special-method] - raise TypeError("immutable") - - def clear(self): - raise TypeError("immutable") - - def __copy__(self): - return ImmutableRdataset(super().copy()) - - def copy(self): - return ImmutableRdataset(super().copy()) - - def union(self, other): - return ImmutableRdataset(super().union(other)) - - def intersection(self, other): - return ImmutableRdataset(super().intersection(other)) - - def difference(self, other): - return ImmutableRdataset(super().difference(other)) - - def symmetric_difference(self, other): - return ImmutableRdataset(super().symmetric_difference(other)) - - -def from_text_list( - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - ttl: int, - text_rdatas: Collection[str], - idna_codec: Optional[dns.name.IDNACodec] = None, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - relativize_to: Optional[dns.name.Name] = None, -) -> Rdataset: - """Create an rdataset with the specified class, type, and TTL, and with - the specified list of rdatas in text format. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder to use; if ``None``, the default IDNA 2003 - encoder/decoder is used. - - *origin*, a ``dns.name.Name`` (or ``None``), the - origin to use for relative names. - - *relativize*, a ``bool``. If true, name will be relativized. - - *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use - when relativizing names. If not set, the *origin* value will be used. - - Returns a ``dns.rdataset.Rdataset`` object. - """ - - rdclass = dns.rdataclass.RdataClass.make(rdclass) - rdtype = dns.rdatatype.RdataType.make(rdtype) - r = Rdataset(rdclass, rdtype) - r.update_ttl(ttl) - for t in text_rdatas: - rd = dns.rdata.from_text( - r.rdclass, r.rdtype, t, origin, relativize, relativize_to, idna_codec - ) - r.add(rd) - return r - - -def from_text( - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - ttl: int, - *text_rdatas: Any, -) -> Rdataset: - """Create an rdataset with the specified class, type, and TTL, and with - the specified rdatas in text format. - - Returns a ``dns.rdataset.Rdataset`` object. - """ - - return from_text_list(rdclass, rdtype, ttl, cast(Collection[str], text_rdatas)) - - -def from_rdata_list(ttl: int, rdatas: Collection[dns.rdata.Rdata]) -> Rdataset: - """Create an rdataset with the specified TTL, and with - the specified list of rdata objects. - - Returns a ``dns.rdataset.Rdataset`` object. - """ - - if len(rdatas) == 0: - raise ValueError("rdata list must not be empty") - r = None - for rd in rdatas: - if r is None: - r = Rdataset(rd.rdclass, rd.rdtype) - r.update_ttl(ttl) - r.add(rd) - assert r is not None - return r - - -def from_rdata(ttl: int, *rdatas: Any) -> Rdataset: - """Create an rdataset with the specified TTL, and with - the specified rdata objects. - - Returns a ``dns.rdataset.Rdataset`` object. - """ - - return from_rdata_list(ttl, cast(Collection[dns.rdata.Rdata], rdatas)) diff --git a/venv/Lib/site-packages/dns/rdatatype.py b/venv/Lib/site-packages/dns/rdatatype.py deleted file mode 100644 index aa9e561..0000000 --- a/venv/Lib/site-packages/dns/rdatatype.py +++ /dev/null @@ -1,336 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Rdata Types.""" - -from typing import Dict - -import dns.enum -import dns.exception - - -class RdataType(dns.enum.IntEnum): - """DNS Rdata Type""" - - TYPE0 = 0 - NONE = 0 - A = 1 - NS = 2 - MD = 3 - MF = 4 - CNAME = 5 - SOA = 6 - MB = 7 - MG = 8 - MR = 9 - NULL = 10 - WKS = 11 - PTR = 12 - HINFO = 13 - MINFO = 14 - MX = 15 - TXT = 16 - RP = 17 - AFSDB = 18 - X25 = 19 - ISDN = 20 - RT = 21 - NSAP = 22 - NSAP_PTR = 23 - SIG = 24 - KEY = 25 - PX = 26 - GPOS = 27 - AAAA = 28 - LOC = 29 - NXT = 30 - SRV = 33 - NAPTR = 35 - KX = 36 - CERT = 37 - A6 = 38 - DNAME = 39 - OPT = 41 - APL = 42 - DS = 43 - SSHFP = 44 - IPSECKEY = 45 - RRSIG = 46 - NSEC = 47 - DNSKEY = 48 - DHCID = 49 - NSEC3 = 50 - NSEC3PARAM = 51 - TLSA = 52 - SMIMEA = 53 - HIP = 55 - NINFO = 56 - CDS = 59 - CDNSKEY = 60 - OPENPGPKEY = 61 - CSYNC = 62 - ZONEMD = 63 - SVCB = 64 - HTTPS = 65 - SPF = 99 - UNSPEC = 103 - NID = 104 - L32 = 105 - L64 = 106 - LP = 107 - EUI48 = 108 - EUI64 = 109 - TKEY = 249 - TSIG = 250 - IXFR = 251 - AXFR = 252 - MAILB = 253 - MAILA = 254 - ANY = 255 - URI = 256 - CAA = 257 - AVC = 258 - AMTRELAY = 260 - RESINFO = 261 - WALLET = 262 - TA = 32768 - DLV = 32769 - - @classmethod - def _maximum(cls): - return 65535 - - @classmethod - def _short_name(cls): - return "type" - - @classmethod - def _prefix(cls): - return "TYPE" - - @classmethod - def _extra_from_text(cls, text): - if text.find("-") >= 0: - try: - return cls[text.replace("-", "_")] - except KeyError: # pragma: no cover - pass - return _registered_by_text.get(text) - - @classmethod - def _extra_to_text(cls, value, current_text): - if current_text is None: - return _registered_by_value.get(value) - if current_text.find("_") >= 0: - return current_text.replace("_", "-") - return current_text - - @classmethod - def _unknown_exception_class(cls): - return UnknownRdatatype - - -_registered_by_text: Dict[str, RdataType] = {} -_registered_by_value: Dict[RdataType, str] = {} - -_metatypes = {RdataType.OPT} - -_singletons = { - RdataType.SOA, - RdataType.NXT, - RdataType.DNAME, - RdataType.NSEC, - RdataType.CNAME, -} - - -class UnknownRdatatype(dns.exception.DNSException): - """DNS resource record type is unknown.""" - - -def from_text(text: str) -> RdataType: - """Convert text into a DNS rdata type value. - - The input text can be a defined DNS RR type mnemonic or - instance of the DNS generic type syntax. - - For example, "NS" and "TYPE2" will both result in a value of 2. - - Raises ``dns.rdatatype.UnknownRdatatype`` if the type is unknown. - - Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. - - Returns a ``dns.rdatatype.RdataType``. - """ - - return RdataType.from_text(text) - - -def to_text(value: RdataType) -> str: - """Convert a DNS rdata type value to text. - - If the value has a known mnemonic, it will be used, otherwise the - DNS generic type syntax will be used. - - Raises ``ValueError`` if the rdata type value is not >= 0 and <= 65535. - - Returns a ``str``. - """ - - return RdataType.to_text(value) - - -def is_metatype(rdtype: RdataType) -> bool: - """True if the specified type is a metatype. - - *rdtype* is a ``dns.rdatatype.RdataType``. - - The currently defined metatypes are TKEY, TSIG, IXFR, AXFR, MAILA, - MAILB, ANY, and OPT. - - Returns a ``bool``. - """ - - return (256 > rdtype >= 128) or rdtype in _metatypes - - -def is_singleton(rdtype: RdataType) -> bool: - """Is the specified type a singleton type? - - Singleton types can only have a single rdata in an rdataset, or a single - RR in an RRset. - - The currently defined singleton types are CNAME, DNAME, NSEC, NXT, and - SOA. - - *rdtype* is an ``int``. - - Returns a ``bool``. - """ - - if rdtype in _singletons: - return True - return False - - -# pylint: disable=redefined-outer-name -def register_type( - rdtype: RdataType, rdtype_text: str, is_singleton: bool = False -) -> None: - """Dynamically register an rdatatype. - - *rdtype*, a ``dns.rdatatype.RdataType``, the rdatatype to register. - - *rdtype_text*, a ``str``, the textual form of the rdatatype. - - *is_singleton*, a ``bool``, indicating if the type is a singleton (i.e. - RRsets of the type can have only one member.) - """ - - _registered_by_text[rdtype_text] = rdtype - _registered_by_value[rdtype] = rdtype_text - if is_singleton: - _singletons.add(rdtype) - - -### BEGIN generated RdataType constants - -TYPE0 = RdataType.TYPE0 -NONE = RdataType.NONE -A = RdataType.A -NS = RdataType.NS -MD = RdataType.MD -MF = RdataType.MF -CNAME = RdataType.CNAME -SOA = RdataType.SOA -MB = RdataType.MB -MG = RdataType.MG -MR = RdataType.MR -NULL = RdataType.NULL -WKS = RdataType.WKS -PTR = RdataType.PTR -HINFO = RdataType.HINFO -MINFO = RdataType.MINFO -MX = RdataType.MX -TXT = RdataType.TXT -RP = RdataType.RP -AFSDB = RdataType.AFSDB -X25 = RdataType.X25 -ISDN = RdataType.ISDN -RT = RdataType.RT -NSAP = RdataType.NSAP -NSAP_PTR = RdataType.NSAP_PTR -SIG = RdataType.SIG -KEY = RdataType.KEY -PX = RdataType.PX -GPOS = RdataType.GPOS -AAAA = RdataType.AAAA -LOC = RdataType.LOC -NXT = RdataType.NXT -SRV = RdataType.SRV -NAPTR = RdataType.NAPTR -KX = RdataType.KX -CERT = RdataType.CERT -A6 = RdataType.A6 -DNAME = RdataType.DNAME -OPT = RdataType.OPT -APL = RdataType.APL -DS = RdataType.DS -SSHFP = RdataType.SSHFP -IPSECKEY = RdataType.IPSECKEY -RRSIG = RdataType.RRSIG -NSEC = RdataType.NSEC -DNSKEY = RdataType.DNSKEY -DHCID = RdataType.DHCID -NSEC3 = RdataType.NSEC3 -NSEC3PARAM = RdataType.NSEC3PARAM -TLSA = RdataType.TLSA -SMIMEA = RdataType.SMIMEA -HIP = RdataType.HIP -NINFO = RdataType.NINFO -CDS = RdataType.CDS -CDNSKEY = RdataType.CDNSKEY -OPENPGPKEY = RdataType.OPENPGPKEY -CSYNC = RdataType.CSYNC -ZONEMD = RdataType.ZONEMD -SVCB = RdataType.SVCB -HTTPS = RdataType.HTTPS -SPF = RdataType.SPF -UNSPEC = RdataType.UNSPEC -NID = RdataType.NID -L32 = RdataType.L32 -L64 = RdataType.L64 -LP = RdataType.LP -EUI48 = RdataType.EUI48 -EUI64 = RdataType.EUI64 -TKEY = RdataType.TKEY -TSIG = RdataType.TSIG -IXFR = RdataType.IXFR -AXFR = RdataType.AXFR -MAILB = RdataType.MAILB -MAILA = RdataType.MAILA -ANY = RdataType.ANY -URI = RdataType.URI -CAA = RdataType.CAA -AVC = RdataType.AVC -AMTRELAY = RdataType.AMTRELAY -RESINFO = RdataType.RESINFO -WALLET = RdataType.WALLET -TA = RdataType.TA -DLV = RdataType.DLV - -### END generated RdataType constants diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/AFSDB.py b/venv/Lib/site-packages/dns/rdtypes/ANY/AFSDB.py deleted file mode 100644 index 06a3b97..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/AFSDB.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.mxbase - - -@dns.immutable.immutable -class AFSDB(dns.rdtypes.mxbase.UncompressedDowncasingMX): - """AFSDB record""" - - # Use the property mechanism to make "subtype" an alias for the - # "preference" attribute, and "hostname" an alias for the "exchange" - # attribute. - # - # This lets us inherit the UncompressedMX implementation but lets - # the caller use appropriate attribute names for the rdata type. - # - # We probably lose some performance vs. a cut-and-paste - # implementation, but this way we don't copy code, and that's - # good. - - @property - def subtype(self): - "the AFSDB subtype" - return self.preference - - @property - def hostname(self): - "the AFSDB hostname" - return self.exchange diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/AMTRELAY.py b/venv/Lib/site-packages/dns/rdtypes/ANY/AMTRELAY.py deleted file mode 100644 index ed2b072..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/AMTRELAY.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdtypes.util - - -class Relay(dns.rdtypes.util.Gateway): - name = "AMTRELAY relay" - - @property - def relay(self): - return self.gateway - - -@dns.immutable.immutable -class AMTRELAY(dns.rdata.Rdata): - """AMTRELAY record""" - - # see: RFC 8777 - - __slots__ = ["precedence", "discovery_optional", "relay_type", "relay"] - - def __init__( - self, rdclass, rdtype, precedence, discovery_optional, relay_type, relay - ): - super().__init__(rdclass, rdtype) - relay = Relay(relay_type, relay) - self.precedence = self._as_uint8(precedence) - self.discovery_optional = self._as_bool(discovery_optional) - self.relay_type = relay.type - self.relay = relay.relay - - def to_text(self, origin=None, relativize=True, **kw): - relay = Relay(self.relay_type, self.relay).to_text(origin, relativize) - return "%d %d %d %s" % ( - self.precedence, - self.discovery_optional, - self.relay_type, - relay, - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - precedence = tok.get_uint8() - discovery_optional = tok.get_uint8() - if discovery_optional > 1: - raise dns.exception.SyntaxError("expecting 0 or 1") - discovery_optional = bool(discovery_optional) - relay_type = tok.get_uint8() - if relay_type > 0x7F: - raise dns.exception.SyntaxError("expecting an integer <= 127") - relay = Relay.from_text(relay_type, tok, origin, relativize, relativize_to) - return cls( - rdclass, rdtype, precedence, discovery_optional, relay_type, relay.relay - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - relay_type = self.relay_type | (self.discovery_optional << 7) - header = struct.pack("!BB", self.precedence, relay_type) - file.write(header) - Relay(self.relay_type, self.relay).to_wire(file, compress, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (precedence, relay_type) = parser.get_struct("!BB") - discovery_optional = bool(relay_type >> 7) - relay_type &= 0x7F - relay = Relay.from_wire_parser(relay_type, parser, origin) - return cls( - rdclass, rdtype, precedence, discovery_optional, relay_type, relay.relay - ) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/AVC.py b/venv/Lib/site-packages/dns/rdtypes/ANY/AVC.py deleted file mode 100644 index a27ae2d..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/AVC.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2016 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.txtbase - - -@dns.immutable.immutable -class AVC(dns.rdtypes.txtbase.TXTBase): - """AVC record""" - - # See: IANA dns parameters for AVC diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/CAA.py b/venv/Lib/site-packages/dns/rdtypes/ANY/CAA.py deleted file mode 100644 index 2e6a7e7..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/CAA.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class CAA(dns.rdata.Rdata): - """CAA (Certification Authority Authorization) record""" - - # see: RFC 6844 - - __slots__ = ["flags", "tag", "value"] - - def __init__(self, rdclass, rdtype, flags, tag, value): - super().__init__(rdclass, rdtype) - self.flags = self._as_uint8(flags) - self.tag = self._as_bytes(tag, True, 255) - if not tag.isalnum(): - raise ValueError("tag is not alphanumeric") - self.value = self._as_bytes(value) - - def to_text(self, origin=None, relativize=True, **kw): - return '%u %s "%s"' % ( - self.flags, - dns.rdata._escapify(self.tag), - dns.rdata._escapify(self.value), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - flags = tok.get_uint8() - tag = tok.get_string().encode() - value = tok.get_string().encode() - return cls(rdclass, rdtype, flags, tag, value) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!B", self.flags)) - l = len(self.tag) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.tag) - file.write(self.value) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - flags = parser.get_uint8() - tag = parser.get_counted_bytes() - value = parser.get_remaining() - return cls(rdclass, rdtype, flags, tag, value) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/CDNSKEY.py b/venv/Lib/site-packages/dns/rdtypes/ANY/CDNSKEY.py deleted file mode 100644 index b613409..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/CDNSKEY.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.dnskeybase # lgtm[py/import-and-import-from] - -# pylint: disable=unused-import -from dns.rdtypes.dnskeybase import ( # noqa: F401 lgtm[py/unused-import] - REVOKE, - SEP, - ZONE, -) - -# pylint: enable=unused-import - - -@dns.immutable.immutable -class CDNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): - """CDNSKEY record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/CDS.py b/venv/Lib/site-packages/dns/rdtypes/ANY/CDS.py deleted file mode 100644 index 8312b97..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/CDS.py +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.dsbase - - -@dns.immutable.immutable -class CDS(dns.rdtypes.dsbase.DSBase): - """CDS record""" - - _digest_length_by_type = { - **dns.rdtypes.dsbase.DSBase._digest_length_by_type, - 0: 1, # delete, RFC 8078 Sec. 4 (including Errata ID 5049) - } diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/CERT.py b/venv/Lib/site-packages/dns/rdtypes/ANY/CERT.py deleted file mode 100644 index f369cc8..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/CERT.py +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import struct - -import dns.dnssectypes -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - -_ctype_by_value = { - 1: "PKIX", - 2: "SPKI", - 3: "PGP", - 4: "IPKIX", - 5: "ISPKI", - 6: "IPGP", - 7: "ACPKIX", - 8: "IACPKIX", - 253: "URI", - 254: "OID", -} - -_ctype_by_name = { - "PKIX": 1, - "SPKI": 2, - "PGP": 3, - "IPKIX": 4, - "ISPKI": 5, - "IPGP": 6, - "ACPKIX": 7, - "IACPKIX": 8, - "URI": 253, - "OID": 254, -} - - -def _ctype_from_text(what): - v = _ctype_by_name.get(what) - if v is not None: - return v - return int(what) - - -def _ctype_to_text(what): - v = _ctype_by_value.get(what) - if v is not None: - return v - return str(what) - - -@dns.immutable.immutable -class CERT(dns.rdata.Rdata): - """CERT record""" - - # see RFC 4398 - - __slots__ = ["certificate_type", "key_tag", "algorithm", "certificate"] - - def __init__( - self, rdclass, rdtype, certificate_type, key_tag, algorithm, certificate - ): - super().__init__(rdclass, rdtype) - self.certificate_type = self._as_uint16(certificate_type) - self.key_tag = self._as_uint16(key_tag) - self.algorithm = self._as_uint8(algorithm) - self.certificate = self._as_bytes(certificate) - - def to_text(self, origin=None, relativize=True, **kw): - certificate_type = _ctype_to_text(self.certificate_type) - return "%s %d %s %s" % ( - certificate_type, - self.key_tag, - dns.dnssectypes.Algorithm.to_text(self.algorithm), - dns.rdata._base64ify(self.certificate, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - certificate_type = _ctype_from_text(tok.get_string()) - key_tag = tok.get_uint16() - algorithm = dns.dnssectypes.Algorithm.from_text(tok.get_string()) - b64 = tok.concatenate_remaining_identifiers().encode() - certificate = base64.b64decode(b64) - return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - prefix = struct.pack( - "!HHB", self.certificate_type, self.key_tag, self.algorithm - ) - file.write(prefix) - file.write(self.certificate) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (certificate_type, key_tag, algorithm) = parser.get_struct("!HHB") - certificate = parser.get_remaining() - return cls(rdclass, rdtype, certificate_type, key_tag, algorithm, certificate) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/CNAME.py b/venv/Lib/site-packages/dns/rdtypes/ANY/CNAME.py deleted file mode 100644 index 665e407..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/CNAME.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.nsbase - - -@dns.immutable.immutable -class CNAME(dns.rdtypes.nsbase.NSBase): - """CNAME record - - Note: although CNAME is officially a singleton type, dnspython allows - non-singleton CNAME rdatasets because such sets have been commonly - used by BIND and other nameservers for load balancing.""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/CSYNC.py b/venv/Lib/site-packages/dns/rdtypes/ANY/CSYNC.py deleted file mode 100644 index 2f972f6..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/CSYNC.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011, 2016 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdatatype -import dns.rdtypes.util - - -@dns.immutable.immutable -class Bitmap(dns.rdtypes.util.Bitmap): - type_name = "CSYNC" - - -@dns.immutable.immutable -class CSYNC(dns.rdata.Rdata): - """CSYNC record""" - - __slots__ = ["serial", "flags", "windows"] - - def __init__(self, rdclass, rdtype, serial, flags, windows): - super().__init__(rdclass, rdtype) - self.serial = self._as_uint32(serial) - self.flags = self._as_uint16(flags) - if not isinstance(windows, Bitmap): - windows = Bitmap(windows) - self.windows = tuple(windows.windows) - - def to_text(self, origin=None, relativize=True, **kw): - text = Bitmap(self.windows).to_text() - return "%d %d%s" % (self.serial, self.flags, text) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - serial = tok.get_uint32() - flags = tok.get_uint16() - bitmap = Bitmap.from_text(tok) - return cls(rdclass, rdtype, serial, flags, bitmap) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!IH", self.serial, self.flags)) - Bitmap(self.windows).to_wire(file) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (serial, flags) = parser.get_struct("!IH") - bitmap = Bitmap.from_wire_parser(parser) - return cls(rdclass, rdtype, serial, flags, bitmap) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/DLV.py b/venv/Lib/site-packages/dns/rdtypes/ANY/DLV.py deleted file mode 100644 index 6c134f1..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/DLV.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.dsbase - - -@dns.immutable.immutable -class DLV(dns.rdtypes.dsbase.DSBase): - """DLV record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/DNAME.py b/venv/Lib/site-packages/dns/rdtypes/ANY/DNAME.py deleted file mode 100644 index bbf9186..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/DNAME.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.nsbase - - -@dns.immutable.immutable -class DNAME(dns.rdtypes.nsbase.UncompressedNS): - """DNAME record""" - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.target.to_wire(file, None, origin, canonicalize) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/DNSKEY.py b/venv/Lib/site-packages/dns/rdtypes/ANY/DNSKEY.py deleted file mode 100644 index 6d961a9..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/DNSKEY.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.dnskeybase # lgtm[py/import-and-import-from] - -# pylint: disable=unused-import -from dns.rdtypes.dnskeybase import ( # noqa: F401 lgtm[py/unused-import] - REVOKE, - SEP, - ZONE, -) - -# pylint: enable=unused-import - - -@dns.immutable.immutable -class DNSKEY(dns.rdtypes.dnskeybase.DNSKEYBase): - """DNSKEY record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/DS.py b/venv/Lib/site-packages/dns/rdtypes/ANY/DS.py deleted file mode 100644 index 58b3108..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/DS.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.dsbase - - -@dns.immutable.immutable -class DS(dns.rdtypes.dsbase.DSBase): - """DS record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/EUI48.py b/venv/Lib/site-packages/dns/rdtypes/ANY/EUI48.py deleted file mode 100644 index c843be5..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/EUI48.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2015 Red Hat, Inc. -# Author: Petr Spacek -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.euibase - - -@dns.immutable.immutable -class EUI48(dns.rdtypes.euibase.EUIBase): - """EUI48 record""" - - # see: rfc7043.txt - - byte_len = 6 # 0123456789ab (in hex) - text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/EUI64.py b/venv/Lib/site-packages/dns/rdtypes/ANY/EUI64.py deleted file mode 100644 index f6d7e25..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/EUI64.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2015 Red Hat, Inc. -# Author: Petr Spacek -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.euibase - - -@dns.immutable.immutable -class EUI64(dns.rdtypes.euibase.EUIBase): - """EUI64 record""" - - # see: rfc7043.txt - - byte_len = 8 # 0123456789abcdef (in hex) - text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab-cd-ef diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/GPOS.py b/venv/Lib/site-packages/dns/rdtypes/ANY/GPOS.py deleted file mode 100644 index d79f4a0..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/GPOS.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -def _validate_float_string(what): - if len(what) == 0: - raise dns.exception.FormError - if what[0] == b"-"[0] or what[0] == b"+"[0]: - what = what[1:] - if what.isdigit(): - return - try: - (left, right) = what.split(b".") - except ValueError: - raise dns.exception.FormError - if left == b"" and right == b"": - raise dns.exception.FormError - if not left == b"" and not left.decode().isdigit(): - raise dns.exception.FormError - if not right == b"" and not right.decode().isdigit(): - raise dns.exception.FormError - - -@dns.immutable.immutable -class GPOS(dns.rdata.Rdata): - """GPOS record""" - - # see: RFC 1712 - - __slots__ = ["latitude", "longitude", "altitude"] - - def __init__(self, rdclass, rdtype, latitude, longitude, altitude): - super().__init__(rdclass, rdtype) - if isinstance(latitude, float) or isinstance(latitude, int): - latitude = str(latitude) - if isinstance(longitude, float) or isinstance(longitude, int): - longitude = str(longitude) - if isinstance(altitude, float) or isinstance(altitude, int): - altitude = str(altitude) - latitude = self._as_bytes(latitude, True, 255) - longitude = self._as_bytes(longitude, True, 255) - altitude = self._as_bytes(altitude, True, 255) - _validate_float_string(latitude) - _validate_float_string(longitude) - _validate_float_string(altitude) - self.latitude = latitude - self.longitude = longitude - self.altitude = altitude - flat = self.float_latitude - if flat < -90.0 or flat > 90.0: - raise dns.exception.FormError("bad latitude") - flong = self.float_longitude - if flong < -180.0 or flong > 180.0: - raise dns.exception.FormError("bad longitude") - - def to_text(self, origin=None, relativize=True, **kw): - return ( - f"{self.latitude.decode()} {self.longitude.decode()} " - f"{self.altitude.decode()}" - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - latitude = tok.get_string() - longitude = tok.get_string() - altitude = tok.get_string() - return cls(rdclass, rdtype, latitude, longitude, altitude) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - l = len(self.latitude) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.latitude) - l = len(self.longitude) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.longitude) - l = len(self.altitude) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.altitude) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - latitude = parser.get_counted_bytes() - longitude = parser.get_counted_bytes() - altitude = parser.get_counted_bytes() - return cls(rdclass, rdtype, latitude, longitude, altitude) - - @property - def float_latitude(self): - "latitude as a floating point value" - return float(self.latitude) - - @property - def float_longitude(self): - "longitude as a floating point value" - return float(self.longitude) - - @property - def float_altitude(self): - "altitude as a floating point value" - return float(self.altitude) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/HINFO.py b/venv/Lib/site-packages/dns/rdtypes/ANY/HINFO.py deleted file mode 100644 index 06ad348..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/HINFO.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class HINFO(dns.rdata.Rdata): - """HINFO record""" - - # see: RFC 1035 - - __slots__ = ["cpu", "os"] - - def __init__(self, rdclass, rdtype, cpu, os): - super().__init__(rdclass, rdtype) - self.cpu = self._as_bytes(cpu, True, 255) - self.os = self._as_bytes(os, True, 255) - - def to_text(self, origin=None, relativize=True, **kw): - return f'"{dns.rdata._escapify(self.cpu)}" "{dns.rdata._escapify(self.os)}"' - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - cpu = tok.get_string(max_length=255) - os = tok.get_string(max_length=255) - return cls(rdclass, rdtype, cpu, os) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - l = len(self.cpu) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.cpu) - l = len(self.os) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.os) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - cpu = parser.get_counted_bytes() - os = parser.get_counted_bytes() - return cls(rdclass, rdtype, cpu, os) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/HIP.py b/venv/Lib/site-packages/dns/rdtypes/ANY/HIP.py deleted file mode 100644 index f3157da..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/HIP.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2010, 2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import binascii -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.rdatatype - - -@dns.immutable.immutable -class HIP(dns.rdata.Rdata): - """HIP record""" - - # see: RFC 5205 - - __slots__ = ["hit", "algorithm", "key", "servers"] - - def __init__(self, rdclass, rdtype, hit, algorithm, key, servers): - super().__init__(rdclass, rdtype) - self.hit = self._as_bytes(hit, True, 255) - self.algorithm = self._as_uint8(algorithm) - self.key = self._as_bytes(key, True) - self.servers = self._as_tuple(servers, self._as_name) - - def to_text(self, origin=None, relativize=True, **kw): - hit = binascii.hexlify(self.hit).decode() - key = base64.b64encode(self.key).replace(b"\n", b"").decode() - text = "" - servers = [] - for server in self.servers: - servers.append(server.choose_relativity(origin, relativize)) - if len(servers) > 0: - text += " " + " ".join(x.to_unicode() for x in servers) - return "%u %s %s%s" % (self.algorithm, hit, key, text) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - algorithm = tok.get_uint8() - hit = binascii.unhexlify(tok.get_string().encode()) - key = base64.b64decode(tok.get_string().encode()) - servers = [] - for token in tok.get_remaining(): - server = tok.as_name(token, origin, relativize, relativize_to) - servers.append(server) - return cls(rdclass, rdtype, hit, algorithm, key, servers) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - lh = len(self.hit) - lk = len(self.key) - file.write(struct.pack("!BBH", lh, self.algorithm, lk)) - file.write(self.hit) - file.write(self.key) - for server in self.servers: - server.to_wire(file, None, origin, False) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (lh, algorithm, lk) = parser.get_struct("!BBH") - hit = parser.get_bytes(lh) - key = parser.get_bytes(lk) - servers = [] - while parser.remaining() > 0: - server = parser.get_name(origin) - servers.append(server) - return cls(rdclass, rdtype, hit, algorithm, key, servers) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/ISDN.py b/venv/Lib/site-packages/dns/rdtypes/ANY/ISDN.py deleted file mode 100644 index 6428a0a..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/ISDN.py +++ /dev/null @@ -1,78 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class ISDN(dns.rdata.Rdata): - """ISDN record""" - - # see: RFC 1183 - - __slots__ = ["address", "subaddress"] - - def __init__(self, rdclass, rdtype, address, subaddress): - super().__init__(rdclass, rdtype) - self.address = self._as_bytes(address, True, 255) - self.subaddress = self._as_bytes(subaddress, True, 255) - - def to_text(self, origin=None, relativize=True, **kw): - if self.subaddress: - return ( - f'"{dns.rdata._escapify(self.address)}" ' - f'"{dns.rdata._escapify(self.subaddress)}"' - ) - else: - return f'"{dns.rdata._escapify(self.address)}"' - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - address = tok.get_string() - tokens = tok.get_remaining(max_tokens=1) - if len(tokens) >= 1: - subaddress = tokens[0].unescape().value - else: - subaddress = "" - return cls(rdclass, rdtype, address, subaddress) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - l = len(self.address) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.address) - l = len(self.subaddress) - if l > 0: - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.subaddress) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - address = parser.get_counted_bytes() - if parser.remaining() > 0: - subaddress = parser.get_counted_bytes() - else: - subaddress = b"" - return cls(rdclass, rdtype, address, subaddress) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/L32.py b/venv/Lib/site-packages/dns/rdtypes/ANY/L32.py deleted file mode 100644 index 09804c2..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/L32.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import struct - -import dns.immutable -import dns.rdata - - -@dns.immutable.immutable -class L32(dns.rdata.Rdata): - """L32 record""" - - # see: rfc6742.txt - - __slots__ = ["preference", "locator32"] - - def __init__(self, rdclass, rdtype, preference, locator32): - super().__init__(rdclass, rdtype) - self.preference = self._as_uint16(preference) - self.locator32 = self._as_ipv4_address(locator32) - - def to_text(self, origin=None, relativize=True, **kw): - return f"{self.preference} {self.locator32}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - preference = tok.get_uint16() - nodeid = tok.get_identifier() - return cls(rdclass, rdtype, preference, nodeid) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!H", self.preference)) - file.write(dns.ipv4.inet_aton(self.locator32)) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - preference = parser.get_uint16() - locator32 = parser.get_remaining() - return cls(rdclass, rdtype, preference, locator32) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/L64.py b/venv/Lib/site-packages/dns/rdtypes/ANY/L64.py deleted file mode 100644 index fb76808..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/L64.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import struct - -import dns.immutable -import dns.rdtypes.util - - -@dns.immutable.immutable -class L64(dns.rdata.Rdata): - """L64 record""" - - # see: rfc6742.txt - - __slots__ = ["preference", "locator64"] - - def __init__(self, rdclass, rdtype, preference, locator64): - super().__init__(rdclass, rdtype) - self.preference = self._as_uint16(preference) - if isinstance(locator64, bytes): - if len(locator64) != 8: - raise ValueError("invalid locator64") - self.locator64 = dns.rdata._hexify(locator64, 4, b":") - else: - dns.rdtypes.util.parse_formatted_hex(locator64, 4, 4, ":") - self.locator64 = locator64 - - def to_text(self, origin=None, relativize=True, **kw): - return f"{self.preference} {self.locator64}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - preference = tok.get_uint16() - locator64 = tok.get_identifier() - return cls(rdclass, rdtype, preference, locator64) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!H", self.preference)) - file.write(dns.rdtypes.util.parse_formatted_hex(self.locator64, 4, 4, ":")) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - preference = parser.get_uint16() - locator64 = parser.get_remaining() - return cls(rdclass, rdtype, preference, locator64) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/LOC.py b/venv/Lib/site-packages/dns/rdtypes/ANY/LOC.py deleted file mode 100644 index 1153cf0..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/LOC.py +++ /dev/null @@ -1,353 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdata - -_pows = tuple(10**i for i in range(0, 11)) - -# default values are in centimeters -_default_size = 100.0 -_default_hprec = 1000000.0 -_default_vprec = 1000.0 - -# for use by from_wire() -_MAX_LATITUDE = 0x80000000 + 90 * 3600000 -_MIN_LATITUDE = 0x80000000 - 90 * 3600000 -_MAX_LONGITUDE = 0x80000000 + 180 * 3600000 -_MIN_LONGITUDE = 0x80000000 - 180 * 3600000 - - -def _exponent_of(what, desc): - if what == 0: - return 0 - exp = None - for i, pow in enumerate(_pows): - if what < pow: - exp = i - 1 - break - if exp is None or exp < 0: - raise dns.exception.SyntaxError(f"{desc} value out of bounds") - return exp - - -def _float_to_tuple(what): - if what < 0: - sign = -1 - what *= -1 - else: - sign = 1 - what = round(what * 3600000) - degrees = int(what // 3600000) - what -= degrees * 3600000 - minutes = int(what // 60000) - what -= minutes * 60000 - seconds = int(what // 1000) - what -= int(seconds * 1000) - what = int(what) - return (degrees, minutes, seconds, what, sign) - - -def _tuple_to_float(what): - value = float(what[0]) - value += float(what[1]) / 60.0 - value += float(what[2]) / 3600.0 - value += float(what[3]) / 3600000.0 - return float(what[4]) * value - - -def _encode_size(what, desc): - what = int(what) - exponent = _exponent_of(what, desc) & 0xF - base = what // pow(10, exponent) & 0xF - return base * 16 + exponent - - -def _decode_size(what, desc): - exponent = what & 0x0F - if exponent > 9: - raise dns.exception.FormError(f"bad {desc} exponent") - base = (what & 0xF0) >> 4 - if base > 9: - raise dns.exception.FormError(f"bad {desc} base") - return base * pow(10, exponent) - - -def _check_coordinate_list(value, low, high): - if value[0] < low or value[0] > high: - raise ValueError(f"not in range [{low}, {high}]") - if value[1] < 0 or value[1] > 59: - raise ValueError("bad minutes value") - if value[2] < 0 or value[2] > 59: - raise ValueError("bad seconds value") - if value[3] < 0 or value[3] > 999: - raise ValueError("bad milliseconds value") - if value[4] != 1 and value[4] != -1: - raise ValueError("bad hemisphere value") - - -@dns.immutable.immutable -class LOC(dns.rdata.Rdata): - """LOC record""" - - # see: RFC 1876 - - __slots__ = [ - "latitude", - "longitude", - "altitude", - "size", - "horizontal_precision", - "vertical_precision", - ] - - def __init__( - self, - rdclass, - rdtype, - latitude, - longitude, - altitude, - size=_default_size, - hprec=_default_hprec, - vprec=_default_vprec, - ): - """Initialize a LOC record instance. - - The parameters I{latitude} and I{longitude} may be either a 4-tuple - of integers specifying (degrees, minutes, seconds, milliseconds), - or they may be floating point values specifying the number of - degrees. The other parameters are floats. Size, horizontal precision, - and vertical precision are specified in centimeters.""" - - super().__init__(rdclass, rdtype) - if isinstance(latitude, int): - latitude = float(latitude) - if isinstance(latitude, float): - latitude = _float_to_tuple(latitude) - _check_coordinate_list(latitude, -90, 90) - self.latitude = tuple(latitude) - if isinstance(longitude, int): - longitude = float(longitude) - if isinstance(longitude, float): - longitude = _float_to_tuple(longitude) - _check_coordinate_list(longitude, -180, 180) - self.longitude = tuple(longitude) - self.altitude = float(altitude) - self.size = float(size) - self.horizontal_precision = float(hprec) - self.vertical_precision = float(vprec) - - def to_text(self, origin=None, relativize=True, **kw): - if self.latitude[4] > 0: - lat_hemisphere = "N" - else: - lat_hemisphere = "S" - if self.longitude[4] > 0: - long_hemisphere = "E" - else: - long_hemisphere = "W" - text = "%d %d %d.%03d %s %d %d %d.%03d %s %0.2fm" % ( - self.latitude[0], - self.latitude[1], - self.latitude[2], - self.latitude[3], - lat_hemisphere, - self.longitude[0], - self.longitude[1], - self.longitude[2], - self.longitude[3], - long_hemisphere, - self.altitude / 100.0, - ) - - # do not print default values - if ( - self.size != _default_size - or self.horizontal_precision != _default_hprec - or self.vertical_precision != _default_vprec - ): - text += ( - f" {self.size / 100.0:0.2f}m {self.horizontal_precision / 100.0:0.2f}m" - f" {self.vertical_precision / 100.0:0.2f}m" - ) - return text - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - latitude = [0, 0, 0, 0, 1] - longitude = [0, 0, 0, 0, 1] - size = _default_size - hprec = _default_hprec - vprec = _default_vprec - - latitude[0] = tok.get_int() - t = tok.get_string() - if t.isdigit(): - latitude[1] = int(t) - t = tok.get_string() - if "." in t: - (seconds, milliseconds) = t.split(".") - if not seconds.isdigit(): - raise dns.exception.SyntaxError("bad latitude seconds value") - latitude[2] = int(seconds) - l = len(milliseconds) - if l == 0 or l > 3 or not milliseconds.isdigit(): - raise dns.exception.SyntaxError("bad latitude milliseconds value") - if l == 1: - m = 100 - elif l == 2: - m = 10 - else: - m = 1 - latitude[3] = m * int(milliseconds) - t = tok.get_string() - elif t.isdigit(): - latitude[2] = int(t) - t = tok.get_string() - if t == "S": - latitude[4] = -1 - elif t != "N": - raise dns.exception.SyntaxError("bad latitude hemisphere value") - - longitude[0] = tok.get_int() - t = tok.get_string() - if t.isdigit(): - longitude[1] = int(t) - t = tok.get_string() - if "." in t: - (seconds, milliseconds) = t.split(".") - if not seconds.isdigit(): - raise dns.exception.SyntaxError("bad longitude seconds value") - longitude[2] = int(seconds) - l = len(milliseconds) - if l == 0 or l > 3 or not milliseconds.isdigit(): - raise dns.exception.SyntaxError("bad longitude milliseconds value") - if l == 1: - m = 100 - elif l == 2: - m = 10 - else: - m = 1 - longitude[3] = m * int(milliseconds) - t = tok.get_string() - elif t.isdigit(): - longitude[2] = int(t) - t = tok.get_string() - if t == "W": - longitude[4] = -1 - elif t != "E": - raise dns.exception.SyntaxError("bad longitude hemisphere value") - - t = tok.get_string() - if t[-1] == "m": - t = t[0:-1] - altitude = float(t) * 100.0 # m -> cm - - tokens = tok.get_remaining(max_tokens=3) - if len(tokens) >= 1: - value = tokens[0].unescape().value - if value[-1] == "m": - value = value[0:-1] - size = float(value) * 100.0 # m -> cm - if len(tokens) >= 2: - value = tokens[1].unescape().value - if value[-1] == "m": - value = value[0:-1] - hprec = float(value) * 100.0 # m -> cm - if len(tokens) >= 3: - value = tokens[2].unescape().value - if value[-1] == "m": - value = value[0:-1] - vprec = float(value) * 100.0 # m -> cm - - # Try encoding these now so we raise if they are bad - _encode_size(size, "size") - _encode_size(hprec, "horizontal precision") - _encode_size(vprec, "vertical precision") - - return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - milliseconds = ( - self.latitude[0] * 3600000 - + self.latitude[1] * 60000 - + self.latitude[2] * 1000 - + self.latitude[3] - ) * self.latitude[4] - latitude = 0x80000000 + milliseconds - milliseconds = ( - self.longitude[0] * 3600000 - + self.longitude[1] * 60000 - + self.longitude[2] * 1000 - + self.longitude[3] - ) * self.longitude[4] - longitude = 0x80000000 + milliseconds - altitude = int(self.altitude) + 10000000 - size = _encode_size(self.size, "size") - hprec = _encode_size(self.horizontal_precision, "horizontal precision") - vprec = _encode_size(self.vertical_precision, "vertical precision") - wire = struct.pack( - "!BBBBIII", 0, size, hprec, vprec, latitude, longitude, altitude - ) - file.write(wire) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - ( - version, - size, - hprec, - vprec, - latitude, - longitude, - altitude, - ) = parser.get_struct("!BBBBIII") - if version != 0: - raise dns.exception.FormError("LOC version not zero") - if latitude < _MIN_LATITUDE or latitude > _MAX_LATITUDE: - raise dns.exception.FormError("bad latitude") - if latitude > 0x80000000: - latitude = (latitude - 0x80000000) / 3600000 - else: - latitude = -1 * (0x80000000 - latitude) / 3600000 - if longitude < _MIN_LONGITUDE or longitude > _MAX_LONGITUDE: - raise dns.exception.FormError("bad longitude") - if longitude > 0x80000000: - longitude = (longitude - 0x80000000) / 3600000 - else: - longitude = -1 * (0x80000000 - longitude) / 3600000 - altitude = float(altitude) - 10000000.0 - size = _decode_size(size, "size") - hprec = _decode_size(hprec, "horizontal precision") - vprec = _decode_size(vprec, "vertical precision") - return cls(rdclass, rdtype, latitude, longitude, altitude, size, hprec, vprec) - - @property - def float_latitude(self): - "latitude as a floating point value" - return _tuple_to_float(self.latitude) - - @property - def float_longitude(self): - "longitude as a floating point value" - return _tuple_to_float(self.longitude) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/LP.py b/venv/Lib/site-packages/dns/rdtypes/ANY/LP.py deleted file mode 100644 index 312663f..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/LP.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import struct - -import dns.immutable -import dns.rdata - - -@dns.immutable.immutable -class LP(dns.rdata.Rdata): - """LP record""" - - # see: rfc6742.txt - - __slots__ = ["preference", "fqdn"] - - def __init__(self, rdclass, rdtype, preference, fqdn): - super().__init__(rdclass, rdtype) - self.preference = self._as_uint16(preference) - self.fqdn = self._as_name(fqdn) - - def to_text(self, origin=None, relativize=True, **kw): - fqdn = self.fqdn.choose_relativity(origin, relativize) - return "%d %s" % (self.preference, fqdn) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - preference = tok.get_uint16() - fqdn = tok.get_name(origin, relativize, relativize_to) - return cls(rdclass, rdtype, preference, fqdn) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!H", self.preference)) - self.fqdn.to_wire(file, compress, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - preference = parser.get_uint16() - fqdn = parser.get_name(origin) - return cls(rdclass, rdtype, preference, fqdn) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/MX.py b/venv/Lib/site-packages/dns/rdtypes/ANY/MX.py deleted file mode 100644 index 0c300c5..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/MX.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.mxbase - - -@dns.immutable.immutable -class MX(dns.rdtypes.mxbase.MXBase): - """MX record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/NID.py b/venv/Lib/site-packages/dns/rdtypes/ANY/NID.py deleted file mode 100644 index 2f64917..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/NID.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import struct - -import dns.immutable -import dns.rdtypes.util - - -@dns.immutable.immutable -class NID(dns.rdata.Rdata): - """NID record""" - - # see: rfc6742.txt - - __slots__ = ["preference", "nodeid"] - - def __init__(self, rdclass, rdtype, preference, nodeid): - super().__init__(rdclass, rdtype) - self.preference = self._as_uint16(preference) - if isinstance(nodeid, bytes): - if len(nodeid) != 8: - raise ValueError("invalid nodeid") - self.nodeid = dns.rdata._hexify(nodeid, 4, b":") - else: - dns.rdtypes.util.parse_formatted_hex(nodeid, 4, 4, ":") - self.nodeid = nodeid - - def to_text(self, origin=None, relativize=True, **kw): - return f"{self.preference} {self.nodeid}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - preference = tok.get_uint16() - nodeid = tok.get_identifier() - return cls(rdclass, rdtype, preference, nodeid) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!H", self.preference)) - file.write(dns.rdtypes.util.parse_formatted_hex(self.nodeid, 4, 4, ":")) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - preference = parser.get_uint16() - nodeid = parser.get_remaining() - return cls(rdclass, rdtype, preference, nodeid) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/NINFO.py b/venv/Lib/site-packages/dns/rdtypes/ANY/NINFO.py deleted file mode 100644 index b177bdd..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/NINFO.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.txtbase - - -@dns.immutable.immutable -class NINFO(dns.rdtypes.txtbase.TXTBase): - """NINFO record""" - - # see: draft-reid-dnsext-zs-01 diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/NS.py b/venv/Lib/site-packages/dns/rdtypes/ANY/NS.py deleted file mode 100644 index c3f34ce..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/NS.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.nsbase - - -@dns.immutable.immutable -class NS(dns.rdtypes.nsbase.NSBase): - """NS record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC.py b/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC.py deleted file mode 100644 index 3c78b72..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdatatype -import dns.rdtypes.util - - -@dns.immutable.immutable -class Bitmap(dns.rdtypes.util.Bitmap): - type_name = "NSEC" - - -@dns.immutable.immutable -class NSEC(dns.rdata.Rdata): - """NSEC record""" - - __slots__ = ["next", "windows"] - - def __init__(self, rdclass, rdtype, next, windows): - super().__init__(rdclass, rdtype) - self.next = self._as_name(next) - if not isinstance(windows, Bitmap): - windows = Bitmap(windows) - self.windows = tuple(windows.windows) - - def to_text(self, origin=None, relativize=True, **kw): - next = self.next.choose_relativity(origin, relativize) - text = Bitmap(self.windows).to_text() - return f"{next}{text}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - next = tok.get_name(origin, relativize, relativize_to) - windows = Bitmap.from_text(tok) - return cls(rdclass, rdtype, next, windows) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - # Note that NSEC downcasing, originally mandated by RFC 4034 - # section 6.2 was removed by RFC 6840 section 5.1. - self.next.to_wire(file, None, origin, False) - Bitmap(self.windows).to_wire(file) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - next = parser.get_name(origin) - bitmap = Bitmap.from_wire_parser(parser) - return cls(rdclass, rdtype, next, bitmap) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3.py b/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3.py deleted file mode 100644 index d71302b..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3.py +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import binascii -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.rdatatype -import dns.rdtypes.util - -b32_hex_to_normal = bytes.maketrans( - b"0123456789ABCDEFGHIJKLMNOPQRSTUV", b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" -) -b32_normal_to_hex = bytes.maketrans( - b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", b"0123456789ABCDEFGHIJKLMNOPQRSTUV" -) - -# hash algorithm constants -SHA1 = 1 - -# flag constants -OPTOUT = 1 - - -@dns.immutable.immutable -class Bitmap(dns.rdtypes.util.Bitmap): - type_name = "NSEC3" - - -@dns.immutable.immutable -class NSEC3(dns.rdata.Rdata): - """NSEC3 record""" - - __slots__ = ["algorithm", "flags", "iterations", "salt", "next", "windows"] - - def __init__( - self, rdclass, rdtype, algorithm, flags, iterations, salt, next, windows - ): - super().__init__(rdclass, rdtype) - self.algorithm = self._as_uint8(algorithm) - self.flags = self._as_uint8(flags) - self.iterations = self._as_uint16(iterations) - self.salt = self._as_bytes(salt, True, 255) - self.next = self._as_bytes(next, True, 255) - if not isinstance(windows, Bitmap): - windows = Bitmap(windows) - self.windows = tuple(windows.windows) - - def _next_text(self): - next = base64.b32encode(self.next).translate(b32_normal_to_hex).lower().decode() - next = next.rstrip("=") - return next - - def to_text(self, origin=None, relativize=True, **kw): - next = self._next_text() - if self.salt == b"": - salt = "-" - else: - salt = binascii.hexlify(self.salt).decode() - text = Bitmap(self.windows).to_text() - return "%u %u %u %s %s%s" % ( - self.algorithm, - self.flags, - self.iterations, - salt, - next, - text, - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - algorithm = tok.get_uint8() - flags = tok.get_uint8() - iterations = tok.get_uint16() - salt = tok.get_string() - if salt == "-": - salt = b"" - else: - salt = binascii.unhexlify(salt.encode("ascii")) - next = tok.get_string().encode("ascii").upper().translate(b32_hex_to_normal) - if next.endswith(b"="): - raise binascii.Error("Incorrect padding") - if len(next) % 8 != 0: - next += b"=" * (8 - len(next) % 8) - next = base64.b32decode(next) - bitmap = Bitmap.from_text(tok) - return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, bitmap) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - l = len(self.salt) - file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l)) - file.write(self.salt) - l = len(self.next) - file.write(struct.pack("!B", l)) - file.write(self.next) - Bitmap(self.windows).to_wire(file) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (algorithm, flags, iterations) = parser.get_struct("!BBH") - salt = parser.get_counted_bytes() - next = parser.get_counted_bytes() - bitmap = Bitmap.from_wire_parser(parser) - return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, bitmap) - - def next_name(self, origin=None): - return dns.name.from_text(self._next_text(), origin) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3PARAM.py b/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3PARAM.py deleted file mode 100644 index d1e62eb..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/NSEC3PARAM.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii -import struct - -import dns.exception -import dns.immutable -import dns.rdata - - -@dns.immutable.immutable -class NSEC3PARAM(dns.rdata.Rdata): - """NSEC3PARAM record""" - - __slots__ = ["algorithm", "flags", "iterations", "salt"] - - def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt): - super().__init__(rdclass, rdtype) - self.algorithm = self._as_uint8(algorithm) - self.flags = self._as_uint8(flags) - self.iterations = self._as_uint16(iterations) - self.salt = self._as_bytes(salt, True, 255) - - def to_text(self, origin=None, relativize=True, **kw): - if self.salt == b"": - salt = "-" - else: - salt = binascii.hexlify(self.salt).decode() - return "%u %u %u %s" % (self.algorithm, self.flags, self.iterations, salt) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - algorithm = tok.get_uint8() - flags = tok.get_uint8() - iterations = tok.get_uint16() - salt = tok.get_string() - if salt == "-": - salt = "" - else: - salt = binascii.unhexlify(salt.encode()) - return cls(rdclass, rdtype, algorithm, flags, iterations, salt) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - l = len(self.salt) - file.write(struct.pack("!BBHB", self.algorithm, self.flags, self.iterations, l)) - file.write(self.salt) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (algorithm, flags, iterations) = parser.get_struct("!BBH") - salt = parser.get_counted_bytes() - return cls(rdclass, rdtype, algorithm, flags, iterations, salt) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/OPENPGPKEY.py b/venv/Lib/site-packages/dns/rdtypes/ANY/OPENPGPKEY.py deleted file mode 100644 index 4d7a4b6..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/OPENPGPKEY.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2016 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class OPENPGPKEY(dns.rdata.Rdata): - """OPENPGPKEY record""" - - # see: RFC 7929 - - def __init__(self, rdclass, rdtype, key): - super().__init__(rdclass, rdtype) - self.key = self._as_bytes(key) - - def to_text(self, origin=None, relativize=True, **kw): - return dns.rdata._base64ify(self.key, chunksize=None, **kw) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - b64 = tok.concatenate_remaining_identifiers().encode() - key = base64.b64decode(b64) - return cls(rdclass, rdtype, key) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(self.key) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - key = parser.get_remaining() - return cls(rdclass, rdtype, key) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/OPT.py b/venv/Lib/site-packages/dns/rdtypes/ANY/OPT.py deleted file mode 100644 index d343dfa..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/OPT.py +++ /dev/null @@ -1,77 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.edns -import dns.exception -import dns.immutable -import dns.rdata - -# We don't implement from_text, and that's ok. -# pylint: disable=abstract-method - - -@dns.immutable.immutable -class OPT(dns.rdata.Rdata): - """OPT record""" - - __slots__ = ["options"] - - def __init__(self, rdclass, rdtype, options): - """Initialize an OPT rdata. - - *rdclass*, an ``int`` is the rdataclass of the Rdata, - which is also the payload size. - - *rdtype*, an ``int`` is the rdatatype of the Rdata. - - *options*, a tuple of ``bytes`` - """ - - super().__init__(rdclass, rdtype) - - def as_option(option): - if not isinstance(option, dns.edns.Option): - raise ValueError("option is not a dns.edns.option") - return option - - self.options = self._as_tuple(options, as_option) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - for opt in self.options: - owire = opt.to_wire() - file.write(struct.pack("!HH", opt.otype, len(owire))) - file.write(owire) - - def to_text(self, origin=None, relativize=True, **kw): - return " ".join(opt.to_text() for opt in self.options) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - options = [] - while parser.remaining() > 0: - (otype, olen) = parser.get_struct("!HH") - with parser.restrict_to(olen): - opt = dns.edns.option_from_wire_parser(otype, parser) - options.append(opt) - return cls(rdclass, rdtype, options) - - @property - def payload(self): - "payload size" - return self.rdclass diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/PTR.py b/venv/Lib/site-packages/dns/rdtypes/ANY/PTR.py deleted file mode 100644 index 98c3616..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/PTR.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.nsbase - - -@dns.immutable.immutable -class PTR(dns.rdtypes.nsbase.NSBase): - """PTR record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/RESINFO.py b/venv/Lib/site-packages/dns/rdtypes/ANY/RESINFO.py deleted file mode 100644 index 76c8ea2..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/RESINFO.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.txtbase - - -@dns.immutable.immutable -class RESINFO(dns.rdtypes.txtbase.TXTBase): - """RESINFO record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/RP.py b/venv/Lib/site-packages/dns/rdtypes/ANY/RP.py deleted file mode 100644 index a66cfc5..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/RP.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata - - -@dns.immutable.immutable -class RP(dns.rdata.Rdata): - """RP record""" - - # see: RFC 1183 - - __slots__ = ["mbox", "txt"] - - def __init__(self, rdclass, rdtype, mbox, txt): - super().__init__(rdclass, rdtype) - self.mbox = self._as_name(mbox) - self.txt = self._as_name(txt) - - def to_text(self, origin=None, relativize=True, **kw): - mbox = self.mbox.choose_relativity(origin, relativize) - txt = self.txt.choose_relativity(origin, relativize) - return f"{str(mbox)} {str(txt)}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - mbox = tok.get_name(origin, relativize, relativize_to) - txt = tok.get_name(origin, relativize, relativize_to) - return cls(rdclass, rdtype, mbox, txt) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.mbox.to_wire(file, None, origin, canonicalize) - self.txt.to_wire(file, None, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - mbox = parser.get_name(origin) - txt = parser.get_name(origin) - return cls(rdclass, rdtype, mbox, txt) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/RRSIG.py b/venv/Lib/site-packages/dns/rdtypes/ANY/RRSIG.py deleted file mode 100644 index 8beb423..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/RRSIG.py +++ /dev/null @@ -1,157 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import calendar -import struct -import time - -import dns.dnssectypes -import dns.exception -import dns.immutable -import dns.rdata -import dns.rdatatype - - -class BadSigTime(dns.exception.DNSException): - """Time in DNS SIG or RRSIG resource record cannot be parsed.""" - - -def sigtime_to_posixtime(what): - if len(what) <= 10 and what.isdigit(): - return int(what) - if len(what) != 14: - raise BadSigTime - year = int(what[0:4]) - month = int(what[4:6]) - day = int(what[6:8]) - hour = int(what[8:10]) - minute = int(what[10:12]) - second = int(what[12:14]) - return calendar.timegm((year, month, day, hour, minute, second, 0, 0, 0)) - - -def posixtime_to_sigtime(what): - return time.strftime("%Y%m%d%H%M%S", time.gmtime(what)) - - -@dns.immutable.immutable -class RRSIG(dns.rdata.Rdata): - """RRSIG record""" - - __slots__ = [ - "type_covered", - "algorithm", - "labels", - "original_ttl", - "expiration", - "inception", - "key_tag", - "signer", - "signature", - ] - - def __init__( - self, - rdclass, - rdtype, - type_covered, - algorithm, - labels, - original_ttl, - expiration, - inception, - key_tag, - signer, - signature, - ): - super().__init__(rdclass, rdtype) - self.type_covered = self._as_rdatatype(type_covered) - self.algorithm = dns.dnssectypes.Algorithm.make(algorithm) - self.labels = self._as_uint8(labels) - self.original_ttl = self._as_ttl(original_ttl) - self.expiration = self._as_uint32(expiration) - self.inception = self._as_uint32(inception) - self.key_tag = self._as_uint16(key_tag) - self.signer = self._as_name(signer) - self.signature = self._as_bytes(signature) - - def covers(self): - return self.type_covered - - def to_text(self, origin=None, relativize=True, **kw): - return "%s %d %d %d %s %s %d %s %s" % ( - dns.rdatatype.to_text(self.type_covered), - self.algorithm, - self.labels, - self.original_ttl, - posixtime_to_sigtime(self.expiration), - posixtime_to_sigtime(self.inception), - self.key_tag, - self.signer.choose_relativity(origin, relativize), - dns.rdata._base64ify(self.signature, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - type_covered = dns.rdatatype.from_text(tok.get_string()) - algorithm = dns.dnssectypes.Algorithm.from_text(tok.get_string()) - labels = tok.get_int() - original_ttl = tok.get_ttl() - expiration = sigtime_to_posixtime(tok.get_string()) - inception = sigtime_to_posixtime(tok.get_string()) - key_tag = tok.get_int() - signer = tok.get_name(origin, relativize, relativize_to) - b64 = tok.concatenate_remaining_identifiers().encode() - signature = base64.b64decode(b64) - return cls( - rdclass, - rdtype, - type_covered, - algorithm, - labels, - original_ttl, - expiration, - inception, - key_tag, - signer, - signature, - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack( - "!HBBIIIH", - self.type_covered, - self.algorithm, - self.labels, - self.original_ttl, - self.expiration, - self.inception, - self.key_tag, - ) - file.write(header) - self.signer.to_wire(file, None, origin, canonicalize) - file.write(self.signature) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("!HBBIIIH") - signer = parser.get_name(origin) - signature = parser.get_remaining() - return cls(rdclass, rdtype, *header, signer, signature) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/RT.py b/venv/Lib/site-packages/dns/rdtypes/ANY/RT.py deleted file mode 100644 index 5a4d45c..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/RT.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.mxbase - - -@dns.immutable.immutable -class RT(dns.rdtypes.mxbase.UncompressedDowncasingMX): - """RT record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/SMIMEA.py b/venv/Lib/site-packages/dns/rdtypes/ANY/SMIMEA.py deleted file mode 100644 index 55d87bf..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/SMIMEA.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import dns.immutable -import dns.rdtypes.tlsabase - - -@dns.immutable.immutable -class SMIMEA(dns.rdtypes.tlsabase.TLSABase): - """SMIMEA record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/SOA.py b/venv/Lib/site-packages/dns/rdtypes/ANY/SOA.py deleted file mode 100644 index 09aa832..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/SOA.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata - - -@dns.immutable.immutable -class SOA(dns.rdata.Rdata): - """SOA record""" - - # see: RFC 1035 - - __slots__ = ["mname", "rname", "serial", "refresh", "retry", "expire", "minimum"] - - def __init__( - self, rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum - ): - super().__init__(rdclass, rdtype) - self.mname = self._as_name(mname) - self.rname = self._as_name(rname) - self.serial = self._as_uint32(serial) - self.refresh = self._as_ttl(refresh) - self.retry = self._as_ttl(retry) - self.expire = self._as_ttl(expire) - self.minimum = self._as_ttl(minimum) - - def to_text(self, origin=None, relativize=True, **kw): - mname = self.mname.choose_relativity(origin, relativize) - rname = self.rname.choose_relativity(origin, relativize) - return "%s %s %d %d %d %d %d" % ( - mname, - rname, - self.serial, - self.refresh, - self.retry, - self.expire, - self.minimum, - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - mname = tok.get_name(origin, relativize, relativize_to) - rname = tok.get_name(origin, relativize, relativize_to) - serial = tok.get_uint32() - refresh = tok.get_ttl() - retry = tok.get_ttl() - expire = tok.get_ttl() - minimum = tok.get_ttl() - return cls( - rdclass, rdtype, mname, rname, serial, refresh, retry, expire, minimum - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.mname.to_wire(file, compress, origin, canonicalize) - self.rname.to_wire(file, compress, origin, canonicalize) - five_ints = struct.pack( - "!IIIII", self.serial, self.refresh, self.retry, self.expire, self.minimum - ) - file.write(five_ints) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - mname = parser.get_name(origin) - rname = parser.get_name(origin) - return cls(rdclass, rdtype, mname, rname, *parser.get_struct("!IIIII")) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/SPF.py b/venv/Lib/site-packages/dns/rdtypes/ANY/SPF.py deleted file mode 100644 index 1df3b70..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/SPF.py +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.txtbase - - -@dns.immutable.immutable -class SPF(dns.rdtypes.txtbase.TXTBase): - """SPF record""" - - # see: RFC 4408 diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/SSHFP.py b/venv/Lib/site-packages/dns/rdtypes/ANY/SSHFP.py deleted file mode 100644 index d2c4b07..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/SSHFP.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii -import struct - -import dns.immutable -import dns.rdata -import dns.rdatatype - - -@dns.immutable.immutable -class SSHFP(dns.rdata.Rdata): - """SSHFP record""" - - # See RFC 4255 - - __slots__ = ["algorithm", "fp_type", "fingerprint"] - - def __init__(self, rdclass, rdtype, algorithm, fp_type, fingerprint): - super().__init__(rdclass, rdtype) - self.algorithm = self._as_uint8(algorithm) - self.fp_type = self._as_uint8(fp_type) - self.fingerprint = self._as_bytes(fingerprint, True) - - def to_text(self, origin=None, relativize=True, **kw): - kw = kw.copy() - chunksize = kw.pop("chunksize", 128) - return "%d %d %s" % ( - self.algorithm, - self.fp_type, - dns.rdata._hexify(self.fingerprint, chunksize=chunksize, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - algorithm = tok.get_uint8() - fp_type = tok.get_uint8() - fingerprint = tok.concatenate_remaining_identifiers().encode() - fingerprint = binascii.unhexlify(fingerprint) - return cls(rdclass, rdtype, algorithm, fp_type, fingerprint) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack("!BB", self.algorithm, self.fp_type) - file.write(header) - file.write(self.fingerprint) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("BB") - fingerprint = parser.get_remaining() - return cls(rdclass, rdtype, header[0], header[1], fingerprint) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/TKEY.py b/venv/Lib/site-packages/dns/rdtypes/ANY/TKEY.py deleted file mode 100644 index 75f6224..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/TKEY.py +++ /dev/null @@ -1,142 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import struct - -import dns.exception -import dns.immutable -import dns.rdata - - -@dns.immutable.immutable -class TKEY(dns.rdata.Rdata): - """TKEY Record""" - - __slots__ = [ - "algorithm", - "inception", - "expiration", - "mode", - "error", - "key", - "other", - ] - - def __init__( - self, - rdclass, - rdtype, - algorithm, - inception, - expiration, - mode, - error, - key, - other=b"", - ): - super().__init__(rdclass, rdtype) - self.algorithm = self._as_name(algorithm) - self.inception = self._as_uint32(inception) - self.expiration = self._as_uint32(expiration) - self.mode = self._as_uint16(mode) - self.error = self._as_uint16(error) - self.key = self._as_bytes(key) - self.other = self._as_bytes(other) - - def to_text(self, origin=None, relativize=True, **kw): - _algorithm = self.algorithm.choose_relativity(origin, relativize) - text = "%s %u %u %u %u %s" % ( - str(_algorithm), - self.inception, - self.expiration, - self.mode, - self.error, - dns.rdata._base64ify(self.key, 0), - ) - if len(self.other) > 0: - text += f" {dns.rdata._base64ify(self.other, 0)}" - - return text - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - algorithm = tok.get_name(relativize=False) - inception = tok.get_uint32() - expiration = tok.get_uint32() - mode = tok.get_uint16() - error = tok.get_uint16() - key_b64 = tok.get_string().encode() - key = base64.b64decode(key_b64) - other_b64 = tok.concatenate_remaining_identifiers(True).encode() - other = base64.b64decode(other_b64) - - return cls( - rdclass, rdtype, algorithm, inception, expiration, mode, error, key, other - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.algorithm.to_wire(file, compress, origin) - file.write( - struct.pack("!IIHH", self.inception, self.expiration, self.mode, self.error) - ) - file.write(struct.pack("!H", len(self.key))) - file.write(self.key) - file.write(struct.pack("!H", len(self.other))) - if len(self.other) > 0: - file.write(self.other) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - algorithm = parser.get_name(origin) - inception, expiration, mode, error = parser.get_struct("!IIHH") - key = parser.get_counted_bytes(2) - other = parser.get_counted_bytes(2) - - return cls( - rdclass, rdtype, algorithm, inception, expiration, mode, error, key, other - ) - - # Constants for the mode field - from RFC 2930: - # 2.5 The Mode Field - # - # The mode field specifies the general scheme for key agreement or - # the purpose of the TKEY DNS message. Servers and resolvers - # supporting this specification MUST implement the Diffie-Hellman key - # agreement mode and the key deletion mode for queries. All other - # modes are OPTIONAL. A server supporting TKEY that receives a TKEY - # request with a mode it does not support returns the BADMODE error. - # The following values of the Mode octet are defined, available, or - # reserved: - # - # Value Description - # ----- ----------- - # 0 - reserved, see section 7 - # 1 server assignment - # 2 Diffie-Hellman exchange - # 3 GSS-API negotiation - # 4 resolver assignment - # 5 key deletion - # 6-65534 - available, see section 7 - # 65535 - reserved, see section 7 - SERVER_ASSIGNMENT = 1 - DIFFIE_HELLMAN_EXCHANGE = 2 - GSSAPI_NEGOTIATION = 3 - RESOLVER_ASSIGNMENT = 4 - KEY_DELETION = 5 diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/TLSA.py b/venv/Lib/site-packages/dns/rdtypes/ANY/TLSA.py deleted file mode 100644 index 4dffc55..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/TLSA.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import dns.immutable -import dns.rdtypes.tlsabase - - -@dns.immutable.immutable -class TLSA(dns.rdtypes.tlsabase.TLSABase): - """TLSA record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/TSIG.py b/venv/Lib/site-packages/dns/rdtypes/ANY/TSIG.py deleted file mode 100644 index 7942382..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/TSIG.py +++ /dev/null @@ -1,160 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import struct - -import dns.exception -import dns.immutable -import dns.rcode -import dns.rdata - - -@dns.immutable.immutable -class TSIG(dns.rdata.Rdata): - """TSIG record""" - - __slots__ = [ - "algorithm", - "time_signed", - "fudge", - "mac", - "original_id", - "error", - "other", - ] - - def __init__( - self, - rdclass, - rdtype, - algorithm, - time_signed, - fudge, - mac, - original_id, - error, - other, - ): - """Initialize a TSIG rdata. - - *rdclass*, an ``int`` is the rdataclass of the Rdata. - - *rdtype*, an ``int`` is the rdatatype of the Rdata. - - *algorithm*, a ``dns.name.Name``. - - *time_signed*, an ``int``. - - *fudge*, an ``int`. - - *mac*, a ``bytes`` - - *original_id*, an ``int`` - - *error*, an ``int`` - - *other*, a ``bytes`` - """ - - super().__init__(rdclass, rdtype) - self.algorithm = self._as_name(algorithm) - self.time_signed = self._as_uint48(time_signed) - self.fudge = self._as_uint16(fudge) - self.mac = self._as_bytes(mac) - self.original_id = self._as_uint16(original_id) - self.error = dns.rcode.Rcode.make(error) - self.other = self._as_bytes(other) - - def to_text(self, origin=None, relativize=True, **kw): - algorithm = self.algorithm.choose_relativity(origin, relativize) - error = dns.rcode.to_text(self.error, True) - text = ( - f"{algorithm} {self.time_signed} {self.fudge} " - + f"{len(self.mac)} {dns.rdata._base64ify(self.mac, 0)} " - + f"{self.original_id} {error} {len(self.other)}" - ) - if self.other: - text += f" {dns.rdata._base64ify(self.other, 0)}" - return text - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - algorithm = tok.get_name(relativize=False) - time_signed = tok.get_uint48() - fudge = tok.get_uint16() - mac_len = tok.get_uint16() - mac = base64.b64decode(tok.get_string()) - if len(mac) != mac_len: - raise SyntaxError("invalid MAC") - original_id = tok.get_uint16() - error = dns.rcode.from_text(tok.get_string()) - other_len = tok.get_uint16() - if other_len > 0: - other = base64.b64decode(tok.get_string()) - if len(other) != other_len: - raise SyntaxError("invalid other data") - else: - other = b"" - return cls( - rdclass, - rdtype, - algorithm, - time_signed, - fudge, - mac, - original_id, - error, - other, - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.algorithm.to_wire(file, None, origin, False) - file.write( - struct.pack( - "!HIHH", - (self.time_signed >> 32) & 0xFFFF, - self.time_signed & 0xFFFFFFFF, - self.fudge, - len(self.mac), - ) - ) - file.write(self.mac) - file.write(struct.pack("!HHH", self.original_id, self.error, len(self.other))) - file.write(self.other) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - algorithm = parser.get_name() - time_signed = parser.get_uint48() - fudge = parser.get_uint16() - mac = parser.get_counted_bytes(2) - (original_id, error) = parser.get_struct("!HH") - other = parser.get_counted_bytes(2) - return cls( - rdclass, - rdtype, - algorithm, - time_signed, - fudge, - mac, - original_id, - error, - other, - ) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/TXT.py b/venv/Lib/site-packages/dns/rdtypes/ANY/TXT.py deleted file mode 100644 index 6d4dae2..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/TXT.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.txtbase - - -@dns.immutable.immutable -class TXT(dns.rdtypes.txtbase.TXTBase): - """TXT record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/URI.py b/venv/Lib/site-packages/dns/rdtypes/ANY/URI.py deleted file mode 100644 index 2efbb30..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/URI.py +++ /dev/null @@ -1,79 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# Copyright (C) 2015 Red Hat, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdtypes.util - - -@dns.immutable.immutable -class URI(dns.rdata.Rdata): - """URI record""" - - # see RFC 7553 - - __slots__ = ["priority", "weight", "target"] - - def __init__(self, rdclass, rdtype, priority, weight, target): - super().__init__(rdclass, rdtype) - self.priority = self._as_uint16(priority) - self.weight = self._as_uint16(weight) - self.target = self._as_bytes(target, True) - if len(self.target) == 0: - raise dns.exception.SyntaxError("URI target cannot be empty") - - def to_text(self, origin=None, relativize=True, **kw): - return '%d %d "%s"' % (self.priority, self.weight, self.target.decode()) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - priority = tok.get_uint16() - weight = tok.get_uint16() - target = tok.get().unescape() - if not (target.is_quoted_string() or target.is_identifier()): - raise dns.exception.SyntaxError("URI target must be a string") - return cls(rdclass, rdtype, priority, weight, target.value) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - two_ints = struct.pack("!HH", self.priority, self.weight) - file.write(two_ints) - file.write(self.target) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (priority, weight) = parser.get_struct("!HH") - target = parser.get_remaining() - if len(target) == 0: - raise dns.exception.FormError("URI target may not be empty") - return cls(rdclass, rdtype, priority, weight, target) - - def _processing_priority(self): - return self.priority - - def _processing_weight(self): - return self.weight - - @classmethod - def _processing_order(cls, iterable): - return dns.rdtypes.util.weighted_processing_order(iterable) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/WALLET.py b/venv/Lib/site-packages/dns/rdtypes/ANY/WALLET.py deleted file mode 100644 index ff46476..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/WALLET.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import dns.immutable -import dns.rdtypes.txtbase - - -@dns.immutable.immutable -class WALLET(dns.rdtypes.txtbase.TXTBase): - """WALLET record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/X25.py b/venv/Lib/site-packages/dns/rdtypes/ANY/X25.py deleted file mode 100644 index 2436ddb..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/X25.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class X25(dns.rdata.Rdata): - """X25 record""" - - # see RFC 1183 - - __slots__ = ["address"] - - def __init__(self, rdclass, rdtype, address): - super().__init__(rdclass, rdtype) - self.address = self._as_bytes(address, True, 255) - - def to_text(self, origin=None, relativize=True, **kw): - return f'"{dns.rdata._escapify(self.address)}"' - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - address = tok.get_string() - return cls(rdclass, rdtype, address) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - l = len(self.address) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(self.address) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - address = parser.get_counted_bytes() - return cls(rdclass, rdtype, address) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/ZONEMD.py b/venv/Lib/site-packages/dns/rdtypes/ANY/ZONEMD.py deleted file mode 100644 index c90e3ee..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/ZONEMD.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import binascii -import struct - -import dns.immutable -import dns.rdata -import dns.rdatatype -import dns.zonetypes - - -@dns.immutable.immutable -class ZONEMD(dns.rdata.Rdata): - """ZONEMD record""" - - # See RFC 8976 - - __slots__ = ["serial", "scheme", "hash_algorithm", "digest"] - - def __init__(self, rdclass, rdtype, serial, scheme, hash_algorithm, digest): - super().__init__(rdclass, rdtype) - self.serial = self._as_uint32(serial) - self.scheme = dns.zonetypes.DigestScheme.make(scheme) - self.hash_algorithm = dns.zonetypes.DigestHashAlgorithm.make(hash_algorithm) - self.digest = self._as_bytes(digest) - - if self.scheme == 0: # reserved, RFC 8976 Sec. 5.2 - raise ValueError("scheme 0 is reserved") - if self.hash_algorithm == 0: # reserved, RFC 8976 Sec. 5.3 - raise ValueError("hash_algorithm 0 is reserved") - - hasher = dns.zonetypes._digest_hashers.get(self.hash_algorithm) - if hasher and hasher().digest_size != len(self.digest): - raise ValueError("digest length inconsistent with hash algorithm") - - def to_text(self, origin=None, relativize=True, **kw): - kw = kw.copy() - chunksize = kw.pop("chunksize", 128) - return "%d %d %d %s" % ( - self.serial, - self.scheme, - self.hash_algorithm, - dns.rdata._hexify(self.digest, chunksize=chunksize, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - serial = tok.get_uint32() - scheme = tok.get_uint8() - hash_algorithm = tok.get_uint8() - digest = tok.concatenate_remaining_identifiers().encode() - digest = binascii.unhexlify(digest) - return cls(rdclass, rdtype, serial, scheme, hash_algorithm, digest) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack("!IBB", self.serial, self.scheme, self.hash_algorithm) - file.write(header) - file.write(self.digest) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("!IBB") - digest = parser.get_remaining() - return cls(rdclass, rdtype, header[0], header[1], header[2], digest) diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__init__.py b/venv/Lib/site-packages/dns/rdtypes/ANY/__init__.py deleted file mode 100644 index 647b215..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/ANY/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Class ANY (generic) rdata type classes.""" - -__all__ = [ - "AFSDB", - "AMTRELAY", - "AVC", - "CAA", - "CDNSKEY", - "CDS", - "CERT", - "CNAME", - "CSYNC", - "DLV", - "DNAME", - "DNSKEY", - "DS", - "EUI48", - "EUI64", - "GPOS", - "HINFO", - "HIP", - "ISDN", - "L32", - "L64", - "LOC", - "LP", - "MX", - "NID", - "NINFO", - "NS", - "NSEC", - "NSEC3", - "NSEC3PARAM", - "OPENPGPKEY", - "OPT", - "PTR", - "RESINFO", - "RP", - "RRSIG", - "RT", - "SMIMEA", - "SOA", - "SPF", - "SSHFP", - "TKEY", - "TLSA", - "TSIG", - "TXT", - "URI", - "WALLET", - "X25", - "ZONEMD", -] diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AFSDB.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AFSDB.cpython-310.pyc deleted file mode 100644 index 50befc16da59f9b36a453de05fd8725092a9ca03..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 783 zcmZ`%O>fgc5Z(3XHi|2?LKO#)dO;#cBoaqdp_T@?w7FE3U}ed2ywiNt_L^NMZ6Y|e zf2M!Q7Y>{_bK}IU?Wj4xNHe?RxASJ-cx4cD2-=e$&!^u#LVlWL+gwbJ(e)b)f(V)t zPV3d;6zJTZ+nPh^IFQEL!Gd6Orx ep5>GC&vlc3-K%0pjly^4ooJ(h?J?@v&*)!qN4Zx3 diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AMTRELAY.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AMTRELAY.cpython-310.pyc deleted file mode 100644 index c25baa0e947e1021c04693a63e4ddd125ab68496..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2542 zcmZuzZExE)5GEx`mgJYZSr)9_TBO^$LBN)*8-@)-*Y&*v)*3^T4X9v1P({X-BU>J& zycseEECKpA;(hC1;+K8cr~HLtKzB#kang-8Pb76DkIy}KRMu>I1j_PXS6+PGB;;@G zoGlh~ZbQv~1;GiYDG9144Gi5kXHOOwj|exoc|^D=jK0;k`?W(eaG>q>U3ka11@A2A zd;R*Mc}Rl>ryIn#Phf4*iBX;{CUkB?%|8GkNI*G(y=Y(xR_y~TSe(HMma?9TG&&f! z?mXFi`rz@MXR8wXF@>4)f^Dq#pyoD+lJv<2c||)u4Qjop5PQ*qPZi5Wy7h`kJo@XO z?|s+(B^NU9j(XWZbnlCNyU0e}$M+xXMrn6f40pSaljq$$Da7ZaDBg~GBJc8HzAkxj zFcSItozAoMxm9bU17&H;@JP7MYB3fo(q z<;(#YUzoSRVR0t8&y+WUrr=^23$?_PJkEB7JP5NnbY z+{y2QD99l>rX?+nsX<9$lvZgU8WX!D$7X3xX-Pr`ZL4IuZI{4W7<1t1!qeqI5s9n$ zp0e^C*c1Je43i=ZHH?89MtQiC42y4N3-kg9`_Hp1l^39^m^QQxO>M1TlW3o+Ngk(B zo-4Z|ik_=y$Wz@{RJmcO)nGH^qtrfKf|d_8Z-8i-9&NzSfjYi8hjVRiV`no)>*oa* z!TJ-_{4)>*h5?|^Hx3OzMB_AJ97h0`zNO!?Ew%zU_(o@3zs^@@|J=7V0t=%pE_*QjZJCjK-8CKpalHFu1l(D_{HgWa&-UGY7LIV-c6>3nXe+ISx8MjYQINR!+ z`|B_PDR2*G4?&dXF`1G{ZT56Zhtq8)mkQd4<8ot4|DXjcokKctW;$-^auakup6LKF zK*u_^OSd#jh6I{g6R#u)R#__@822F6*_enrCzxW!ZLvQRaghvrt6!{Ua`nc^?>PMa zVmKPE0%b%`$km(Quip6b8{Y}so+v6NDHBqNa>afuH0@P=<6u}s`wyhdq+*&~7}?6* zlG&hw9MA37l^LhGT!yxM7ZuDR+m@IB+6N9IMKP<9^n-)HNJAr%%({4h|(JKyf zG|^BZ;g-NTEy~`EmrmVsYS6F&wR!_(zYq}@@-46+HO$s~ z0*mXE+oo;m(W~b|bEb0+9~UN|MH(MWT*yXFr?hKKtchLF(&okw1bAA5midIh7zV73 zoCLg_86PcRq+L3FruoP^@)KA~UPo~Sgl`2NvaEteUc+%sq_*}OLJ^K42{&Gqtz7vL zsx0_q&)#ZEVSFwC|KC_%2bB$|I+j}o=Bd`4G?&hk=FH}hX*R*Jn;j6HhgJSMNARn>Lg9EjpY#wC(iuAxACRCAV9W09uw%!*`{ zD=3hr5WOlDCW?GU*MHE<1@u9apLp*Ib+N_+L)z`u; T%t0D(=b~d^q^_8@bD91NNUk?q diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AVC.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/AVC.cpython-310.pyc deleted file mode 100644 index 79e4ec5d266690764d3bb76cbf4938508e2823e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmYjN%}xR_5N@{%TZtqZjVDdKau5=a#uyNc2MHI^Xw#%A+Xh+o&+S6QE53}cv=OMKO9h-Zs5u8vNZ}AMT)qy&8V4jGw@5jP zd>}=@cY{h$U6Lhcp2GL2;r>7$8u%8s1%uNDHG2TM2WXG%y VzAWhFYWFL9Lt{g9pW-Sx#(!zxaQ6TJ diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CAA.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CAA.cpython-310.pyc deleted file mode 100644 index 2a02bef0607e3365fd6b2bbe482b1761b635a71e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2009 zcmZ8iUvC>l5Z}H3=h!7_(-w*ec^$pegz~{X6_uv&004*yF2@5e)F4g+3BQ;Zr|?;Dpnh#7$3Qs~+2n-dXf+Yzb@M+xLDT+~W2r;Wmu@{ouqtp>fFROA)IF-is5YGCO#?BiupxoxpX%M@7o%=jErLiac(B&IE_7_!a&^J>Pmm91^d={hP+#-rAae4WfH*TS%P^vNX|IS#-B1dasn3 zK04Q?^?cNoA}uA4Y~v2{WT=d-lc8}BlYAmlZ^a4J5j7h=^$dh2CuBw|T3K_8l8Vf% z%AV7TFdKBIayaGI9CYSZ&di$=bzA!!u=)dRVBM{415OaP-p<>1aOCtRT;9!8w-i;(~QL-OB9=Ah5kn3o0{?NkrqlK-p0>VlEZ$}`URbN zB4sHhdJuWWQ6e80U-C3hlro;=`UpfiXXM}K+YkFcD9ma&=U(=9Qhd~TL&q=>&*4*_g5Ut=KGAgFngP`N&YUiF0C-^E zKzOa*v~_pVy{o!+?y5VHSNmyfc$sk}Pjmv<36&<}Y;bhpe&onCxWRZpn_*U%mJ~T~ z<}jNIV;#Jb>#*2}4K(w0$+UQ_KZk+B=~JpV;_1t2TFk+tmt7ykZ_e>1yy+Bz9eU~2h1Tc|26vtnpGQKTgoQOnqA zt|THYJ0O7L<$>J9;dKyk=fX3l%S$Y{>}NQT<*4@bE7+?rj)8-ILg+f^=W_jNiflV? z=;qSZUtv(u83b+ybpQfq&#gJ7L_46nC-m5@Ty7l@b^RHEe7Uf68#|mqOWd>2J=E)L zvU^kOlSgj}1*-eTeFa%Bj0c!ZQf(Y0=7IpZC|1JlHQ{y!SuRYFmZPy0O4Tr#cA6Ar z0ktH@=+pc%C;{NcUS(1|1jlMhZ_*ZEa<##wq4dJ!Jya0BB`Wt2m4*Or6ZB&bdL)6r z2)tW)m5+g!AA)gY%a5RoH!$dFIVrT@tS$j@2dAVMB~UGjVHC)Z!El8F-Z+tv%MAYr zQExN$`vl5Wv*I(x%M_-e{;0gvim|$2$eVDpS*uIZNI*g7@;18l8HxzkI*Wppiadu+ z7dd(bO)ycV1>zQb>IR5_I2O>?Y6X^WS?zbw2b;9EiCVG?7I6pa#C`EP6=VD(kyn>< z*=RJ;$!;#--w#ZhN>W=xdWiyJ|~lJ9`LMB$@@ N4R}&r8$J6L{U5zR-u3_h diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CDNSKEY.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CDNSKEY.cpython-310.pyc deleted file mode 100644 index 0bd98f8576ef13d22343ac929e2006d77d2fca41..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 541 zcmYjN%TB^T6rJf5T8bD=h%1e5yAbxq7!;}tNHG#km^7IbW`aOpc7O!8_%nWrztD{f zSN?)4@03Ql$$h_1T&r0KsQ!8K{GlWCrJP+Vfztw(w;(v;I6xHVTFbQ-Xd$5_)Tthp zXbB^MXXRP>4spWuH^g=DjhQ*CY{&*vi{k;ZOW!aHxi-nl56)A+>ttl$+-ExNyUtjp zb_s*i0+t6LM82GA98JhJu?}L{7^8KS&W4-Uk1wF zW9((=2SvtUjK^cf-chQM$i+{;ec?SykxDO_#G&vyLe3X);`KVt$`8Dih*n;2I`ZUn zAGz^yue-sG# zDw6a_#fm`O;&P>M PmI?v$(8P68t{mfE2v~&B diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CDS.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CDS.cpython-310.pyc deleted file mode 100644 index 7ee1f8033ba41420365afb11b414ce52d39171d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 547 zcmYjOOH0E*5Z*`HZle_x=}Ez(J=lUr5%E#+VCkiJa0x6)cBzR;6L-@>z3R>1;laO@ ziw95r3m(+jv``1;oA)=&Zq{nK2xRwj|KZI+=*tHGr3S${s5u6ZNa6%>Tv@`g!ZD5M z4U$CCS0pLKPF#!YFZ2cThQuS(aTYL#hM~p(LLoQ@HHQGI;^ahPP9vl$j<^xCcWjv> z{Ej)34zSfqdet92y8s7Tg_)Kb!~DX+u+uD=5EDODLX@r$X(p$M^*4ohn)=DA(hx#s zA*89Cn6jZ|G0&AL>(T_iQDwb9x&+JHLPld{3X!PExOfo3T-e4Bq&Hz%1>d(#4GVV3 a`hca^f?UZ?m(O)(pVC-nw#{&z?%_X;KtOn}dKTLf)vB-d<-Pa4SDn>rz6NRb_tQ^*t7+OF z*w~#a(6|O!ya1pYB|R-DOA-*()&oP8=BTtrr9CPgD0OO3lUmfK4t1$VeOjT_7k=Q< z8m-dVnR z7H&5Dmjw2CsUsK&CW3`vBRB{y!aoTA0`MvVs88c{gaZgO2nP`kAsj}SMK}V`@Hrm9 z@c@noa6EwH0UQtDcmVeh&^{c^5aYeZ30LFddB}gB0m!v&QfNc6K?<$BEPCYJJS(7J!~)=JcCt*~^Zbw62bi6m#|2T{Bfb(m<;R9xf~4-pryH-ES|f9v7n z3xhQ|Gdj7=vwoPfXZaPpHwx(!mza?G95nt{M1B-T`7rT^4BfVB(Ry|SwLc-_7(w3xaoRBD zOw4$mw39f>S%`X+&JtS-^Qa@esMpDOl0WUs%C1>4@@1T`juId>#0`L4+eBiJLLcfx zE3|FBFor;s&`@<#)lH~dg{A5?)Sbdsb(d<7Mq2lzC6)(_OE(OYG|9s-@WV)i%fOyX zSNJ<{6n_^W@W#EL^Y*F8MOuLakGicZl@DP)!TN zsYUq*u+e?U0)3-yR0)1FWWA>7Hojo zuGzJ=K?PlBNTB6*J*fL_l4ynTEBTqU&7+`_hTdGSoD*~B=p3SGR1}w{B1i)qK~?|+ zQ!Xc@cYR_#XT(G$sI)kZ@(8rK7zuXea?)Na6=m@c;gZq@lXsF-`keKmJXuNBnben7 z%d_?}onM9pPf$FJLO#*qGfADy68rDc6AFMQ~&6dH1^a0<8Zipr)v=1)cWci=t^peWPtC}u3 z1O)T}*Xv5nlk4A(k#^&R;T^Nm^hZ#^pbg{$>OlsN?3zP!!zxJWjo`0X)4Je|1Rh-o z<3K#~?A^OJz>REB<8qu!6NB%*n@ejI0tG9HWS2xT+ewc}H_rM4&V*1(kkvR!vlOCD z4|!$7NIQA9Pg-z!pv`K+Sprv9K8LI_U;DOqHgjnxG11JN35JS>3HmnU> zkqc*>N-q0s}0YQTra%aMThR0PTpPJSlL>wNh(z=s?G>s(wy) zX*ueRMw~FDSq$9})I=}K1q3w=Wy)_Mreiqlv;1jB6~Xu&99sa8wNVs|S+6&agv$3X z;uL)4_&I=^kOjV!u4d}4S=D_{_jJAb+V^#5mZ&+68U7{CzXkw*PN}%CD@t+n!=Q$} z>{-kPd6K1NGwJu2^JuZh;Li+3%b2AmfuvZ%+}{i;;nH~6!oUNHBdOI$EW`RN8mwY{JHO0Vzj!Iu5Xt-FrxoFxANl@5lb diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CNAME.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/CNAME.cpython-310.pyc deleted file mode 100644 index 5cab356b41424dc1abef4ca88e31f3c581e3a534..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 670 zcmYjP&5GMF5SHxxxS@fzl%879HPB6<$EB40$x;ftzAQb|7=&z1VrON^YuPUDb^9`X zfxb&~>7l2-LQfqlhU|bwnwf7tX+~q_^BF;T`TI@wb419W-gqoyG|q6@cc>(hRFR0f z-HRyDoxk%x66s0*JCQ!xquqEndGH@-G?nz0EJlAZkA!Kj9}7j}43~X|3LIzTNgDam z!z_P4z6{TAuD<=8Sm7L8ON@!|0WkS`NX|@?V0CLOBW|OD6P^x2s*<5cG)JC(q zE8#7Z+Lj$=XiQY*t94A;=#wLGxJimySg0*aAQg=TW}7r)&Xb82&<&cUrYMY7oufgJ zWJ$*^K80&0v}C5vpki7SV4-TEvTS22ri?(CP(r8pxMjE)?E}tx6zBUH=Y^4t>d#L( zzi)&ZB2&(#Njd*PswuY0sed<@r}1Ybw{f{O1;lHxceN?w>-AMDRNR7YzEV~jzGaF8rm1hya&2NWTLLkJ@5AvTAMRvL|`+s>?KXO`|> zJF&*6wdB{Zx%rj)!hsX7zy+#$*4`!bs;hshwx+)Ny1J`Qr$wNx{_*hjWkkrIxR`Gq zEOwx)6A+wmT9CLIY0T`}nU3ys^roXf9fOz&HV6mdkAySsToCTSIvTVF3lnETTutoXRVc{@pd8>huo6X~}jVa;xc48gM%fB&-kP5)OVr0S23 zs-fsV73x@5qyCGhKb)jR|3s80{TKN`U*%eSF-o)J^hl^aFV(i>=uvHd*L$^XBiS0g zl?)s|z}Q_7Aqkn?`5#2oVpB1Qd5A}l%-?D3UXnw~9qwL)vB#Hrz{3j~`yz-ueve1I zbwMG;Az$Hb-T_S{0)C$_@+G_9x+E@%7a&=y(t!`0wQYPGQe>6nm_Y!Xr-ktji}XmD z;509Jb*eHSW12RcW0>ebJqMx5gj~^@*6f;5Qj;rIJJ+-(i34-DcJ18Le(mXC!qfvD z)ZT=idpfMWK{P?jh?6~XLwntp@zi)EBr=zmxlWR}m82>e=cRu9mBh0<+xYTpxd0oc zm8-l|IxRC{vuZp&9u-2iLD}_UtK34a@|(O0;;RX90tH1w0zRlKD|ynwAtrs`HclOc-{2 zYFul6ca)_C@;>}y8@fG!i*$vabs7Lu_gMhS+lF~Yo_C?E&p_196@j<|7%7aQW>*ff zd>+*VnXiL7tfPsyM`Q=gyKdY%5_(G8Yz~ZJA(-e;Rzr&l7R7Jh z@&gcYX9h0O)hr3dKd{w4E7=Ao7TIIy3h{?-2y_8iOAXe$&pykLpxcIXgm2+~4wIT* z5e-z$Xu1ZllxPnq^MS;mrnt7p7Kn2m{q(#W8t+uXZ2(oI}@r=_LIX%s# zxMk8k%nM<{tQwA_P|CtL?JO;;GSAWihmh_q#fuAgIr{mx3xLm=D)*w`(3BE-viNm)*QLE#Cns+r9=-VND^LU zaNk2=tD@2h3LDE=VkwvfTkAuiUsqh>p^;eT5`!?E=}nM{qPV>cY_RX4i7h9r^+(Xv z8i79S80ow!;mImhvzHHtW1Sup0&ZKBh$jWFJ=lUr5vjW3!O}}nFa$!n3ANk(a`fH z6!}Do0C%HSbk!$hen~rUBf^I;N}28*P6^xm=Wc`6sbrseEDbtoEJLG z3N`Aw6%`_ti58-23z1}M5!-lQi1&qzn~E=l%0eN&P~n4e4S!GfSNz%N!ti{WC7K7? z%*!n2!{A{lW4_esk`HGSZf2#v$YnT}Q*F3PO}|j(D%YleJ9_QIV|w|ja6tCNzT5?% zh&pwqOIZg7db1>1lyVYl*d#UV$mSZ6o-z|@G~3(u_)Up%$=pn@(ImQ2TxReUKJbp6X^rE z;P2(>yX@LXZL)T$YMITYx$RV&UChtcyvo+HS!Wl;A~QuN-?Tix?Hj(>)$kO?`+Hl8rKfvfgIt@R8_=hXS#Tri t!T&wckfPy`n_M@$MoN)h^`-X^To1M5u<`rHCw#yTCU!7SV;qu~_#XuKrAGh& diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/DNSKEY.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/DNSKEY.cpython-310.pyc deleted file mode 100644 index c293f9efda304e95e9dabdb365092475ff4caee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 538 zcmYjN%}&BV5Z>*!rGO-w5KkJt_8{DiF{o4zkYXg7uxYX>>;{4U*)1e^#h39(e1~2< zc=8oIIolFtlAYh3Z)U!@(WoJi=I8PAhmO#f3U*k7HZ;>7EBos}PWD-o@{{%q{Y zStiaBf3onWLV7%s?UZNhM9B7)J8GBvw32nII6P4&0Kv#YmR4l!I&DBtYZivf%pV5= zPKqQwRJkoq3;cyxk9}B1Q|l3>6bh~Ww^g>kf!)9Fv{sJ4R;_CO|9PcXhg@!5l(bwb QlBFWRIIJbcOA~`|`f`1r zg`D*4iVBeii4vmf2$5uR8JqY>h>v9uHx*Y1nT0}pqrwH<8vb4$Z~3cMh35GzOBDB% zUX)qR$KKN_i1|vTD?Xl2xt^EmIuF7{FjJb#R1XSSu5+aa50kfn=lAnP diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/EUI48.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/EUI48.cpython-310.pyc deleted file mode 100644 index b562e4eae8836fca431189963824837b805e7d62..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 523 zcmYjNJ4*vW5Z=Ar%bn4HsGx;H+7u=r79t{16GVt zVjn~?wE4&$Ro>Y<6^^2Jq`~J{NBW_`|74-jM%Hx%D0>P^QNffYIB>;wh~j%h*viH( zm6_cg+#H|0Zj_>)Lzw1jUcuTqGe8mgnC42E_%TR1t4bNCY8)ATL(1o|A1xz}lqwCS z6mBprKt_-Vw}6+zXrClE|0v<-_UhCdXvnpfJ)|*s9neojnt8oWcj8Ch1d@r@8wQ>p z7I2vP;gkOW+Ea;c<*Jxwpj#LH`&PMeGn?k-?-AiL6f$6j3xHf|k+}6lkCI*)36) zVjn~?w0Ym|S0-#ig`?;LIpQ;{Bi+#8Dp_bWk@X=0ls$!|s9?$x9JpdNqWB&Wwz9EH zWoow{@6Jx&H%oDtLzw1j=3?!P8K4MVOmn47{1~L1u1guGY8V-PQ_9z&A1xw|lqwCS z6mBpsKt_-Vw}7|8XkR2Z|0v=2{^s0!)R1d0dro8UTA&9-nt7d8d*nyn2$GT4=>?wd z6>yyS;lO_e?WsgJa#f5o(2c9^Q={Cto{e*J@-DJAYrBM7oNv+6d*q5LmeqT4JS_Ym z0(?WF#g6eUTGe6L3w#Y?ZJFdOV#4_kIymeav&yc^OXk`Jj-9#}^RHZ*kIgsPc4>v} F(?2~^f0Y0L diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/GPOS.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/GPOS.cpython-310.pyc deleted file mode 100644 index 7800e7ffb80315c06bbc4d48fb1cf7c191af6c56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3280 zcmai0UvC^q5%2E#yX#%YPMn+*IN?h;#0ruKBoI1|BapkC1Yx-&;ZCep8cn8Womr1} z_PWRRc^M;wjqXDrBrk9I7CiAG=H(uE%5&cC0rRV#nf2O&%dEP(x~saoy82gDn{~Tw zhHvA`H=lpH&e*?cu>3g~JV4VQfk-BK$_7=>2f~c4y0`1zK`*3r!Uk?E#@^WbkV#uQ zCrmmR`{UNJb<78C$)B*E`x3jde#EJ(KMTE&_7F|~3nXU+JLZz_2-VK{Sd6W|@B)_H zWK!%1eWT_r$iE5Rmh7+MCOg8aQ+v+TZONXnSqmdaI&(f0NBl^9$|fr|%iY5tb4I^r z-vd@~>0+mcg{b;QQqAj+3x4X&&CdGch0N&cpb!gL*vRN~YCW&7=$bF@68Rnx8onZO z?-dB^`K6V{lhTqCUAE%Sqj;Jp*`#be%GB-$N@c3_5-pSMBrhF3P0_VK3Ddo}lDRUD zG8y-*(mr?|=B1s+BPgn5`+5F?sjE2QtH%%D8U9|!N)M;o*={_1Kh`^WHXS~G|AYN7 z9qz}I{o&)}*-$5We0Lf~JK=V$hp^|qlKJ5@*7twW|HJ(cKl<&Hd(*@6Mu0_$4D&b` zrCFE`cGhDHsF#0 zReWG=vnkkM5+4?^qIXh;jyx@hH3t&$aR&E^&y>2-BSg7l{Qy@x? zEX>$O_ASGa><(l$WHx3TBfD!jlKlWO2Qmj}cMD5$DdyIZWkz;Avdze;M^5h1NwC7B zT}_W2I4iI!@C#@MtpfW6?ShS0j@-hP)(+Dn^!ARe(!4Y7o~}}4QB;nv9C?L@$YJ^b zy$6k>TEiy|6A7*U)0by(!!{aYfBxj34f9~uc^1m8#sj^Fy@Y=hnY9M3c*j+Gn$_iO9wU{ihKjt@$XH2#vo+)87HX zD*=6T_BZ5E@M4L#D*o>da4-5_@vWX+-DMT)&K-r>+n6Zb4A~`_lx-E0&-Rm9T#B88 z>Q`~S}LtP+flTq>VXWp=hg>#cIoXd z-=#HD*{-?G6Rb72@ojpTH9lK4w^=AWiYVxtk1n&g&?yE~*2YLv2v!6m0%qk`3?al% zMQ)wi62Uzea|%SvkS6hFO%>qPnzz4p4T7>><1U@^^RHdw(i#({R{td`Bb$l0e%bRB zJ&y5B=^QAOhtfqr?M0|FR410O;a1qNM@fo=7-hRt6>Dw$U3Q{yl1-8bWdl&*>1FTw zc!1y_QSlI`X^P1<5KfijVh?B6n6LFOxSAlgaP<;)kW&qYkQr+%RoHO~x9|u%>ibv; z^sEzlqHJ%H$FfQnJzr7XUILLj4HYVBg`uoW)_g$>JY{^@g+o$=Tfy_3R z?P${PYYn;GRO8p%K~Piw!;YpTG&}uqVbZc|8Yyz-)1K9T+6U=Bs?fAXwP_OW##Ebv zU^kO{De;{k_-rpsYl#;GGK(;c+Mv@c*QgCt5fuGVELTjq*p2h&nN;^_`X@x*A(=l_ z87g3YXdX|I-_&~~=+;#xiqo{IG$tp%O)945Tn9(6)|AbCW((i$i1wy%h3K5MeX-i% z!fkV5Q@hF)>GxLD577;}_*Zyu@h8=k%4#mz-QCN>XK6fWk&43q!?2Pd?Zy)XzB0vk q&^p(2DlO-Cq->5^!oztX@!zf7_a4Q9UL&K|eG@_mBg?&Zi~kp+_4|DQ diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/HINFO.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/HINFO.cpython-310.pyc deleted file mode 100644 index cc9436649394f5a8b4ff768362529d275d2553fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1824 zcmaJ?UvC>l5Z~SV z3d_R-;Y%R>9GD=2W+bX-8Zj$7^VyxxUc@9D`a}O)BA9T_iEuz}41+W0j7CjCe<5A> z3Qi-v1o`rC=Yo!4AxT69fm3PZ;7J1(xv$7R6|V5kgUAzWA`s1U8u_x(^u@Xe#mYH_ zI|6Z6w8bjyG-X3B_+9Fr6Z_dGp8gR2xNC5yMn-dPH*?>4VZSl%F~mvR8_!v znx}^IsL5l^_fCz}3a?NY1JHA|%=W8>5=jF51l zwN$!49uyw)h^V*4!Sf72hwnDRGJUEO~|fHE4)Hs$yJUi4%Iq} zcY#Ii8&9|?Zalv2QgdGwBkR;BU}oWIxh=X%r*~?{7W+GIr7=Q-WPQtEVIXyfP%baM z(i8NM=#}ruACT4;%s3aWV5K)>GYSb_Lr8ILZM-F$kN(%jLz{U4ToFphl)e9T*RLFi zkoBn8fbSv&14lM#b~Ug);3^OD~aLGF)Z1tnUezNqBeukTm{@%g;ge*&jipaT{l(D#>sUQ+9_-Y#~U z9?!J^BFI7Vfp@Ehv#$21YmKw}L8Ig9^*;0g%2AEFdlm+!hNx<}lWJ6E;}5 zL9I?VR1ZNTYC{WnEKd?SHffP7M6dpqjz$v`?`0DHL_no(5>^{3N#>9WDrzp2)EXLk jKVvJg=Py0ZKGQac;7J{lFCaOI#!tZ-Mj3y;^ML*bW&)(l diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/HIP.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/HIP.cpython-310.pyc deleted file mode 100644 index 5fad0c5ece2af23687eb9b76abbaa80acfc46520..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2675 zcmZuzTW{P%6rSR*P)aFKE(I-!6a*?2l!{9!MXgqd76jH-mgAXhyz$!G8E=|I zUI~;)@Edqq^VYvKFFf$XGjDyMoHO2}+p13H%$b=pw{O04&X(P7K;T>Z>*cLKLPGw= z#`0%F<8vtTClHJ;UQ9Fy;jVx}Bypi_}VFoh~2{WPXkAeg9 zfJPlgZ_#JV2y6XGBkMP^Ntwy4Loc$~3UirvNF#^4 zzRgZCp9O~$_VCy$3t1ONeD1R6*a>!0_Xocbi$opRe@&S;zWr`L0C8UMv=ppoDRV2U zl%M3oQe@TESee^=Pq~td9WG?*E}au~1j>XWZ-J=D0h!a9)<$DcQj@t+n~XA}F>4Y- znOn8hP|$5XW;5Ct&~l*V)*wfoZu^YD;mrP>e;&c2y+GM=I^jZjahw%d6~~buCoLFJ4rs+;leX=Kf*zZj!64`iyuF#O4plftL#POrs_V1*4uA>j< zAo4e%$lpO!h&dS<4V{|}nOT)J2Yg2kv|Ww9q5ExS&YU5cxrp;MaDE?l*UqMO8eh!s z|4ZRK!M`AgA_5x^>G>4vqt5_E^95>o2E?zxle_K=STiRL`H{dGz_D(V2ejX#QBalf zw8+wu@t&cK_4gIs6(?a@D^@^L{*@sw`0hkp{SX&L0vNxXCi|}-h%mq6yVd%YyiAi^ zUR^&n-VZKJ&tH)6e?j(6C~qSx5}9V1a<}+yo^9@FHYkUIV=%6qjYRTGA1Qz1(nq|& zF3mFF5TE2p+A>Qy$z;L{7M)7B%2M)J@I0xqovhkZX3h&`jmoUh4D0y@Nojsp%_N)k*~jst9O-|=2CP(7ZB-*GOKc1ypGK`Kt$cgxW`r5IzJLr zzix}V4KsKl-ooCexwk3Gv1ZsM7?sFJ&sqh%Ex;Y!8IbQH^2c`9Q+(8;&jSUE2A_da zfjf*Kde3aF8K61f8YVh5qu^}d*tOF@7=-`}{b;?ULlD5gI|5g|8-T03@EnjmAPgIg z1+H~r5n3NwuYLLDjq5+3foe^?~gG`82JRg%PX;1tVvKOuL^6-t$`aTANwU zm6w*|iQrOdTveDRMF~!umhViFf&Hyz%3_Ax^dE=^>emy~}@NaZ0vb@tJW35+j{SBEYd*QX-F9 zz&}RqNh&@Q#1+jge3iIe2vczz1`LD~sfcy>->SL4c1*^l2|c5K2lH(oME`p0l_92E zJainZAdbf+o93v8aeQx@-i0t&)j#yv}75 zpW#?{kyKNj=P>E9Utv5FNCknp0)1Vc2H_FQ@T|}XT%%(c;iDil{57g=dZ9owfw4n; z03zx_zFp_LDW6nXSwto@+rDf(o>s{Q{3P(vM6jev+7YedkATR3Y-G0v_V;L~_gXrr cKC;e0-jx=ftC;CD^4=+r!k?ifbY`-aR2}S diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/ISDN.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/ISDN.cpython-310.pyc deleted file mode 100644 index 40053b195c9a9e4a0203400ad1cba87346f3e553..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2014 zcmaJ?OK;mo5Z+xrL{gGtJ5G?MXp#655Jlsn#~>)$Bu)AVbZF8;2>}b5yH+Suq`FHv zwm@HM13C2<6aggkl)uDF4?X$ZTY$oyS<;G=Ll>CQ&hE_a?8k3LMZX^q7+ZgR^5RdJ z{f)-u;ehcqi2e?gAcAHjYJO?NjBT~QcKho@OtP^%cApTzgmp@U1$JlbomeL{@&$cH zLi-F(BZCC>{e?#6r zeRyy9vzAH^r=wybhmWM*FN^8$>7#EC;%s;z^Mm2jba$xJQhq*-ll^!k^-$z`r#V^g zd^7lE2a&luJyIP=VjD!epw{R*-JE(T_ezCVKK2cRl4ChEGNB^|Q` zpfa|X^bg?1$|lC9ubpSWuhnYfMPFM6wYPM8Zf)P%4jltaZ9%@ZqeNWBfSc4wJWcnG z3@D+kJh--Y3zd%2ybhGi;xau*=dxz|FI68l8?}aRowDGiJS^{kp?jcQy2*OfJ!j|F zoq5kZwRK4ljEjMFgKT&R(!A4JkR>_pRMwc{SO1+JdnK#96R`Fjb))ix^$}TEOF-b* z&zS&S5oAx*sr(Zg-sud^C>$5kD44{Dye#%*t`#oTuo(p-S#n*fG#^EMoGUqrfjs%B zwlbO5-Yhpr$l8G~J(FQjTS=ys4+kjBx3=I&wTb3cP*MLKG;o^EHFk%IWcY<%6U^F@PPyq(o{!!5%x60}v72{ek=j<+Na> zwXg-NoF!XQC@fe(Pn??=r;V}pZFR4W4gWXR!B{LnQ-t>5i~y)}cKd+=H+0nv$ftR~ z^HM=!)GpvWOUl~D3TaBwZFptxrJ1a~q?k;xT^Km)UJ~a;o+fdIG^5#v$a#P-f0-(I zA1=~cpaOtx6C|LXnE{0VUQ|}=`yPDAy%paO{;J`d1HW_$l>=a0Y1dp}7dv)ab~%-6 z*kujOYyW{*60&Fm8I%;Wyp*D8JGH+eRM=4;gWDzQxYJlcS83R@YCa#nbKQJ=d?;`H zpTH>^x#vMq1r1HEy`#w`&yWqCV}Bfg8axi^Anajt%;SmVybd^@6k?X)yvO;kvp8#a zI-H9lfo14|Ix9-ex#?Q!8r)iUO=FzM@8?CX zzd&$lI+yV_^#-g_k-u_M8yM*Pg#FE&el5Z~SVf3ZWFy8IO=MdINQG@?ZaA%s9J1*wrANczCZ(&~DKnca0l zt>YUwGh&uh18mIopW|taY=yGqbxh^ZSkKZZ{?{dVjqC-1i9i6E~X! zbmUw3^p_w65ws-fa;7P3_fE>pP*Q7!4#Cfq1NS++KBVk z$oVCC{p8_SgQr?5J(!H@u^c>-`oz?e!NH^NPqT7xDy!4MLGf&$3nM?BWcf)pl6oL2 zy}!I!?|;|-c^~R?Z}LI~@X9Utv=3sNcIXbBbq<@rSBWXt_s1``n4)XMP*|p%ghv~#Y|dua;CaqT#9XU3rx+8{MEb( z8_huM(%BZqw9@Ao^m;_FK=dBMr#}GEICHWfzXdQ;n8Su3icQdj=k6g<=$kMbkEB__ zlWya>5VA7Gu#hT=tdo~o;mrzL#yX}xQ9HQBQl;JN@HtSaMc1!tAq#Ocm1wByahuFL zaI!6O=!SHg&bpY;mG$v|*ob(vIeh|)hR%thbLbZ+v$J3e3Yo%>!J; z>}@B{s=6xjtOVq4rW!&m_*tRkUCb1D(xY#$$+R;4D@#Q2|B&-m$U$B$a$e(aAg6k8 zEbSs>N{%z=wrZ3F>JDf(5c4OQf)-hVh5)t6-3)oBtv|-hm;N7t=Mp5=g4DYLX~PK$ ze3Ur-qdtiK<0YXw*!fj9mYmy|^KmVvC9XT1|1!NdP< zx7rpTOY^)I>Me|U55#qI)a#@ye=(=IH&;`3jVWS{rHMUJiTo$?=7JJNLtn+sq zFt(sG diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/L64.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/L64.cpython-310.pyc deleted file mode 100644 index 9d277b93761366e448a7f5edbe3f0179596ed60c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1866 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 DOO$tL diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/MX.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/MX.cpython-310.pyc deleted file mode 100644 index e1b660417b28ccad128d2070bd0809737f17fbdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 456 zcmYjNO-sW-5Z%qD$+lQf5l;$Ud$0wMB2sHbkfs+A;dV2Tum<9;?B_aak% zlF4z$ET|B%7bzi%mJm@Q7hxG62=Tt~!n$G$AroJSZ4ki$;w2x=CS1>Qb(wnp+?y)RWvqLd%vY(>y}R*i&vCoyDl@D#_jc+laz_ U1-;q6`?mZ&U8d*}#TGfk|5QD1;{X5v diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NID.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NID.cpython-310.pyc deleted file mode 100644 index 1f9aa957f227a0ae1c341e9c0cb83dbf3b816c00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1860 zcmZux-H#hJ5VyVFkL)Ga>oqN+YT=3y)e7}0B!p0f5U3x3TIGSZNUS1R+qHAuyUlK} zoog>zUdT!PBPyiivHy}^c;Kney!8cUHo4wW@XE9H%y>NGncvjCUQA&0|G4@z3JCcV zH)n?rn{Qy6FM&uRX-U%6pQfzcdnr?FpYQYUh-A_`CenkwzaPxKIZZ=JACiQ>hSOw_ zBRxC#dSg;pD3Vf1z$#5Ww6w=k{(_9Cc2+#6{TYt{M$z{xwG={H9pv16v(YN z^j31t`DQv%+C@SXRbholW04s#Eh_uj7aCo6abb$e*bL+JpB!0boL8#K#Xn``RNd9O z*3OfaalV$B&C*ajRnLpjk;bcBsHHucz!^TZMd>a~GHsL?)q0#+t0d|szT-xfBh<~y z%orD}4z>5UW?oU(5uz0e@rt~;fBV+(u~FI#Cwui+4euy(VC%{7!JWGh?eI`lhrz`ZUOQqv(uuJ#ORp5RMtdMZ_bzNoPHb<*oGIe;|Za+=lZxEE>8XmM#F{ z@WS4bEh!W|@;LU3MF`vokPp~ja+D!Z5Hq%73PzGF)J+p61qZERmJ- z=THl)L1RAk1tgf}#9w8NkBU;cD6hu=e`DIGaNRts>Z-^AXfyS0=n*`Ocvfh29n2WC z)u%frb+s1#D{4&W|0U61Coxzj(Qg7wqTT_0D6nhrOM933<5EtE90uY5liJJEH`p{wVPVj|M;n_f~Fov9na!SP9`` zA;z_wmbmT;@yj$T*OE{OS?9n8kejl$Mu--b8jHnkw74HD`?Qw&WAqu_(Kk@mTX%(A zl_eZH#m;-Ef&kKp8N`Lb`i%%@5%02igL#Z~|Bge(`?S?bBK-+yq&;X8yTy1swb_$W zX)K6z3wi6-v5So??VM_0+erN%vH7)z&Un%K)519VY8Cs}*n17OoQT0k1Mf2Z2R|FO Aq5uE@ diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NINFO.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NINFO.cpython-310.pyc deleted file mode 100644 index 3ad1de9f3dba27798da565e4dadfa461d098dc86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 468 zcmYjN%}N6?5KcDRZY(WW6i*6Xd$0wMB2u*~LR}A5&=3gQO{m@OpPOy5UhB*FN_+9( z$ye~?Y+7jt=9~X7Gf5ha8Uoqy4Uybbz=@Q zhCt|=FxT~$O*fd=`Oo+-_2OYC z{{>IJc7^T1`|`f`}oZN06 zOrAkk1qe|dhotBK19y^sit=`&FnI=DZGaHgp2*=ea=8P$T;u91i8waRI3AUJlH+?jj{le>`9jmsugAhJyCE`!gRS`YVDG!ZZ%Rlt7@w3QF?cT2 znJ&kJgXb^KlYDS4iu1uib~I3#7GIB(^ej0MYQPJ%D>uzKe$Jj9*I!&V7WI zGY}yO9sA`yfT+c$A`tHaG40J9^+0zhi__fdN zR=ebennoO3WgOS6LXZ>L1@Sp_g_m?`n>J}kH|VruiCP-df0-iGW%J<$;r{|%eF>r> z!xel0=)fET`5VUO`knVn>XX)ae!g>lXdpY1^V&9GwQBST@{( ztnNWqUx29GYf`bwtNgip8E9HFdKp#(S+0UAoUtV!*MuiR*JNQ}o5ry$N45P8j-}xKnu6PxIQ^GBxBs#a zqQ759eOn@EiHIcfVuCp4WeVjN5>w@+R*;yOjuIo+v}~@9ggz~~MDiuNz}jFsi%d>M zo-ec67V2$WVxu3^^%Lj{4+{x%LZ|IC1IKfm_J1(?+til4UN`DMjouNjQZd$9S-`)e zQ1!QLG@9t-C>KybVF~^oq6WT6p6H}rV_&hnM;o=qminEE&hn_SJ^%`nRTzdEOHJg} p$9TWuY1Wuq4!3X+i3y+9|EcfsXQvQhxEVr`svqBdNPYH*{tvKGyCnbs diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC3.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC3.cpython-310.pyc deleted file mode 100644 index c62c6d6b2e728c7f20af979ee476211117ecc796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3459 zcmZu!OLN=E5yqPUNJ^Bfl@(XAu`6*ZOx4=4z1Dh@IAzQ4te1AyayE-n6$-*YGAIyW zW-7}c!`TC)v-S#y+EC2r4 zi~n>q?FSm1d~6JEp^1NhFpcS%7Sz2S=xS^PhU(40QoTLxooU~g_HJM$-o$4HGmng* zsd$qa;9JZJ+Gq=j)nDu{KG2xWoHrVCFz)o1`pbvrp&l&Hr48mn>SBDRzoKNHF#Va< z_1j*FL|#{>6M*HZYm$%Ra?4>0dnE@uy0~`jMFr~ARmV;<0?cTF{cdqrimUP1~j|NE? zN(V5AtH*R3pw-q>Sg?Y?>qX&(|^&0FG)?}?W zI&RKmt89TSLgFVbJIgw3Nxg4^UuI|UzV*FkX+az2TjTWYaZBy^JWt|+v#uk(DBCS~ zTD}-adnb!_h4gV?9+hd43u%ccE2WhuuS(h2Pjgo6iUY~#XH~|mBVx(7CND;#*O*dEB(qXn}>$DS~e^9P(N_X zR^|5FhqP*&X#|bl=DQF0cy~eCVl+%R0VB=RG7JMRj6^s}^YR97LWQ?L0)O`M$~te; z3#GOFx=aLLAgx6ZSVE+^D5E@1)NM+;91XLC6Fj>fjFV(LvcXxLMM6lY#>Meh)XK-p zscCO@>4l-15Qa4xDNOJ)AlK2vGRT72(&^X1&(~eh@j?x>*{Nc3mDyu}A^YD!6Tb#2 z=?1jEaimYo5*DA>N7}?W(hhJh6Ik|0Ck}Qqdhhj{T~|8Wkx14*m)`cZt4SUgEU69P zl|0Ht7L|!yf+)-jK8UigEW#JbD`{uNK1}T}V2LF-zbJV+>>7L(dr%7;yBnud!bu59 zVF|K9n{`0W;fR(#?o1CjSLkiVbg0?W07LC7H1QM!Fwt-%K&h`Yeb3-6W*peLTN)F< zsEhFu!7*|e$pEpwhvrvyWmV3Ovq~VcdOu=W?Y;ilxN~uIe)=cQUlbQb zx5cA>v6i;2Wa9PhzqkhddFDM4VaI9hWa`0$L-pb(>=swwb?^h zr&SeH{spEol@%M)-bJs&P9Ay#yFqM_zaHzcOA~#Jk%L%%^G_qe^fP@#hl}}YubwTg?7*^Ta$Lxq*cm=$sz@h zgI1+cK&cv)TX~gVHLKR4iyL!${36c4e+eRObtONNW854sJpzh3f?Roi7%`USyYF1m zBx$!3c)Lki$ArM2u~*h>oAZr zVjtmD+V?mwxHPjQ=RZ}8!Gmg7se_5P!;67}Nw+P{I1~IV)c6|dnq{%ayELSn610zj zf^VHd)p3M@AFBj;%I)|Ktnn?Hpk2F`i;zM;g3lUYpk*9H#k)P_>DeEHDOjn_lF35d-{ZmA5Utb1YIgZ^^ zwT}!+DQRxdTNscdQiR?z59|ZyfE<$?a_*QaypdD*Q>U;iXXY5nDU9COA_H};Ii6vT zV2N-Z7o)sPSXd`IidV9uZkmh`4kM0w2%+vv2u^^}sRcD2=Q;FrcKba|qNCJAWwpB) zj?e^+ItGEx*8#HC6CgYB>6kLv>>-{i78R-}E0%x{foNhL0ZvCK3E%2e1DdGGP@8TV$`UhB5(07*SxSz|A8#k%0=z;X^^ZU^1E^zV%PENons>((f zvLZ&siJUI7q7=yKl*#L4LGfBPRjwZ-<%@#V`=bMKvJ8Jj3hik*5GPqSD+$z&e?ltC zjAVw(Xm#M%EW0mG_qwOp~9SIfAqB5!_ilrhq=+qKb@Ln2~X(nw29_bCDy+oA<{2Er|KL?T4 zvxm2@1kRJEn@^r^2Hx=pP$a1(q(y5e4-D-3gZ4M{UA6ZU@KF|^!%O!MbzT2QiruQb dahFv5Qg9;9GLZg0Sf--3Wjf}X?pWva{{jtLB^Lky diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC3PARAM.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/NSEC3PARAM.cpython-310.pyc deleted file mode 100644 index 8fdc05f8baf6a721a8ade7e40901c63514806ae6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2085 zcmZuy&2QT_6c_a^#ZHqnXt566x&gzc0c}wXD2kyNmVT{3J7Z|m!vq6_BGQf=S@K9a zZ4Bj<0R1i!G%-l{LGrIH9OC9cv{E`2g#cbvrTMXyHC_HkGNE$Kn(n{R- zV9n~~*e^crd?Hg2xP>RAHY2Gs1Y3WT)O~9W2y>Ww9Ht&yV*v|~N$T?;^4L0ySbR+2 zjF4@x4(r03hzIO4TVUMt#k#>-_&vM<>QAx{jv38>-X9Eg?vNsycR5Rb(EFE zS`=z`ti3^*4W*6?#YLuyx{}(JS*h}1!FQAqEC-r=0-dsstP|3Z#y+)))mSHX2xVfHEL(2!Z+s?*zk{}Ie3k@nKTI|9&09yGsk2ksRF+3o!Yo2?Jz=4|D=>5chcCV>G# zhdV`;$-F3Zu*=_+#o$2u42Z&(F-tswL1-VCGb}0{3tj?a_KO+U_TFn_Oq1*~6BkdmI&K`7)b7Dc1!F&v1BruO)v|)^! z*kE%Nu!*ZcIVWxtpLnN$4!pCFs!h;@P1M9kzM-Dj0IS+c{4^SJ)lw~u&%`@-TUjbm zR6}tYb)#u@4iT>qqGUxoc_{^YD>|s-sCrLa!Rb}#((VOFRMnqj;WA{=K-6Oc+AT03 z5ysFBN&EB3s=YyGn+xEbt3Sz+EoTpA1Cr0+cMk-G{DBH`=rzC_#D_t`&beZZ0!UOy zRY>NRRRm>|q;_xSee>YK(+5eYosw5AZM@e|Ke+Y*pJ}eNi}|n=UgEceaR)`ob(q)V ziQrNibaW@rs=6xjtVI5hav6pY;G(Y!!S93b5~GR9S7dD|bLKjqM2=CPGv`N`AY&NB z({~QNL*Fn6nG?=g;Wa)o!>|Hkbure&KEHj4E?q}ftoKaJ4l1N+!(+d~xPci|; zqrLmjRGZ}h*UZIXgtXnc1@=s!Yj#NBlD}NO_OLil8|1~!O~e}V@|1# zDIM2rTB6*c^si}F&ff%-vO0%lD15T4m88^^DDedxu2)Pg9CNi>Gx0Ts_XBo_q3+Hr zWzNeIHeKX-7gdm@!iMe|G>P;NE!Ph1jvWVfVB4LKao6@XiP1@7lTPAWP)oZ|KX36j zIiKLi2R^fvY}bnMc&f6UlEY^eR0PXZmPQw=Uc2JGz!%2uf>XvlQ-Q+!Efl{H^lTM9 OTZdc%h(qE#*U0}MUFw$r diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/OPENPGPKEY.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/OPENPGPKEY.cpython-310.pyc deleted file mode 100644 index 702d5efbb7ba6d3f7ed78c102bdaf9dca86a8736..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1653 zcmZ8hPjA~c6emSle;hka(qI@eY-@)BgAZ$fq3EF-h7E1n0WG{B$qp3^5VA-+vSrC7 z>7+K4Qv&q1&tL<)HXgCJr&Jn9l_ZD^YioXeT4op zi_KAk#ZNHhFCZ9VI73nO#*t&!WchZN?^@(=XW$LI*N8cc+#p6^?GJ)$a*d;q;ZxLd z{|0ZUofx?}+~q=^fWlFP83M03A|Fu?TW>++vIop#{tb?5+zVZ{!vYrGVDRm;UADy< za1wBj?Xf1?w)^2nuDdpmc>$PPcSuwJ05)D7VD5wyHDvY`sd`u^UiOQ3)va>ixKa<8LZJa3I3*eoAO>hkaY_EbzZ-I$whoi?Nj{Y6j00W*@#vahv5KQQ z?Z%Qndz$v97I4cIP<2Rqg-H8puIqwlu}UxCrgnyxq5+4MXc{wL6;$yL>T6g?2gCuM z?QKNAJWhzXDN`Ia&ab3v}fxXHH6gfv^^(Spq3bKg_8LXrs?QcN8GkTR6hF8Pr28~6(14@bK zP`U%Wz!>^?h1JouO94exky5KjaeHaTb&wRJvEWkL&~+n;^CC}^I0KIEhZ+D7dYKA- z2w$=U-7l}@`Tt@xi0&BLH!)gn<=qYhhYJ*y;yG z8fO7=9jFP{A&%4dx9&S+A6tu7U3>!PQ4@Ob3ICAru}X_vJhAWU*%*^#mG%1e6oll?E1PeHz%W$U5Z~w-3F*;S0RRy+azf{57!Ed@4Do6&nC@&8tE_LPy6i)Xmt>XzObrKM)C_hL^A)$1LfCZ+(-QNcE1_86+V z1VWR7XgXj6>wu|-wmHP+7g~Tqn{~$5DjVoamTR!XGqo&GR1BQ)yPmz`&~Ab`uGJyVZVSZ#kBopV9VQ;*to zd<`|iFoCd#;qpqF#}Js+-vKS?OJ)zpr-S1 zCy~N9I}%VeuF`TV*2YG7jgup+#!5v73(kRUW3MNvFkYMwM^Y#VY%Y_2l9^^4WqFnW zl)!0Y0rG*96v`ki=H?(z%(m0Z9T=Rp{^QYg`^t{?_Fuydg9e}-`3?A~`k zUoC>LS(DBK9T({3e|*;btLcoF5bv`KPH_x<#aaT7KHwz<80ffpGTFCjd1mcttt@ diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/PTR.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/PTR.cpython-310.pyc deleted file mode 100644 index c33d396b83fb0bbd40d5b0a96dfe1412839f53e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 459 zcmYjNO-lnY5KT7Q-B>KBh$jWFJ=lUr5vf}7U|GcK!4L@BO{m@OS2x>2z1BbDU)qZY z@!((ZcxX6 zZ=OB*S}WUw_vL->$CtcB^?D6~?R^|ReG`N}bFyv~AZ>7c0w9sZK4Q2y4Tcr=h(~Ua zG$eULk^ncoidS8dC1#ey1Jp3TU=G=Cj_Zbjw88Z@fGRYZAu%J;fGLt$ciq9QecgZE zDubg$xltnRhM7?zLMKo{WHljzNY4B`-W1|_=J;jB5<*6<5br3l;D!Qz`d6p?UaLg& zcpL?aca)x{QOtXt?%eVDT!nMqn~b=gr0O_!+^I8Gn#)kP5}7VyrCS&FW2<~nGhQSH zNbl!cm;e+}qsTNUtHV%p5(Kl<8Tksf3N_o!bEQx-eMv`-R%~O{WR*2${THp_!|)Qi d3f0vfe-VW%GkW&7|9SqOI#1CZimT)R{{qOCb*2CS diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RP.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RP.cpython-310.pyc deleted file mode 100644 index eb34285d22c49365f59401365919d8fdfc2ca57d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1659 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 AvH$=8 diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RT.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/RT.cpython-310.pyc deleted file mode 100644 index bd808d83ba3fdce00614f93e3574a90d4a138678..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 474 zcmYjN%}T>S5Z=wE&9+!j5%HklwFg`9C?bj#L23`R1zi@FG`rNaNj7HFYQ5H%@s)D% z;K>K@;>k%GXb0xo`Q~qDMmHLD1hV&a^!!T@`p(IwRDfK9no|IYBn}Y6#cMIF@Ptgr zEs~ZbA4n45_M|eYF3A!zN8$(6w11!u^}HN61p~PRHQNBH=*cXJ8IcxLk<983-fR8A zaiTn($X?UVs1T7GDj~AE5TTZ{Ah)-Kc$v9D8F7S=+7sdvB@Xm0;P3AGj1P@U43Eb; zRJ^0iG}SThc5dcwz~?HO^R7SQ#!uBr?0QpotPGctX(uvW#LBdW%^hYea_a=DxB=D|{QdMzPvD$0?H(FT~Cdlad>Jk_EJx%VSI}}&RA^r!m7k88Z diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SMIMEA.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SMIMEA.cpython-310.pyc deleted file mode 100644 index aac8e3496949f836a47637eb73c41807b436e78f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 474 zcmYjNy-ve05VqsAF%^**I)cR7fmUKf2({1(A+=cw1C}Mrjjhr&f5d5}vX+%zsulI8W8kB%_V?B3Wtc{%32I-9FTzABV{S_ zjue5|4jMsoOSYIf3QtkT{((8<`6V6-hM*5>P5^Yp$t;B#Q5H;*qB)&BOh$t@x3=e* z_LEF`9lM}H#4^%C6fGg5M6JToKNjM3CBt3C5ke)t5FaRWfWLxY@9v5}8J!uP&XY*< zp*G7rN%?p6RK7{I=?%Q+Uj3hLy2&hHF4>I@ zKoPa7OouWTX1a?gTIF&UYFH^YtX<}IJl#Arawd&tNBb^kS7h|RN*~A5!7cPv#QRNZ XkHV`3y{<2CQ{K~*DQZ#NB&YZfdf9bB diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SOA.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SOA.cpython-310.pyc deleted file mode 100644 index 3de4e0a3efca2bcf5c68bf39b10bd000bdd7b686..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2183 zcmZ`)&5zqe6rb_89Vgx0E(J;}6;Ka8&?2}&g{WEzrBy)P<$x8*ay^q>XPr3AO!g!4 zo_3|)_!~C8^{&sEd{BnODfVd@iRtgrmwLPAsV_w@rH;&{YPm9_W zd?>iw2Rm2dq;~l6G#9*f$N3~5&&HX?ue~?w_y!ZI9D-2fj9k!)R>s1hq#_qaWiDt% z5>xAz)-BNO%GSCAx?4F~_q6V6-PgLO^+4;s);o;skXN)Hg|#hbQ!Z*RN#JHGNn$Ta zWrB|pcprfmivzUH@`?KTD}la^T{I|F2nXl5C_EHCh$yHn$%`R?z_KEhvUUVhCveK; zhI*5Ct$jsnKS}heBzZ;td-C9$!Eb=698CAhF&{kS@<5f-!PAF79HzzKkWUT=PxI#k znJfOqG|djuJuU}qBJVaw%DeabzuyIi-I<;UU@G|xs@wq4Gef%iHt0OWSxXf9yBS_~ zS@4zkz9&%SJrETcU3%ygJTWqs{yMc8t*puh8+dDkW2l3NM()tP2DnE?f4+TN-ohVS z|3#igDBjHW%Tn@0@FG?DVXjWJ7v2k6YR^bmTPDKcwsk1I{kI6$qTW$dC3 zjEs7NI+;U8DX#IgkBee#jx0DET&S9>A?H@H4zuVlZwYQ1lvr)ic}p zYp1*c7BUXO(_noG3NQs&wxICnr3Ue(Sz}kuo&{FQ=z_ka&&ZzuhPVNXB13!xO+%XI z@sTS&2Gbf>oM|c`-86K;4A4a0TXD0Yy^2^S&HQIDQ=(4;BcM0veEZV%Ym*@EcO$dE z+XvBq)UY|k#EZ!`N$Ma;#wD8-sE0}N$1E+{5jRO#nSmK{qby1#lSC&o@gW>pcXYZO zbG2VG@d@7fa}>96tlK8jj28tgTD=2Ppui*`3=r3$>IC2s%kZqw2tuQ47~$)nXL#FG z&xrzY6Q;#o$gX$zamJ@AFDJ1H-Nu%W$1{~aFF5>_!W6ta{BeUOSgO+4Uya+1#eRkZ edh@lLtpd%v*WmFT#p_`}dz+ro#F=AWr~d=gxAFb} diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SPF.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SPF.cpython-310.pyc deleted file mode 100644 index f803f2407ba44154e6e2554cede30dc4c0d5807c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmYjNO-lnY5KT5)Hx>(u;z_}454PY@M5hwAP(%%QGtaosSG7P#34(4{7G6lO#@FhvT|yT5s>0vu)9 zPcqf5y9E^@mXQ{ss0tA!Y7*LbONf_=43`y82$lFke4xw&Hfwu^ei{RcxA>%4exI&5Q0+6CTq@XPE=C`}XB7 z07cX(Gj+;pFwhu9(Il6HP{Ss%VY@cB6lvtI`9K=YHdjsFvc|msqSt@yUqV-@y4qn8 XQMj_8XN%p>?H?MOqB|6CkOTY&R0MJ% diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SSHFP.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/SSHFP.cpython-310.pyc deleted file mode 100644 index b4439b5662ffb7733c4d0a5887f8b1fa2a012abb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1966 zcmZ8hUymC#5VzO+HxNkTa)Y3)&FQEbm(01>S2s zK^G33_=4<`7f%0492if}rc#-Z^SsP!&Xb6zn$O_bI||=W_*lEScT`KQFgUSqTrG>C z36#i+RBPiafp)Jxv3f74i8!|!oWCIde1HFo!B1K$J(!NFi5xtT`k=0+gU1iPIZTVe zp)3yvkMq5O&TIMUG|djuk<f7!0`u5lTpKn|EZcUF=2&TLbQzNrUyYRb0=bP>M zxkLRY8TxTP(EI@AcQEx`APqYs3v$e0rGg4T@z@oB-58J>v)UbdV;{Hxa)35&P8;?I z{f!RURlqQI`zFfvXXSy;=kn#RaNRuoK-|E;jzi;S)%3`)X*FE|V;J~jJSEaPO#;3z zpXI}&7FAC{H4x)NGK})lbd)U8IzNP~jdSo+ZNZ`1ydalQH>fLK%V+gRAZR=b0R)G- z@Ozv3|IT|Y7)z}TJwG2UXL)X- zSqVrK07cv}EGx7^^V9|q!|LilT}AONAW3fp3$LpcuolDD@rj12nplKBgKsrn8oG#4 zhi=jNr52qForf8w$N4~TP__Vl0!$5s21&3?jRiaQ8Vay@3krpY92r|4%PV&Jb9QrQ z2TH})wVGwMaWSJ;_8RXg6un#)R2zDCm=^#`R!yc#YHhtX-7GDuGSAWiGr`}NsgUY* zM?=7ZKh2f=5)9R7`jytl^Kw`ozv3aL!$k^w3<8E8ngj*UZ19gE^=-I4;anroKp0RT z!;Y!%?CdBCU%f;UJ4pwVpmjFsA%7A5I8g6_&RS6YX{w+Tv~m3q&k*X@z1p&&LAQ9T ze-D(bcO55$44+?Ji{P4?La$=hf6@oif2gjb*u^earW47z>2N-&#H>KR%lR*}v{;@5 zoQo=hZRlLOsA|o*Z8Yi{++j9sGn>eIzY^*O>?o`}h1p?x%T|}kqJWQ9mD)uWELY_K zL0dGYb4Xk#bh}Q+cOu8>{?~~dZ<|`3xTD@d{hL6N9yE+w`D8My)4f8fZQP4+uk9iB u*s|DxlW3*+CTe;=VyCgUu9;+wvmGS7+XC?w2C;1+mqQu?ydm}3b^1T^DAYm# diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TKEY.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TKEY.cpython-310.pyc deleted file mode 100644 index 2abd2d6425d8dc7c6757cca24763cd1ca0dc8f2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2751 zcmai0OK;mo5a#kFlA>fQaT3QtQKx9y>d+W&0~aXzGGh6GC`w_uMMDTBXztpkERpJx za$lg@g{UsqNF1^`A8fh=CY%RQ5}t%qcEkdxAhH)%2YX(D9#IQ<3u?j zj!8*Vs;U>To7C{Jzxt@7Nz6fD5}x45lsL*h?DacwR8yh1UrBp}s#H5Q9gW_h1~pHK zqqBmk(|Kyq;wgc140@NAXc^v^tUwp&44oBvi&mT>z2VsOrcoSh_ zaV(tngE0B@6ONbU2>(>Oyux+V7Eo)V?e1~HVs4<)gsy63YRo!&S%Fi(zY6;-d zwoeF^4^_ULYE+q6*=Y5v^qc${*rghhq%o*Gh!-F9ul&cHz%4GxVzrbbR`Cy_C}u8a z9f-uEAUV#IIN@(|b*6xGGL2I&@c`3ZFJ>!`g1ut_L8f$Am}98(GMtg=5b^r~g!y>u z0n6mW7a7FJgbixKUM3v!hLm@6xUi5!F6zI8Njwi-naD&Z>gcab^vklbKva2P3%8HV zeT=H{gD9cTA43z#AXVCse5m|085UCIjGRkDV>FsD$}qP^V-ZH>9Jm8IJJHVc)IKM} z5@-t)m?iXOp)Z4eCY6wTX(2UIGquuUT1sb5OyU3aD&hCw20K+FGxk{`nBrI{xjP0fyD^Bv?_z6_^FF0k1B# z`&(O^n*;g&rr=Z6&dG$4`y$|w$X`IV2lN2VzMo_&rkA%-irv_e7u}on8W}K%+w*T_F z4QnQh!D0>ZE@Ab6Yyy0t>uU2#uR>6u|Z| zrYQ>o(wYY5t!ZFhvA)2h$(NwJz_Tx~v|V7B0>9B`Rk^WKRT?`D=o;(1h^h)!Nvw>n z3n|Zq`rhxLY`gAHeXlcmQ*d1x`Jjf<6?dW}c3n|w_`9%2Rut8&%aVhL@()16A7Zx* zol|Mnw!g1!yQ|IS)<)xLt+C_WS=(A)->SKrwR-*OYQwGl@OX2zu~BnwY&4sz-)^~$ z+Qze;t<{~aXAS4(cCGoWer*REs-3%5tJlyZD~-yj&pI8r*ECI6@D>K29Q`KZcP6@^+wCXb zZim57J}}9vjychCEDVmejm1dpdgXfJqIkW`_#*fFR|ufM+o(W7k})ai$^!WZ2E~jp diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TLSA.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TLSA.cpython-310.pyc deleted file mode 100644 index 884d8743af997f47d94e4322a98cdf23f5636220..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 468 zcmYjNJ5K^Z5Z=eZttg2Fr6#r%LSku*0max{XwbsVCY$AUgB8Vf7` zf|aue5hj^$-rwwO)^4{DNaySPwF3L?fFbZYyBF4wuS{o(kf?_Sf(*98Gy$89|Th8U?c zUB=rm(VHj9vQ*R9z%i-i9hcj&^vc+(sj`M2?YsP4k+c6QbDQp Q{#*Bx)}xJl3OAJoQkp8x;= diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TSIG.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TSIG.cpython-310.pyc deleted file mode 100644 index 70929c52ddfeb245404ecc09d091f083ef8f1eb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3229 zcmZ`*&5ztj6|eHQ-5)a(vSbND+W~>p5hPj^4G1CFRrX_|4K0)m2dtJn9#>6|d))1& zT$5y4ZXz*}_Qd`Hph(l)_QD@j7Y>|q=76+F+q_qHcRSgQEx&qI_3BmC`@Ik6olZdD zx&E&ooPKeQkbh&R`Pk6;0KVe)Kp0^(BVpCjkm|k>n!2^>)~;J8G`Tr;$L^07TrD;Xq6n~zm@iVzr1aHr5mM|SqEl(?y~Q&F5A)L!RN#xVGH)ZuB^ky4?dl@koE*m za>4qp^5blji&UOYR7<849u?_m%9*lH&e@17a}p=21p=dV8fQ@o6I_T~C_9&@TqN3} z^$n26+nDebV<3`Tk}F!$(pVall;p}N%_S{KWCCxMmga5Xozm943%pl4n)mg%tNB2- z#_e(Es#|)xzoX@R&F^aK8u2A10W-KM;?81xxAS1x39+8w=Uk88rQ?-Y+Brz#uI*L0OaVX zdCUeBuWi;mcDYSZ<*OLytKqs7+d8XP8QruBn&$L}-vioXFV$#@f13riYf z6M~71ZAO>I!Y-}9L*jtGQ@1X*FCFQ@n14yJ2Wx_>7WSFBH1xc61NFA`8e7YtdU4E zh;n5fN&ZY$FrY7Je3Y5-sRjw~#t;M#IgSgye=j|`(9Tf7?TQ`L;#3Z;g7qGAu8gy% z73k<3%F>%$NBx?-gWL@ukKrr63#1D;yleERvASs(UmGjOzDX@QZ);@gQzi(*`avKu z7pf_vUN$z;LH?1k}iW< z@fTW4wk1@Lt6(GBsmHrzmsw|)c<`F09niD`n!2Fr05sXCX=*TM0hto>Z|Rm^>6fjt zU3Ngy2dLb^Cw(fu4+o#O(kZxf%6h;1@V>@wer-LXL%oL({0AgSzoonpmpYbJfLs;E zTmJohTH?fO{4m(@0BbmPu;GqloFIqcMKG9t)GMH0-fL*M5hG+ zAT$>1~9@wbqE6#OFA?b{sIHC z8i(wu1IsR*I=BJ|W(+KI@X7$qa}!JlH+~Oz(L-_zNVtbVljP@9$yrt5Ho*a=1WW$} zMYmq>%whpmsB(M+reWtzY1~$^Hx0L|{SZNmDn(y_isFYrJOh0?0PhaI#g7dNp8U?% zlN%cP#^4Yxc{l)qIb_gpW2wjT9z`mMqDjuqGvwP*^r!PUt7qIOVtE3?P-crPmqirm zvZ(X0YU#>5;qo+R0>e<;Me=hXs#DkHgl8En+NN>%izhZwb7-xD6!i;13vomhhQO^Qlfl)mS>2oXhw)T2X~ p1jP4Hk*)s|^#+a8ZPJSJeqGt*H&__;FMziP*4GGl)G=?;{{!aL1(E;& diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TXT.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/TXT.cpython-310.pyc deleted file mode 100644 index 5c71bc74fdbf3118549218dc65cd4b61229ed468..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmYjN%}N6?5KcDRZY&lQ#gl^99&Ev*h*Yh3ukG2L%v1OtwcH=*Lw;a!Q!qGPP_qM|D^BJp%!qQJi4hsTqlS44{~2}Pyhe` diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/URI.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/URI.cpython-310.pyc deleted file mode 100644 index 885b65a0e824561858d6e7624465985ffe828e46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2602 zcmZ`*OLH4V5T4oht|iAYPU5`4q(}t;iQ&Q_MFprlAwfks&VemeZLN34%F3%6mA@fz^Iw_^2Tq*1GjD+<_L!(-o)6tra_H=YYgBv}!=RPIOVCE5FCak@le`p@kFktj0X<2`P zRMJk6&Ngehkh?J9B&3XhR2rIHko7wat+!;GGLuNju(x~{z`D2N_iLj`Lk z){;2S3$?bz*LZ)R_FD_umcs!T+KZwzPgN9!K@`hqnC9xMuLbHSP|?uG-K~AarND@5 zGvm27SuVBD-z0pX(jwOjFZXj5zj-V~AzF^MB+s_BD_D}nQffyqwGVfl3aum^Q|(7l z#SulvJmBF{Dx+VAh2ku#*~2F6q>Se(-A=g>J}4_teF2q)Xd41N z1!Q~|&Ve`y)kt*gKKJQ6?TNM4um+SDY#2|Q<2MAb#zD!3= z^y(?klLVuF($J~6t{jV@P>`b)5+MJ2=EOX(OFFhndqN>+aYlO8yvjeL{m%UO*)zxk z2dp0^N?QomGkvwa2Ze%HSoK941%F!9M}g=4V(j40Vt+*=87_V z*4VD=%oH$o>A*R{#cGQWK}ubB&H*RhUprTLoEkW_XTm0eNbr6PH7M^2RO<{Jq5q^1 z{ko`l;yRw4VZ#~30;)v~kMosf-akuKn9)H|{n57|N+SFg4MYTDVzhFKhZ)8M>*z_t zId(+F-{?GuI#hyV+HTP*xW}}L<^1(4(LfXl1QjfVY5ht(MIo5r4jrxH)&Irxzt@XT z;Y-m10#{?r5}zTND<;dcGV4bPtAs#Ak1o$&S~Dc5(@DcQy0*##%t!@w5UXGbNO?I` zz^VckLbb;tFSRvPX%=3s#X$v_F&KKTi*uBzdpF}gIb z_f%+mvt_n7+d$e+YR_E2w=IwRJc@J>Mg4*eGn_XfC{A%UJ#nLm6$xy^VuR3-sp==n`|q zBbMP=4I}Uj(=ZzEgTSyG)N?)4Fqdh?+gcDG0cY5RSMJ{FYg_xf+DrTWp+XA{? zCWSuE1dCN1F4fa2F88Xi_-9|(HIKc4tkrchI#=3PFOv67?YIXBeYu2+FME(S_0KV{ G(SHC*LTwcQ diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/WALLET.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/WALLET.cpython-310.pyc deleted file mode 100644 index af4779518e99837ecb0fbc23dabab75d2d6334f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 471 zcmYjNJx{|h5Vhm9F%^-JU<8S^1Fgh}5Ne?nOO%Boz_Mheu~nMpi#Vw$Yxy($r7$os z@fVo5Bt`8>es}Lao_$ViyMw@vzD}M$!GBj|*IGaZaP&EVL=uOH;o2JvD;$u3+#+d6 z@{S|{ZU(KOy(VkSEQ#+>*ZhGwl5Z^!d&lfvQf~imi5>%*?A7~H~2qA=kmV#*I2MAI*Sz29gH|{y-JF~k^ z8q0klk@^jIK}hyvzS6$%z*D|LU&_p#omzplc5Y{9cJ?8IWd|%R70S2dw!BsE$1jOTk}bHs>-f`8KApuN-q$Ltv~*!ArB=pdYXk@c*O)(t zY3_osK~qh*b>e~=-B^*|?_k71hIASAV9L?L@J;!FA`=znp@o%LVQyO0%!Tb-|EYE#Hr znJk^;M`x>?HL#4hpwjs;FI}uvk=pzupDD+VPjwrNjp(3TXe(jWb9)aI!$91ovn@or z+Rrf9dPJ~5m=9o@E{Hi_kR^E$&Iy)m9-afpOWN_v`eh0%Cgw?H^< zt7E;3>K=%s^9G`@Rh`96n5`pSjccGiI8i@p9-+^okX8FRCZ0;}Fk^=3Tho`t+QSORRLT2oPZ+pJug(_>1&Og<_ z1s6b`)66;#Nzn_M_xFzSLb)ib#uKD{ovv$VX<3zdmKInJTHH)Cg8ap4uGPl?*WiQ2 zv`zQu&YC_e^MCUEzpD7Fs`ywH{Wb)Hy6j?IvT9mdC7VtGz{t3b@&uDqLmxC1LYm%$ zxl_M5;uMYRXW-Nng+Woe*G1WI0q!1P@Ag6TA2o2=*t%spRzkQ~h;b#S1+Lpd{5DOC zl_eBHRvBzVx0<4|Mu@t-G&0a_)eSsW_E{zMI|vrrPJf8D&Z@mLRTOaO4fXLKStI{7 zQvMFiy6Yn1vA}Dy*khcr_UkxcL6_D(y;#2sZb=6^@4kATsfo?2Qs27X%g5uXO%DqN zf570<^k(f1WLG8BTPLk+C%uCQ{hzRd>-ZbsYM6C%Mqf5h@)eMem~9ZzZp0#rzkuJN F{{k4dc^Loz diff --git a/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/ZONEMD.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/ANY/__pycache__/ZONEMD.cpython-310.pyc deleted file mode 100644 index 2d12809fe9734cbe973639eb747723cc24ff8fed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2424 zcmZ8iTW=dh6yDkUuIyaVHa1U@61 zTGu>=UA10>_WWno9T`A_Yj{$iGZGjB*y}G6m@l+#!VG2}x`D;o%wg^!32g3o7Q4he z<{uI`!(}V1$yzYuafe-IOKiCu_g`qH7Bt}e)xr*b>OK5%W8SLjj^I%ySl29U$weF{ zP)9>P;l2*CNA zlb>;A6*r0h=z*@X8uxE!l&+JC(9a3@Uq zJ3QU#KaRKhGFJS?G>pa}@Tm{+->lA(H}CbH-mGZ3KHU>Yu2m@V3YaC*ByIRLiLblF zCoXC0Yhc~i^W}QU3CO)C5kh4^ZS?FuAeNju+Hg`^|78I#=joBT<(%{AnZ*(*wl`1ByR&2U@||z)px_BFArBcB7o&Co9l9F}{uNwVVgPFpZkwE?Q9b`gu*j2B zu3)gp6-IyuR?QN-=7YubceUJNMrlp3HgW@n_Y+uGs_!vM@Uaf2t5e+AL90qVP#CG{&7$dFx?|@SoDr(0EWd8Q~mp$j#)q796M(;@v zOz)BS5SDeDsNQKf;gl9WrIU=!5^Ogq{e2cD^^8L)%OV&CMU+XVB&DT(i4S0pqEU+E zgsWl3#C5zeGEUsaxmGQq5l<3Wbe7>O=z?i35GZ7)L=A8?Q+Lg#?zeSc*PE|>U$<6C z>CD8yFW6Q+TAJ0DjaxLp;SNtEgDc+l-9~&qvu(nn) z_%?t+VGC=5zMhdP*V@Bu?LFVBoodR>#A}MY&As+vue?q7tn~ThCAfGd{2MsIQJT;Y zuL0p(0*GJ?BjPjhff|bV0vtk<6kNh^L`@QFW@LVN3$EW&!+&DiXkEGtuHN+N^%XdC z9vf~EuvrXf5pZw<;WI$t<%I#GKw(V44msG-3J?o?a9OXmnHkIkC5A9~3FAI-oZtw? zF{g~rdB0-JQ$RdTV3bht_iw_%O%f5z!8V%@MHEC70}^oudX)O225yn-Rbj7C12*vFBSMZJ--yW~|R<#(%bj2Aup=HzX*)T+_h zep}zG%vbuZt@l~z(?ecm2emt7VfiW3WvgE7^UYnpRXQtndfF77KYD7Mn@U;k%2vwr Y{loF(`o1o{RO;QJbG@77Jb7gQ0R~o+tN;K2 diff --git a/venv/Lib/site-packages/dns/rdtypes/CH/A.py b/venv/Lib/site-packages/dns/rdtypes/CH/A.py deleted file mode 100644 index 832e8d3..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/CH/A.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.immutable -import dns.rdtypes.mxbase - - -@dns.immutable.immutable -class A(dns.rdata.Rdata): - """A record for Chaosnet""" - - # domain: the domain of the address - # address: the 16-bit address - - __slots__ = ["domain", "address"] - - def __init__(self, rdclass, rdtype, domain, address): - super().__init__(rdclass, rdtype) - self.domain = self._as_name(domain) - self.address = self._as_uint16(address) - - def to_text(self, origin=None, relativize=True, **kw): - domain = self.domain.choose_relativity(origin, relativize) - return f"{domain} {self.address:o}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - domain = tok.get_name(origin, relativize, relativize_to) - address = tok.get_uint16(base=8) - return cls(rdclass, rdtype, domain, address) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.domain.to_wire(file, compress, origin, canonicalize) - pref = struct.pack("!H", self.address) - file.write(pref) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - domain = parser.get_name(origin) - address = parser.get_uint16() - return cls(rdclass, rdtype, domain, address) diff --git a/venv/Lib/site-packages/dns/rdtypes/CH/__init__.py b/venv/Lib/site-packages/dns/rdtypes/CH/__init__.py deleted file mode 100644 index 0760c26..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/CH/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Class CH rdata type classes.""" - -__all__ = [ - "A", -] diff --git a/venv/Lib/site-packages/dns/rdtypes/CH/__pycache__/A.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/CH/__pycache__/A.cpython-310.pyc deleted file mode 100644 index 319e6a015a5edcea04bac57f64000bfe769899d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1689 zcmZ8h&2A$_5bo~z^~4T|$?}inMF?Re9Kit)LI^9%5{Z=$Y`BapwIM*H>Rv7mY?lVC?<#@yXvIA^+my z{_tS&6HNUb2tfqRNxb~hnAx=xGs#ZfQ}-7lm~d{0aA577`q$1ijRQfSlD7L2{wBQ? z<^AEV7CHt+l9&ntr_$KLlZGsIpOXO!WD9JUM(~4GX!6>Q7oK?<(R)jmCyOnEoPmrhNmiF4d@$_^el?ge| z##zaE9P&i-aWaw$&x|8nPP1|O)i(++YJ0}jG9Q>gi8N2NHog+&C7glo*5#I(8t2x? z`7L>Mc<_DycP*9fPlm-v_8&=oRu+@~lSe(>mRuv#8ry$KE?iF^Kh8=jK<~&@B)ZIlarx73AUt zlnd-J!Ctt3IY5KcdqrD@7Hww8#f6toBpHwjMQ5F!}?S`g0JKGbfc>d6mC# zu7b)rrGg6fC%pcWPxGvEqQV4beqn$x}7`QrzeA(zsYcmM7y~ zD5xp$v~;g`k0+IW&8MB!g7#@Q-$bb>ZaRB0CJ|L085XF$fn9dl*n8Fmypvhb%ip-_~PSdyqvQdy9ykPH$_E!Mlm=;)`(bc;PcJ|#anJ|4tK%*lz5U&&C!0yGRv z{PK6UiU}=FEh>&FNYBqrjd4jW&MwI>i1Bf8ElbRaDND^Oi}A@!iYd-4N!2Y#OwLYB zPc4o~$t%_`N&(qctncihA0MBYmst`YuUAlci^C>2KczG$)ehwHVm2VbBFMzd@gD%q C$w1Qp diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/A.py b/venv/Lib/site-packages/dns/rdtypes/IN/A.py deleted file mode 100644 index e09d611..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/A.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.exception -import dns.immutable -import dns.ipv4 -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class A(dns.rdata.Rdata): - """A record.""" - - __slots__ = ["address"] - - def __init__(self, rdclass, rdtype, address): - super().__init__(rdclass, rdtype) - self.address = self._as_ipv4_address(address) - - def to_text(self, origin=None, relativize=True, **kw): - return self.address - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - address = tok.get_identifier() - return cls(rdclass, rdtype, address) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(dns.ipv4.inet_aton(self.address)) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - address = parser.get_remaining() - return cls(rdclass, rdtype, address) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/AAAA.py b/venv/Lib/site-packages/dns/rdtypes/IN/AAAA.py deleted file mode 100644 index 0cd139e..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/AAAA.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.exception -import dns.immutable -import dns.ipv6 -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class AAAA(dns.rdata.Rdata): - """AAAA record.""" - - __slots__ = ["address"] - - def __init__(self, rdclass, rdtype, address): - super().__init__(rdclass, rdtype) - self.address = self._as_ipv6_address(address) - - def to_text(self, origin=None, relativize=True, **kw): - return self.address - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - address = tok.get_identifier() - return cls(rdclass, rdtype, address) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(dns.ipv6.inet_aton(self.address)) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - address = parser.get_remaining() - return cls(rdclass, rdtype, address) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/APL.py b/venv/Lib/site-packages/dns/rdtypes/IN/APL.py deleted file mode 100644 index 44cb3fe..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/APL.py +++ /dev/null @@ -1,150 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii -import codecs -import struct - -import dns.exception -import dns.immutable -import dns.ipv4 -import dns.ipv6 -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class APLItem: - """An APL list item.""" - - __slots__ = ["family", "negation", "address", "prefix"] - - def __init__(self, family, negation, address, prefix): - self.family = dns.rdata.Rdata._as_uint16(family) - self.negation = dns.rdata.Rdata._as_bool(negation) - if self.family == 1: - self.address = dns.rdata.Rdata._as_ipv4_address(address) - self.prefix = dns.rdata.Rdata._as_int(prefix, 0, 32) - elif self.family == 2: - self.address = dns.rdata.Rdata._as_ipv6_address(address) - self.prefix = dns.rdata.Rdata._as_int(prefix, 0, 128) - else: - self.address = dns.rdata.Rdata._as_bytes(address, max_length=127) - self.prefix = dns.rdata.Rdata._as_uint8(prefix) - - def __str__(self): - if self.negation: - return "!%d:%s/%s" % (self.family, self.address, self.prefix) - else: - return "%d:%s/%s" % (self.family, self.address, self.prefix) - - def to_wire(self, file): - if self.family == 1: - address = dns.ipv4.inet_aton(self.address) - elif self.family == 2: - address = dns.ipv6.inet_aton(self.address) - else: - address = binascii.unhexlify(self.address) - # - # Truncate least significant zero bytes. - # - last = 0 - for i in range(len(address) - 1, -1, -1): - if address[i] != 0: - last = i + 1 - break - address = address[0:last] - l = len(address) - assert l < 128 - if self.negation: - l |= 0x80 - header = struct.pack("!HBB", self.family, self.prefix, l) - file.write(header) - file.write(address) - - -@dns.immutable.immutable -class APL(dns.rdata.Rdata): - """APL record.""" - - # see: RFC 3123 - - __slots__ = ["items"] - - def __init__(self, rdclass, rdtype, items): - super().__init__(rdclass, rdtype) - for item in items: - if not isinstance(item, APLItem): - raise ValueError("item not an APLItem") - self.items = tuple(items) - - def to_text(self, origin=None, relativize=True, **kw): - return " ".join(map(str, self.items)) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - items = [] - for token in tok.get_remaining(): - item = token.unescape().value - if item[0] == "!": - negation = True - item = item[1:] - else: - negation = False - (family, rest) = item.split(":", 1) - family = int(family) - (address, prefix) = rest.split("/", 1) - prefix = int(prefix) - item = APLItem(family, negation, address, prefix) - items.append(item) - - return cls(rdclass, rdtype, items) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - for item in self.items: - item.to_wire(file) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - items = [] - while parser.remaining() > 0: - header = parser.get_struct("!HBB") - afdlen = header[2] - if afdlen > 127: - negation = True - afdlen -= 128 - else: - negation = False - address = parser.get_bytes(afdlen) - l = len(address) - if header[0] == 1: - if l < 4: - address += b"\x00" * (4 - l) - elif header[0] == 2: - if l < 16: - address += b"\x00" * (16 - l) - else: - # - # This isn't really right according to the RFC, but it - # seems better than throwing an exception - # - address = codecs.encode(address, "hex_codec") - item = APLItem(header[0], negation, address, header[1]) - items.append(item) - return cls(rdclass, rdtype, items) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/DHCID.py b/venv/Lib/site-packages/dns/rdtypes/IN/DHCID.py deleted file mode 100644 index 723492f..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/DHCID.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 - -import dns.exception -import dns.immutable -import dns.rdata - - -@dns.immutable.immutable -class DHCID(dns.rdata.Rdata): - """DHCID record""" - - # see: RFC 4701 - - __slots__ = ["data"] - - def __init__(self, rdclass, rdtype, data): - super().__init__(rdclass, rdtype) - self.data = self._as_bytes(data) - - def to_text(self, origin=None, relativize=True, **kw): - return dns.rdata._base64ify(self.data, **kw) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - b64 = tok.concatenate_remaining_identifiers().encode() - data = base64.b64decode(b64) - return cls(rdclass, rdtype, data) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(self.data) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - data = parser.get_remaining() - return cls(rdclass, rdtype, data) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/HTTPS.py b/venv/Lib/site-packages/dns/rdtypes/IN/HTTPS.py deleted file mode 100644 index 15464cb..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/HTTPS.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import dns.immutable -import dns.rdtypes.svcbbase - - -@dns.immutable.immutable -class HTTPS(dns.rdtypes.svcbbase.SVCBBase): - """HTTPS record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/IPSECKEY.py b/venv/Lib/site-packages/dns/rdtypes/IN/IPSECKEY.py deleted file mode 100644 index e3a6615..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/IPSECKEY.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import struct - -import dns.exception -import dns.immutable -import dns.rdtypes.util - - -class Gateway(dns.rdtypes.util.Gateway): - name = "IPSECKEY gateway" - - -@dns.immutable.immutable -class IPSECKEY(dns.rdata.Rdata): - """IPSECKEY record""" - - # see: RFC 4025 - - __slots__ = ["precedence", "gateway_type", "algorithm", "gateway", "key"] - - def __init__( - self, rdclass, rdtype, precedence, gateway_type, algorithm, gateway, key - ): - super().__init__(rdclass, rdtype) - gateway = Gateway(gateway_type, gateway) - self.precedence = self._as_uint8(precedence) - self.gateway_type = gateway.type - self.algorithm = self._as_uint8(algorithm) - self.gateway = gateway.gateway - self.key = self._as_bytes(key) - - def to_text(self, origin=None, relativize=True, **kw): - gateway = Gateway(self.gateway_type, self.gateway).to_text(origin, relativize) - return "%d %d %d %s %s" % ( - self.precedence, - self.gateway_type, - self.algorithm, - gateway, - dns.rdata._base64ify(self.key, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - precedence = tok.get_uint8() - gateway_type = tok.get_uint8() - algorithm = tok.get_uint8() - gateway = Gateway.from_text( - gateway_type, tok, origin, relativize, relativize_to - ) - b64 = tok.concatenate_remaining_identifiers().encode() - key = base64.b64decode(b64) - return cls( - rdclass, rdtype, precedence, gateway_type, algorithm, gateway.gateway, key - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack("!BBB", self.precedence, self.gateway_type, self.algorithm) - file.write(header) - Gateway(self.gateway_type, self.gateway).to_wire( - file, compress, origin, canonicalize - ) - file.write(self.key) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("!BBB") - gateway_type = header[1] - gateway = Gateway.from_wire_parser(gateway_type, parser, origin) - key = parser.get_remaining() - return cls( - rdclass, rdtype, header[0], gateway_type, header[2], gateway.gateway, key - ) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/KX.py b/venv/Lib/site-packages/dns/rdtypes/IN/KX.py deleted file mode 100644 index 6073df4..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/KX.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.mxbase - - -@dns.immutable.immutable -class KX(dns.rdtypes.mxbase.UncompressedDowncasingMX): - """KX record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/NAPTR.py b/venv/Lib/site-packages/dns/rdtypes/IN/NAPTR.py deleted file mode 100644 index 195d1cb..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/NAPTR.py +++ /dev/null @@ -1,110 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdtypes.util - - -def _write_string(file, s): - l = len(s) - assert l < 256 - file.write(struct.pack("!B", l)) - file.write(s) - - -@dns.immutable.immutable -class NAPTR(dns.rdata.Rdata): - """NAPTR record""" - - # see: RFC 3403 - - __slots__ = ["order", "preference", "flags", "service", "regexp", "replacement"] - - def __init__( - self, rdclass, rdtype, order, preference, flags, service, regexp, replacement - ): - super().__init__(rdclass, rdtype) - self.flags = self._as_bytes(flags, True, 255) - self.service = self._as_bytes(service, True, 255) - self.regexp = self._as_bytes(regexp, True, 255) - self.order = self._as_uint16(order) - self.preference = self._as_uint16(preference) - self.replacement = self._as_name(replacement) - - def to_text(self, origin=None, relativize=True, **kw): - replacement = self.replacement.choose_relativity(origin, relativize) - return '%d %d "%s" "%s" "%s" %s' % ( - self.order, - self.preference, - dns.rdata._escapify(self.flags), - dns.rdata._escapify(self.service), - dns.rdata._escapify(self.regexp), - replacement, - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - order = tok.get_uint16() - preference = tok.get_uint16() - flags = tok.get_string() - service = tok.get_string() - regexp = tok.get_string() - replacement = tok.get_name(origin, relativize, relativize_to) - return cls( - rdclass, rdtype, order, preference, flags, service, regexp, replacement - ) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - two_ints = struct.pack("!HH", self.order, self.preference) - file.write(two_ints) - _write_string(file, self.flags) - _write_string(file, self.service) - _write_string(file, self.regexp) - self.replacement.to_wire(file, compress, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (order, preference) = parser.get_struct("!HH") - strings = [] - for _ in range(3): - s = parser.get_counted_bytes() - strings.append(s) - replacement = parser.get_name(origin) - return cls( - rdclass, - rdtype, - order, - preference, - strings[0], - strings[1], - strings[2], - replacement, - ) - - def _processing_priority(self): - return (self.order, self.preference) - - @classmethod - def _processing_order(cls, iterable): - return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/NSAP.py b/venv/Lib/site-packages/dns/rdtypes/IN/NSAP.py deleted file mode 100644 index d55edb7..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/NSAP.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii - -import dns.exception -import dns.immutable -import dns.rdata -import dns.tokenizer - - -@dns.immutable.immutable -class NSAP(dns.rdata.Rdata): - """NSAP record.""" - - # see: RFC 1706 - - __slots__ = ["address"] - - def __init__(self, rdclass, rdtype, address): - super().__init__(rdclass, rdtype) - self.address = self._as_bytes(address) - - def to_text(self, origin=None, relativize=True, **kw): - return f"0x{binascii.hexlify(self.address).decode()}" - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - address = tok.get_string() - if address[0:2] != "0x": - raise dns.exception.SyntaxError("string does not start with 0x") - address = address[2:].replace(".", "") - if len(address) % 2 != 0: - raise dns.exception.SyntaxError("hexstring has odd length") - address = binascii.unhexlify(address.encode()) - return cls(rdclass, rdtype, address) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(self.address) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - address = parser.get_remaining() - return cls(rdclass, rdtype, address) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/NSAP_PTR.py b/venv/Lib/site-packages/dns/rdtypes/IN/NSAP_PTR.py deleted file mode 100644 index ce1c663..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/NSAP_PTR.py +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import dns.immutable -import dns.rdtypes.nsbase - - -@dns.immutable.immutable -class NSAP_PTR(dns.rdtypes.nsbase.UncompressedNS): - """NSAP-PTR record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/PX.py b/venv/Lib/site-packages/dns/rdtypes/IN/PX.py deleted file mode 100644 index cdca153..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/PX.py +++ /dev/null @@ -1,73 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdtypes.util - - -@dns.immutable.immutable -class PX(dns.rdata.Rdata): - """PX record.""" - - # see: RFC 2163 - - __slots__ = ["preference", "map822", "mapx400"] - - def __init__(self, rdclass, rdtype, preference, map822, mapx400): - super().__init__(rdclass, rdtype) - self.preference = self._as_uint16(preference) - self.map822 = self._as_name(map822) - self.mapx400 = self._as_name(mapx400) - - def to_text(self, origin=None, relativize=True, **kw): - map822 = self.map822.choose_relativity(origin, relativize) - mapx400 = self.mapx400.choose_relativity(origin, relativize) - return "%d %s %s" % (self.preference, map822, mapx400) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - preference = tok.get_uint16() - map822 = tok.get_name(origin, relativize, relativize_to) - mapx400 = tok.get_name(origin, relativize, relativize_to) - return cls(rdclass, rdtype, preference, map822, mapx400) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - pref = struct.pack("!H", self.preference) - file.write(pref) - self.map822.to_wire(file, None, origin, canonicalize) - self.mapx400.to_wire(file, None, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - preference = parser.get_uint16() - map822 = parser.get_name(origin) - mapx400 = parser.get_name(origin) - return cls(rdclass, rdtype, preference, map822, mapx400) - - def _processing_priority(self): - return self.preference - - @classmethod - def _processing_order(cls, iterable): - return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/SRV.py b/venv/Lib/site-packages/dns/rdtypes/IN/SRV.py deleted file mode 100644 index 5adef98..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/SRV.py +++ /dev/null @@ -1,75 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdtypes.util - - -@dns.immutable.immutable -class SRV(dns.rdata.Rdata): - """SRV record""" - - # see: RFC 2782 - - __slots__ = ["priority", "weight", "port", "target"] - - def __init__(self, rdclass, rdtype, priority, weight, port, target): - super().__init__(rdclass, rdtype) - self.priority = self._as_uint16(priority) - self.weight = self._as_uint16(weight) - self.port = self._as_uint16(port) - self.target = self._as_name(target) - - def to_text(self, origin=None, relativize=True, **kw): - target = self.target.choose_relativity(origin, relativize) - return "%d %d %d %s" % (self.priority, self.weight, self.port, target) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - priority = tok.get_uint16() - weight = tok.get_uint16() - port = tok.get_uint16() - target = tok.get_name(origin, relativize, relativize_to) - return cls(rdclass, rdtype, priority, weight, port, target) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - three_ints = struct.pack("!HHH", self.priority, self.weight, self.port) - file.write(three_ints) - self.target.to_wire(file, compress, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - (priority, weight, port) = parser.get_struct("!HHH") - target = parser.get_name(origin) - return cls(rdclass, rdtype, priority, weight, port, target) - - def _processing_priority(self): - return self.priority - - def _processing_weight(self): - return self.weight - - @classmethod - def _processing_order(cls, iterable): - return dns.rdtypes.util.weighted_processing_order(iterable) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/SVCB.py b/venv/Lib/site-packages/dns/rdtypes/IN/SVCB.py deleted file mode 100644 index ff3e932..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/SVCB.py +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import dns.immutable -import dns.rdtypes.svcbbase - - -@dns.immutable.immutable -class SVCB(dns.rdtypes.svcbbase.SVCBBase): - """SVCB record""" diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/WKS.py b/venv/Lib/site-packages/dns/rdtypes/IN/WKS.py deleted file mode 100644 index 881a784..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/WKS.py +++ /dev/null @@ -1,100 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import socket -import struct - -import dns.immutable -import dns.ipv4 -import dns.rdata - -try: - _proto_tcp = socket.getprotobyname("tcp") - _proto_udp = socket.getprotobyname("udp") -except OSError: - # Fall back to defaults in case /etc/protocols is unavailable. - _proto_tcp = 6 - _proto_udp = 17 - - -@dns.immutable.immutable -class WKS(dns.rdata.Rdata): - """WKS record""" - - # see: RFC 1035 - - __slots__ = ["address", "protocol", "bitmap"] - - def __init__(self, rdclass, rdtype, address, protocol, bitmap): - super().__init__(rdclass, rdtype) - self.address = self._as_ipv4_address(address) - self.protocol = self._as_uint8(protocol) - self.bitmap = self._as_bytes(bitmap) - - def to_text(self, origin=None, relativize=True, **kw): - bits = [] - for i, byte in enumerate(self.bitmap): - for j in range(0, 8): - if byte & (0x80 >> j): - bits.append(str(i * 8 + j)) - text = " ".join(bits) - return "%s %d %s" % (self.address, self.protocol, text) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - address = tok.get_string() - protocol = tok.get_string() - if protocol.isdigit(): - protocol = int(protocol) - else: - protocol = socket.getprotobyname(protocol) - bitmap = bytearray() - for token in tok.get_remaining(): - value = token.unescape().value - if value.isdigit(): - serv = int(value) - else: - if protocol != _proto_udp and protocol != _proto_tcp: - raise NotImplementedError("protocol must be TCP or UDP") - if protocol == _proto_udp: - protocol_text = "udp" - else: - protocol_text = "tcp" - serv = socket.getservbyname(value, protocol_text) - i = serv // 8 - l = len(bitmap) - if l < i + 1: - for _ in range(l, i + 1): - bitmap.append(0) - bitmap[i] = bitmap[i] | (0x80 >> (serv % 8)) - bitmap = dns.rdata._truncate_bitmap(bitmap) - return cls(rdclass, rdtype, address, protocol, bitmap) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(dns.ipv4.inet_aton(self.address)) - protocol = struct.pack("!B", self.protocol) - file.write(protocol) - file.write(self.bitmap) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - address = parser.get_bytes(4) - protocol = parser.get_uint8() - bitmap = parser.get_remaining() - return cls(rdclass, rdtype, address, protocol, bitmap) diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__init__.py b/venv/Lib/site-packages/dns/rdtypes/IN/__init__.py deleted file mode 100644 index dcec4dd..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/IN/__init__.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Class IN rdata type classes.""" - -__all__ = [ - "A", - "AAAA", - "APL", - "DHCID", - "HTTPS", - "IPSECKEY", - "KX", - "NAPTR", - "NSAP", - "NSAP_PTR", - "PX", - "SRV", - "SVCB", - "WKS", -] diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/A.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/A.cpython-310.pyc deleted file mode 100644 index f57575603ba5d545befc70bddabbb989a3bc32ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1533 zcmZux&2Aev5GJ|*vgFvV5u`2B7AR0ahsZtTR1`&pq-lxnma2!BO13p*G^YS?BzQ{QdmNH`8CWRC-#?%cYz?mHNz-)%3;FA67{|UCClK zeUZJI>deSTRg#`1bE&7I&?oJs`sAm{$#_(~Q$F1OIf%xG?b8E#*&C0xSSP0`dfzrQ zp&&nlXgpYx1-w(?`jB?dP>?dj`lZU|Sz&uh=84Hx*`>7X>_YWnvsD8$3rxw4d~3dh ziDsaD3Q-t!t0`W!Z6OTM(Gw7T461h4WJ7)rYJvf%gDd9)lz4wG4bOxuOg77;8iv+M zbFJ_W6@jvjDbLhCPVa$=2e&Y}DVvwvg&NINxop6G1t%K1Lbp#Z_r{|SJI_+Ajcvm* zN`v?T3~IV2hA!CJ0pi>Z-B1ekvqkM$??OSmtOIe1UCa<0Wd%GWF=f%R>$U8 za+yGS7xSU7j^OkT(|(mG$kdi>%%;204jTFp8*fd&Mu_M?WWeuH$M258kWEg9&g66g zYVxd2zdlx2kt`+Ww#WIh6z4gP`<%ZyPx5Xj;9Qg`EJHQvyfm8grUKLZVql2^Hee-@Zv62SivMoJ_mX>A~NWq~n{qg!*YHSm5x gyT;89#s+OuaN)NtGv8qyYb=29Fr@A0JD<>h0pQ4Aga7~l diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/AAAA.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/AAAA.cpython-310.pyc deleted file mode 100644 index 9382a61fa560e1bb682529eae5fa275c3e98459c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1557 zcmZuxOOG2x5bnpk?AXq3SWtKbkdTmk$Sx-i2q92HAWGx|StK;F)S67Uo$=1YboY9b z)o|LC@;B_`{-wEa;KX0xLaKVkyJkg?s`^pYT~%LIO*I_$35<%9` z-vgPSfk`51PGah2*3G<|y>9kns^}tE1V0hUB)=q*!#-R@7yN?8JxO1XvG+H;MkXop z-Qjf`^BXLbvlKH)V=md8#@<^pqmoPSGKzhC&n~^mi7%?Md=l7dP2B!A+E?j&mMg<{naRKrptL%sOe*6PHeTDK7ah z!*-w+1$qW#@NP{O5Us}ZG3|oUP(GvyDxJ-x zwfzD%h5-v`n~uXykm76G5y1j&JpwWZz-qoG8}dh36U;;%Uhr#g;?Z1Lkx5nBY?diK zjvAikM&ld02dv??I?*HC-USv9Z#)&Ya>3m8wl~vN;r#s)ZaB~)Z$QsS4zz3GlN7sU zJ8+HUoW2i>ny!hZ3%2F}pSPhKN};2+j{A*&rXhC?hn&S8R!h^%N{A(~RoPcwv*2U5c(xj})EKPEN{B{5lL?+HMtsa6O4)6QdDeolz@f~yge}MZP;QlV) zLj+u_B7tfz=i@-%gWEfJ2g^i5;kJ-tS>5(-&moBJiB|P1^b+ky3{Zam2IU={F`FEZ z`Q&&4Z1SWn#R2wQnG{NhrY}TM$3L&c$j-kIyURfiAYY4p$7MnY+ z5q{;K-sWs$W-MyT)L@g{D*2RY>l=2A&~h1SVTM)umS6Pj59X)w;wQm zK%LIG9}gkXhw62zmNtV7(+2 diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/APL.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/APL.cpython-310.pyc deleted file mode 100644 index 01fb083e530adc8907fdb020ca440a9438811d33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3762 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 XMHFr=>CJBcTl1INq^L!4ot)u6@^Exr diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/IPSECKEY.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/IPSECKEY.cpython-310.pyc deleted file mode 100644 index 10865d3a73e4ce48fda0f50364d8bff21ed91804..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2469 zcmZuzOK%%D5GMD%E6J7<*ND>xoT4cpw6#$n2#U5Sf;^EXP=h)x(1p;&dP&JEue2(c zwqs*;vVq+C8>FI_{3Tv`=qZ08J)|?-mF>ErJwtLh|AuMc-slaRl$ zbFtXaxdT%C3W^a%GZI!c4XN%Mp{Z-DuIl+hK&>RgoaHqeMXoKPezZ)8i!uJfAWh(bkEcs!4bliUY zZ2Q5zCl7wv7*v*S$5LJtjpGrIA{9i@C};Z_wwqD(+kTwYBNo=Lh;ZQpTD|$<-q*dK z3NDJ?WRQ<|?>;Z~WIpLVz5n1K&Uy!Ye9(KE?(~XO@-HTFvKJ3{(PQIcOE7sf;l?&Jg%i12iBo+x9fZD3^7P~uMUbHp@PjbOJwhAWD z&J#WPTnoRAqUX=%(2N~BR* zrE_9Tos!JV(wx(hL|_@(P**lv+gz}DU;~-?rK@cLBirN^?RFZqaR7R18 zH1wmmi1yR5{7N9Vm4*8j4QL8rI1w#SmDA3V(39(SF%p=KP$m*F*gMqto=1|wJF(+6W#`F)X(G(O>tBp)Y`S;iod;G-C5Hy%VO#EDG%DP#-fK*;2bE2qLt z`8&67F^DS0H7=c&GLx(jtFW?o50^J(z9-(t?gya4);XAw%-_Yn(1a!RMO+5?BUs=Y zkYWv#XL&$8iw4ws+XNaKv<q_Qw~UOJ|- z4^Misd)-4oI(=Q z=-A9$C#3_v7St{TvWNWZ*j@1nto9n8JAvvo@~>lu0Wz|}OJkzi`tA^rXc7x}rNS1v zoH4SZnlC=amCmW=RL&LKKEpAc6cOQf@@WeOwn20%3k**qWYBBKqxJvt=)zv$mY;Xb z?(;6F?!zjongX+&z$ZZ<*_0baEKlGah8$XCxhx=uV&)W>C{#nI)e)DwITOfg@i{8o zk80IPH{n^fNW41xBI&DSgBOIesyHB);aN>1Xc&QEG~WixhPO%u`gB@i11fP7RM>)y zx5-~5d?M3)EY{C#>1ebsykbgb+2U(>NMaR2}S diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/KX.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/KX.cpython-310.pyc deleted file mode 100644 index b7eb94861a16be8bc61816ff2b77dbc330a97192..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 473 zcmYjN%}T>S5Z=wEOdI3NLe zK+=-r14#nh4r)PtP1cw?5o-7iJRmMUJdp+9BD&(uXCyt$Yu!(?o_smxZ1GTr{DJD7BmRcb-g<6>$X zz(uZAdfF~+L3+oJqD3aAp@J=9Lk|mI)uI!s_BxZDF5*U2gV2PYMGIRF3v diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NAPTR.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NAPTR.cpython-310.pyc deleted file mode 100644 index 8c86c2f00ad09058124e89a58252e5c60556e67a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2931 zcmZuzTaVnf6(*_cXfEE}xa-(yQrnFiC_ro!Z4w|TiZpRLjeCJz4ReZ`ws%YIOkBBi`SNhhv#r8UcU439G3llK;XIh|F<9i zG$7<>G&Uaxj8CDc|A63x)0{+2O(SM(tF7&}cG}v7nsMulM4n*#{=WYe;Wl^92zS8l z><6dTDUG_EJ|v-g0i%;)%CKr53u+h2=TOw2L10~{uq2sPq` zx+l3lo(XmDo8i6T-~PGx?cLdN-H*-0G0dA4lechNJ_w)o=nfrF*#jem^3r3smMTCI zB%+)Et~9bHgtH%MWdA_Mlv~_B^CO2}cH}h1MPZ#umAkTSV|y#x0o$#t1rQ?kjBXp<2fb7IMh{v->|MNo>B4U9sKXg-!;j;v z$aEY>oj6hPqhl?U+=4E08^sQYD8PRXvqJyzBMHZZ$Sc_DV{4I2g?t0duv6PgCaJP}F@871>`wdt!3{X`ex{w7u^DY-HbC(3K8gt@I86XOG=oJV|UgzjlY; zgx~Eu>h^}Xqr$-KB-&0Nm!%T16nUbvqf8&Kw_aOtE^0^eL?-~WP-!yD#>bZs2_1P2 z7F@ff%qCe;2g{-6qGktA%rp%~ct8zMwWrHii>LZS+%9@+KpC~+MX-9HyU*wS2C%kg z>OrsN(+35~XyVKRP%7)3EXax1);`n}>`q$;ZQX^MRd(f6?!r3hRS=yjR(X|Qb*iB1 zR=rdIA$dlJp%n!ap&5M-iGd@4*z$~0|S{=*$cZ3*KGLQy7l$fVOQep5~tkQECxdp zCSSMh2zl@%lOl8tha@_=_S13-VM-|jX5CAZqAapB$+NkLeEp<^v#-@yFPwxry29+t3iQHGe|d5W|Fyb^N#*&t#bbMIbAKnnCE%#~FO9aOfVL-)N)lYr4I3W5Mp| z2D2IjO2bO_;dX-ek>z@9`CIrWf*fIP2(^8vvpl-KoOg3ACdyuAcMO?4%Ee`_ zZol$L4*kvA2W)=r)wQ?74)@@4vDUmo(ULHACk;n@iY}Pos~rc zwQ0+y(?gB$!CeTt;9jB*YE44gYE%UJ7Mu6Kj}3V9)%c>n+a diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NSAP.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NSAP.cpython-310.pyc deleted file mode 100644 index cc1ae2ba6982ec57e8054b8a4c07165f433c2700..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1800 zcmZ8i-ESi`5VyVGY0~TUdKGulp@;`ikZA7-34{>nJ^7 zY`%f1zXu|SpgD=_FO6BXcbc!;e7%@SHulHOuBul!W3$|jEEXa~AoE2RV?g(-~u4%vLT2G%&rLrOCS&g0e0bm^m>Qkhq+4{}saR`M z`-dsoupVpoU%`Ri1tO?H_sN*8=+aq{Kggd9BFg%fJ)MDH;Zas3I?Xa0jN~lOjxQ>o ztS=zSLiSu0fEMeQDjQ~nZ7G>2COgaK(z26t)dprwIw%&Hk{dZQAHzm7AiK0q+Frv* zQQLX|e5+hNgRd@tESx1-kvG925LB?=*&~4BiKDg+9kV6CXhnaczylZ~Z|Mq8_$&4% zFy11#gd4lyF35k{$OkBI{3YmHhAXn7pqU^NK-z&IgndQf)puy9+5|FxqK(RmVONw= zcZJ|qc)PWR8CD+ z7Ix#{qA}IhkUiR+ig#niOS`rAZDTx@&F- ze(>{5$?vZgc+YX_7abfOAo%a18B5=cUn{SN%XeglFwW)o~`$j7p)fMW|1ZV47{G z=|`!|bGURkXH+MKcQUp!Y%VEL#s{_epLtMYphU> P#TniYSxE8cJCEsqh*Gg? diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NSAP_PTR.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/NSAP_PTR.cpython-310.pyc deleted file mode 100644 index 69b000332aa6518807b0f111e1dc92858ca8f66b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 481 zcmYjNO-lnY5KT7QZY#FK*89@>IO5vf=ap{&K)O9+JRCe&{C%gwe>ul3LPmwNHw z$zLFNaJD!DqW}E# zwr`>)MCY0ElT5k|dqstay+{eMstFM#au%9+SBTe{7nT)A2$}doe4xyM83p`4-d^&d zR+;AMIEfVRDm~4Ul=r%Kb1&p`70-EZGU9rYt7hu?Q*W#^m$7bVGGC-hw;$a0|I=FO zBC|mH#Oz@MP(-aF)1a&lO|3~3&2n!PD%dO5?8xLwp;oL%o>pvUbH^!5tXkIghOwVS jX{NMR(j64in`PD!g}Ezwwf=-_^R3#X=pn^ba*F=|lOTAc diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/PX.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/PX.cpython-310.pyc deleted file mode 100644 index d8e60259e71b2842fea303355d207dad219b4d40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2213 zcmZt{U2oeqkkq#o+fCXmZTEq-D>^{HmUcza4Z}7RXxFY-VFXJD6oLUl6`53yYBBUIf?6)#+IS&W_6m?ZB{R~gf;L7{!_v&ZXXkF104)nNA?koLr%9zMj8r!?@*6%cS-jN;3ZSEWgvCG%F&x2zcd%|zI`~%+N;V}gn z0pH+l-hq>r@cC8V<(JHU$XEH=F^N}T_cFh7On|rjjyNRlfKJ!6we@luZoRxAMOsL{ z8QD4V^ypd?4+gjTe&PAy6*a$;5X zDXj>z0e33L;I6@4gL|B8lQY_jeC?{qSV$c(mW{HKu{dOjVv}rCe)T}2ggC&BQ8E+~ zg-Q%o~^{&eqG#@qr9L&@Gq> zkuGh+Z%9=aU7H?S+Ga(C zronA~OO$VJ|U;%(1(?x0hM=Z z9|jkwRz)ybD!&S<){(nSB))KF#o?|fo7n3BaSVGDYCFx9L`iZ5fVRtGPp%@l1|aU7 z+s4XbDFv48YwgHlXe``>yC!;p)7aPs8|TMQQp~j3Kn3S!J_MqK*qJCn&L6rJJ+Uju zZOs0Ga{@F6M?mH~X2-j@gV~P}wQl|d72v5-PSR34m~cjW?Y@zafpwHIAa61$n#8Ze z>g;5>&_P-Zp=gyd&d}{N85N@}P4a9iVh784+4=w+WM2CkOlVR!q?hSNle*361=BIX z=cb#)wM~TGI;N-e(3@j^6IqCQ<L~v zOW)7*53G=en4ni?!CT-;DX`53;y6vFqCr@IP3}dst{Q6GyDWX3jb)L7pR>^}pc&Lu zdGHusP!<4>POoCw{|`@!=d*!0T505C)s>av{AfkP1lzcZ{F;^i0s~r9)RAHTCXm4 zXskxYbjaAS;FBEjHeC@;dOv9dPWXc$YrdBahm#V02Om>lL0jS$Vv;9i60g>%iN~f1N9+8C mTl2WTAgd9#ps~^2bk*Ry+G9Up0xE1>!CGJiwElVahx9+4iu(-! diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/SRV.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/SRV.cpython-310.pyc deleted file mode 100644 index d59cebddaf15d84b9dfcf716b9224013f0cafa57..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2401 zcmZ`*&2Jnv6t`zQA3OWeB&4A&0u@Suyg!?Q;%+F32W#Lz3&LOxP3yn4Re3kIJS>z7;w5n zy6jKTN_q*><;LoXIs`_Lka7ZAX=o2X*RM2WFUcasPyduJ9TTf1NjY za6;h@pI_rG-iDoq@c4D!;aALhz}NWt2??8ggTDr23wAg8)e{0|+Aj$sVFzrxQQA9C zex3$EZc35ll6P6@Ph^_QRKFU)TOIqIS@MWmb^e79kHRSZ-8iWOipP* z3u|ssQjk-tu;;WOk!^TpcxHIV@DA{9;TqoKWQUy5Ue_-jbubaK^rI*pr#gzlAc|FV zkdF1IcO~8?@mh({g+6YL|BhiDF2!FJgeM67G|rp?>@X8otSj`1yAPxkU$iAahp*6AT2x)K5qMB7Ri;2xyo zGFV7XMQQCH87=Y(NK|AEWj&ooT0GYu!bBkk9lAxQP4ubWxs)JHkiaClhvJ_BDeO}+ zCo``e{d#P`NDEdtkP7xJC1ShC<|E_jHYhL{`pl<3?a&Q6ZKJ>E5)Tr@Y|$_Y zu^X4~0;2)J%gD{y%qi%pQ@|U*S2A=@J>#%lusNepeBd1bs_gBD4lh9!92Ni5-+RtVz*x+n*)M03qxg^`J>lV8FagndF%-5Ul4K7gw7~h{a;{;*I5tt6Kg5#ohxl-CDi05=hXdMMEB=i^i%B5KV@3Xr0;xAiD6K zl{OT>5Xvo9Syi$Foo3 zmG+)??cUQKkluqTGFR~Pf#o5J${>nHIX}pdZ$;5B2XR*Kcu~aj1eW1Lpt4-6C^Ds6 zZo++K(|j97Lht2VUV{~R6UjSBZXi>AHsuYF4BHUkZSg!26P@N``N8>GIvO2lj3N9Z z03zs8*g#J5SjXX7#Ts0;4J?g|6HX=LJV8-&-IC45dQDn*%sS@`R4siCTY9fLLi;5%hw9*w+)V^0l@&&+yE$~aD*7Ht;4X!AqmL?QjQ`Y zND+wLun{)5WQ&=n@EmpBADBb4z~ZrB2nL|$96;Bc%u$#T<-ioF-1*CB_)XflvQ6#)t)(_D07cZP zGhNEsFwk4Z@w$+Hq~Vstu#U~`NqVLXd|w*PP7Yn(zR2i*mD){1=&OkjXY4!*TPu3E RJOAE(q_HXLP~0RJ_zyiGb147- diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/WKS.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/WKS.cpython-310.pyc deleted file mode 100644 index cd30aa2d1ebd0fb6a269a17b293fd235c5249d6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2634 zcmZ8j>u(#!5#QZ=A4!RN#A%!wWgiC07PbrIfhKU9z*b!30XC==1UWD`oNiajQO7%a zcPUrG5(p{-`8TM3^S`uT`k|lnF9hggW=UC!kJ#DS-I;yN{APx2ua^?|cK>zfyS)uU z{*8m1Ukrnfp(z7|6HaTAt$LbKH)fgVdVk#qnRnI|WEpaHL9@tl9&qv3r0MxYB&YW% z!5{athzD8x4Qc3eBD_gDN&iB4$fFm8M=ZQ1rWxZj^Nt8-|D>7!139GJJg=Hc=Xuu83zb*1lXvs=ZDa&TWC>2st49A(qGwm*gHtV(Okg|= zt*=CVXd}tXx_~!?lIv608nvB@lY2>RlIKn$&tH-sKYRS)_$wu(8qbc}sTl7Gb*$Uj z_=~+yPKtVbBAS!&7uCU7Ra)Ge73FbpB-EHU>cMJz_2ARd12E$K*{STpNxy@p@PZq( z3%@=+>*DIw>qh$}TJ7q?o8$dHho%mJ9Fc{u!GaU;;vV_-&X_HNMW_J*oSie6*;zy; z0&vS;8-M9(-vpfP5)-{i&gliEEJBBs|I)Z;I0C%B%+y5g)FpiRMuVm1>Ex1Q3{`jfV5uFX44 zWDj<-VJoYnsP%R6{M`D0BxPv@40z4biS@PkyO!Iav?4pG9_cp6`9Huw z;hImkDH`(@W#6;^rrtI^>!3;3awXdD>cfyibUucrAW(_%mgItf%~pME;w8Nxa!WH4 zpM!0hKzo4D811BkbFxT4GQ1#Q>HS4&(q(i(Ch?+UI!^B%=ygD^+q`XJog91e1L#xi zb%%q`{z2V5lOJ=o=rxRciyoZNH67EtV2iHla{o42Z0MdzV4qF1X*PK9COIZj=#8t9 z^K`W6n`F7kL+83_gFro5ALG@ckw3%hz6Hd35R!mWUg!cch?euF z1n}mo>^0o7URf&%WrD~}C$8IL`EwlJ0h0Buv6}1l8q;g=gD@O+4<#YV$djyhWl{%K zIe-;QYfJOj(VQI0cIt#a02zg#j{TU%G^HsE0oAGF`wZto>a#BNG0bm6yA2HzNDtBe zYM&=%0GnKW2zDGhz&`}W&?V7y!j_PFClLM!9vwhQgLFKJ0D=KZU>b%*jU2!mc}&Pd zHacU!d^AjK@LWQ^lkdQWnUA^HCRGEzEOfhyc=0#^=E#%EPT7CL@HYKFjZ%W^ diff --git a/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/IN/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index f3856e7d22260bee177a4d0e933a51e36717d30d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 318 zcmYk2%}T>S6on^$Sj38gONDH+u-U7KF$pv@#L$VgUIvD-Gt|(u37HtEkK@i)%EpCn z;mR3TesB->+|@m&9*+-^;_U0<_1Z@0Tbuuw%G{}uCrUU1v_{p@MxOP49#%|B zH_6iyOx(h!XNsq)^d|dkB z(QTyA!qt5ZZlVMtptl(oPvP4@4`D?2FVR|-m_r{6glH*o;uW;nY!s)N%emoTm&B9f zXoX@P)+ap{gWc*(g&rMNoXaZVd@O`goPUvKX_lPQZ?L~(uLupYI;{#|K47k^ng#xI zClu?T>{yV+3^NVawMcT20y4AZu94#*xZ^x4GtK!;-4D)vQOQ=pgEhXw{E67-8~O)H CAYM!W diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/dnskeybase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/dnskeybase.cpython-310.pyc deleted file mode 100644 index 4342eb2b33ec1094440f21eaca578e48da46cf01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2452 zcmZWr-ER{|5Wl_eJKOmpjY=uhs6xf6fYKs_P*qVN^aErnLM!!T>2$eWJLjD5+}%we z(IHhzB;NWrBvoJdm-eL(eagRpDz!6vj$_Q)J2SgGx3@F%o7pQ{t_>SrI6>``-;o#~ zb~~=}L2rU4BP z2?W8XE3`>luo5tjo}&wNQO}334cmws;JZ~7KJ0EhUjOwzoN@mq(sr6BLbUrOZ*!W+ zq%F4++0H~e&$d}RY1jH~&eD?8j;)+NIA17#%u89OWv+rGACx?kTO(zG^{J;VsR_zx z8#-M42t*nO#u2GVWgeTvkY;5ZS(SARr>~6IhLKa*$0)nf8~VfGD6AYkZopcza<$x| z#)k2RbUO>m5j$hXG4ffF$vD>Tjlwt)@lICAo45HQyfq3=C+_ei7%K}R6*Yhemg>+& z!M9T@>`}7K`116*%{|EkUx9JQQ?_7vUwNErw<)&{y?%?{T0f_i-w+kVu~vg~X_&QO z5B>p=&!G#<c2GIcB7CA4;kQsvvyLcY%GCuRw(BMR039`#;s9f_p_WSKP^XN&V8PQdajlPqQkxr^KDk8pFU&`HMi(OUykm8r!xh`@KB}?a}0>kEg^ z1jxuZrez9uArvH$mr_7M!ZO4!<7z|Ks1cJ}CFP&tGcr4}pP)PhHsH=Z4Rpu9QKj#_VYx)dx*Z)i; lruA9*U)P@w-(cv)$3XmLOgA5bp?}tj<+^Lcz2*WM{|6k^JzD?( diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/dsbase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/dsbase.cpython-310.pyc deleted file mode 100644 index 67d4efd25cbba2731be8c355c1471a292b7ae24b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2489 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 diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/mxbase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/mxbase.cpython-310.pyc deleted file mode 100644 index 91ae69e7926b4316ba75a20efc8af01b88f7414c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3103 zcmcIm&2QX96!-XRy_?-_lD0`oDRO}VM(u_ILINQ`ZD|oSD?wTmSu0tNXOej1wU-%h z(yW|QBK6EG-q=nyAwBfKtme(voAG<^_dYghwHgYvYk%C@$(oAt zCoX220gLaTi(?>EaTQ9a8WESsQFS#r>g8yZqgjqMS7Tb=>RV3~s!{z|p*pPV{l<}Y zMBKU4GlQCNX0kcC-#p!~Q4991a=%5@b;YTVudi*~i^5%IZ~B7SLF5a;MCUIMQ0WFp zXPaIwL<|$AfZ&R&QUU_1RNGcv{iU)+s7{Sz%QfhAYSH>JaZOgMn{@Q7yVm zTeJ-)bylM*^a`Dq`whB47mpQCrADvPYsU)kHeV{b;ehRs=!aN5ZmL(aAsXK}!Ci@gYT{CJxMh(^_Lj>>7!#m7KW zE?Bgc*Ep3%&rMF#19$_OCCilLb zcnv=C9&}*>X_F?IC*v!Hc{`N~-Dd&HQnkuNKf#808%U<~Pfc{FQ!q|n&GapG35?>X z-LY|p+INJbNoCxHU?)ig^EiwAG~5f*1F5NFa0}kb&4h>BVVpOr^D)cS-FkwS4E!h@GgrrWyQruIW{?kkUg_B;4YD-jcjfsxEfK|2D2gj7-k?chdze@Do{e-zSOC0RhIU z;T*e!2XVr1DV@q8h3^w-(Tj$<<_&ogfN8^c8>S&dMtblqydYE{CK=zX0`(HU0C}p0 zb5v8xfT5ErebQIKG022evgo-6Il_fJgy~1*`X~(}_eS;MSz#cVGVZ9-tht3A;%`Rm zqWla0x$*!$EroBZDxbF}WW?o{h`AIso#+L%x=+&nLDc-|nPqX_3s&--oU zN99S)^Jo&lHl#}tC8_W{nc(;$d^ewy8FawXorLmb*x~OWv60+HatBD>Dl=`sq6n^^ zWt=%=LECY(<}K(l`B{ptT53~m7^<$S&3_s-)o2pSP_;!OIRoH4*Dz6Gd-X1mbG6ev zt(tYLpiu7&h|gNyejZm*#^~C{`1d!fdw1>4QEKn+K-RUB7=agL4So1K}K0VZ@5mC zdH4r#J~jD=FmS9M+(Cl%zHo|rIJ*q{RXBJ8y+{Lq{gTdc@3km%%*cS@%B(1l3KKzG z1Dd1%9nDLyd?RemiiM0u{t2kW?<2Xy{=ee>r$ENHU#IeU9QbE=<1%Aof%qBvnXxsF zdrrH6Y6a$Q3zAj`{>!mp8YVHvpepvl!C)l46aHrc3wpj=$C><_=*|~Ynd>?-)z!~# z7zK~<3;v^&VJuOWU!M_G3XPtZTVEGB=^IS-;w>Qhf(41eBE`?tmWb&r60^QU{smY) B(DeWS diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/nsbase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/nsbase.cpython-310.pyc deleted file mode 100644 index 37df1873ebaabecad3244ce7d2c4139b5d9909eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2091 zcmb7F&2QsG6rb@|oHXgjw%Yl<6$cn=o@eGgKmYuDA1->m4uP@p+xF3Vn~>je zvp8JXynv}jAUKH#r`*bDWSP6&+@0p`MwYOSy<_it!fozc6Yjvib?jf+S2Swh>s;=E z&J%5O-r?4e^jp)%;qY0Oo`_&SRw78USSg_ff53}Ln4nx7PP0)z!$OdV0yqE_+1xs$ zk@JomPy@k_T)xU%+`p!gCt7WnukkkTTvGt#^GCePd!T8H7GLMfe8rr1-VujHO8{!4 z^1|V_0B5>`vIZ3#6f%%J)^VVZVjZL^FtFo12#0|bNg?^5@^mZ@g-&Kb5ihQB+A!6} zAT+rmH?*Xsb!$;lk{heEZ)r)G&B>75(Xj7St~#9vS^12md8!$Ud=@K~$73PU4_G)# zWCvACa>H5WNv<#85!Bw%s?C@=XY7vr^~1}rM{ksnYBV`4#$vQ9)QK)8qgT7%oyFPc zOyp;ySLyyprCL0j#K}o~DAb7OYNvLpc5;Q`8B8vu2mS+?3O{L?uF~mBP1axrHGG{Q zh}pnoLfao6C8i-P)I}l3?V@)|K6W2DW{Oxd~3+uk0jK5`9Q0EmGOKIFT#3T?G;K=8%~# z{uOciKo(p4zC z?=8J_8*1HqYUMf@_C5I+ZVQ}xlUPDJ*R*1;y^m_uaD-pRYSS;l$S~QlfXS^zCKs&w zR`|Mahp)psI}G>gjO=0!V%;%Tbr>5L{4~RLm$6??{0e2Xnt*AadB}XF}>g7r`!cPNW}u>p0d=gE;547vq4Z(1vuppVbC4hrBq? z6X-^K5dOys;84Px&ME++yeB^ZTI7c)=8PM%F*48b96R-N>me_LS+>hhKnv~Y30i)N z0{e^n9EFMP+^bm`*L~1_1yf-OU>uhniD&&K^I+72jyn)<6EV?gk;6|dSM^ys9-kT> z;O7M<$Z*ugmH8hUr-%s?)mif`pW@}&o7CIh Gr2hbRRpt=@ diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/svcbbase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/svcbbase.cpython-310.pyc deleted file mode 100644 index f0e2082252e9bafa9ec14e464352ad595e16e751..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17343 zcmb7sdyrgLTHk$j_wAmZ(P%V!%W_+bQUIi?M8ES!O$pex=2#}-_QfvYH2T&}eZlIt@QiUp2DGEV_ zh}t#3-*@i4{g@uv>8bPGbI&>VJihli_q)@boGcmm&Hm{lSHC)E82^JegTHCqoI(mJ zmSK2?XD%9beKqT*+*@@^u6Es#Yc9FwlWQTly2-VeTuaGyBDt26>tu4Bsyiiw|gaT0@od0xxUkz z^rn#C_s2jyjk=yd&jzC*7s$l+r1qq-Qn-MW25|$tbC`p z3+20#^8H!)Zf_6D_axcd%|RqqM(`2_BtUN|mz`G{v;Fse`9Bk$B&go8g5H>Z#S zvXgI+bHFub-S#XzWyf1y>s;$}Z+6Z%RdeYj|8{SCQc$_@`tzTxq{X$W6T6K@r@7=e z8gZ%7Sn7H!i_DiBjq5AT#iXXtXn5ULqjA?z1q>+Q!OPD-ck#8rSHZ>QE8Qjk;+!8` z3%kn~U!FU2qq%tThTpky@#XfVi$Oc|k1jV`*P2)S;G)+FKCHa(_Oc&*IJnWebg3Em z$Chs^NQ1GHD{=r_!!@O3!@_OUo?+KzsI@V z+7K1*z6*~d3mYTQPODju{ z^GS~CSiP<3{Enryn+~RC@JQ9F)yrH-`kWqR8>&Xfn`i`AyDAh8d5ZNr0D80OgU1G{ z-+xT|r8A%1e5gWWS^1aSx1P?1neGpxt2P}%m?ktX7Htgi|E7BB|rzr%%`BPS3yc>Str;^vmaK@s`>v zjkz;tPrvr^d_xMH^RK)*AG_zyzy9ot=W6q@edhTW<@N+`>xH>jUOaz#{>3==%8T>! z=i>>P+L9k$?RsiE$Dx3zT?BgwGFj9)a)>Gd>_rNW0Jw%@Iu_EBz;!GfO~Z#}5LL2SxLzCID*H{0N@nTCaw> z3#VUx`IXO{nH#&1L+Ik0kpeDD7GgpvuylwGLIRi|r-C*Q%%ic{s7}PCcF^twVYAcnZ-V){N=@F%NJtC&QkN5U$qp~L_B%9t6F~Jir?{7yETAp zVm6*^KwG!HX6QFCr%#|Lm<4dml34JwS>>;|G@aPODFt0|^_!ZQP-rHd+ z;SNgTfu}AG&5C7|OPST{$dD%@W6pTv(5e+#p>e}d+ak;_G$Z&XJB^PTtLAklf^T#! zrw-uiTr+Srb$wE6db!Bjk+!9E&evk&fqC&>1w-8XM*zLt#lufO<5evvYCmW-mwgXv z{Hm(j^}=;f5*!daTyt!0phHnV(Y}29+t8C3b_X2qnlt7!a6bhxR$S1~N=ZSkR#rL# zYJii?YnB4{UVyKsCE<>_ij}R}ksVoB*E^9B*}IKZC$c>UYqKNxe|Tn9>T~KyXf9X_ zHu-(D9pxr#_uNRkT-G1Q$*E6`)aSGMob*$V^1KG$A?UD5vf$Fsc!*_?jsokD(WO|?|B5& zSodIfHDeuaRbBNF+{HG0mAIH$ig@z1j(=;}Z-u^hrsKthcHp(Iw8MDf!tGAjyrt#P zZg;{s?{_G@RX5H-xK{kQxB>;K`N3R_&9?d^2e4WnL3$=Gvhi{kPmZ#F5e6%H5Dx^W z09?`Kgk+9~|4pO5B5lg1WtL6%FPz=#Gw5W9iD(An5xfKt z=bOvRe#b+T^DKLn-~uah@Kl!q^{p%*fkvs3Zv@MW?eKe06+8~0Ns$r)=uQ5nfa;Q& zH_MiLzcdB8y@CehMkr2QX-0eaDks8eCAgvsh{_&WTsj`_So2&?3!NSfSfo z5&xh9?XJE0WjgzQ2#(E$$T&Ug1!bBXxMI9y>=P?!i)Vi;uiD=%u z)!QP|IhNIJH1*;Vse|mcK`_o$c>@*iBBd7IvMksbmTth6gThm6N{S8QN@J?-_`sBh zT`X{xM_zWX$U|euzSTw97IFSflopYv^KW8nPy&9Z}F_=}e{ zPxjG84bMGVyVDLEjW6R)JqOU+J~-oJY5k^zSKq-W2TA@R7K|ae(Cc5Y@;d=~DK17R zz5y3D8WR@*`3X2MR*awoMFM<_MJf{;^vYOr2mA-jhya5HDXF5C?plhz$5oZ1r{y;iBJe12$5E1tgdUH*o=uN@Og+5!{LUotj_|%meUIL}_@O z4VR^9WU8yo4^u~d6Uu&t~sR`ETToEMRbp(HL9;yI4^ElsCuuz?`_?#9z-E1qr zpyx2FX@xGs?g(?q*M=l2 zRe`jfvP--I0e{04rxTBP#%|*a)^%==OfBhp0|8BE9eaALr(Zg`*bc&0cWL?Kzr#*B z!Y-rt?3_gxb`dn|yTY-^oVL!t?RwXvQ-eK1IUM0NhSC&#_N^LXf z7gY0cKEPpz@2O`nu53~ix6*MgM3;W-puYf`L3F^|sHhi~RlBPi*JAV901pZKkn4U6 zNj6h6&{K2{rXg1)T&?$}ptUwx)ewPgbU`9N&#vewq~u-0A?~^m8Ki?xMg>uI9zq~0 zRv}Oxdm(epSWk!}69Hb#9nL0>3jL2sh$kB~$TXN}&`k?Hr#b9St(~{XyJmo2D5%#T|E|>K_t}LE3+3`S$?yo)}p}VjRZd3tLEM0XqUE*y)bx znkpPSMvY$ACELsu;I zo@u}O9yHF5h6IxmPBs>+Lx#v668%G^73aM@qE)-`ANJu?v@e~tBpB{lY*6P}rp~(h+!=c&VwAGvK58GGfL%1Iz z+c7-lnb57WS?%jqoEtb=Wk4iybZOyRJM^uoZD|KK^hvHEJ=H%UAckO&xVpq3#a7!J zMckXHet@J2b+|wGhiFyN_0S{#l+Ot@`nNIisMNihZQct$JD;+o~$=*>k zV{TM4%G!P$gO09)KJV9&f--;uM;{DlmcQZJy*>T)ysrwRLm=yV8ks}|&J3zRIF8t| zXf?=nLM3Jj5wD+m)?=T9)W|HU5Y-n5et>{`!HpVm+){dInS(ZvJxj^l0oCq&V}vZ3 zI#fTz&ih1_ocJ|AjEet*)K_vjC^_45#KUK83u)+=D!Kb}C{8_mADW+<3qHJq{6;U| zeyEo}Q|r$8mzyh#VMd1`F`?RHBHH_#d2E;uvET^7HiG^VWp&*0Y{hfxJCW(_+c-%7 z5NCsmp|o?j`}8}LExpU*4QvuhG;P>y$o7H9`#fUp9qM$CdU_Q{n~Tex3g1=0IV&$gkHDeb#X40GJr$Hp$CzV3uEmQV}a6Pxxy5YGcIPyzA z+ZZuJ+AcvF{cIr2R;BbboQM;lzUzok_Z=SfIXrSV zagF<4ℑ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 aZAaRhq+Ph~&%;OU|2co_mh&@v%)bZW!TpB- diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/tlsabase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/tlsabase.cpython-310.pyc deleted file mode 100644 index 053c054698045027ebeee08e3bb347641e92b1e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2081 zcmZ8hOK;pZ5GM7Oyqnl*nkGRTY>K`Fv`K+pilPV-=g}5*_7J-lVF5xGxwdSrv?aMt zypVwcHjrC?gI)BJzr;%qJ>@SH1=<;E?by~XheLAsm~XzBrr%EpeAoZ_X!{e;{>H)i z&xgT7XzE80oN!u^tm|n;?byj&+k1=N&s^c|1UtbGgge|lA{@uzPITxV(k$k5ouuAd zIE@Sol;=NhF;E#Og5V9A!)fMj!C8OM%zI77l)KzJiZY)s^N>eJGz&x+`+SARJUOCp zN5rr39`D0SEJFSszrwHD`Q$b6NVWv`UpLXl+WMo_T#5N-CWE5a)1kiyyk=T z=RZAv`e-0U(MYaR&-gQyZwV7AQHeq~()bg-KNZF+gw#cN&Jonn7Z;jZ1)<3yIi@Xb zofC(WmK-~+dqP{nT&sIl_pI()-3L8r1FMIetdlo%m`27|v#F3KVyvu7%~%$*T(MbM z>u)7qCh=B@LF-mF_q9+mfN>fc4<0@?q2$(C6G)EFzqHR9zo8~(%$hOwhWxYk_`A_B zN=P-DZZ#7zdLq=WZlmHL6a^ONwIpqNE zfyV*T9S0irp7w!?A!rd0hqhixTlY`;I~{vB0MyhQnz-1W)w`;ki?_eQk@KZb`C#!^ zX$-+_ru)X7Hq%Q$85jIBzT~;ivyg3zSLJxWgW8wqnF$(MZk4r3q^NRT?!gtt*?lQj zU{PK@6U%5D>V|3YN~bVTI1>RX4)yHsCJp|bFQ1{aFulOICD?+jdyM-Zf>=NkF8XNE z#|YI4@DE^1w0rEe$q7A3T7ukc!!~N;HaQH|iNw=VKa017?g*CMEtwWy&nDJD5^ zu-;-N7qu?OCD6kJqAnT^IkH*Sxhl%i#IqWpsQ{aF$+$(OBtBL4Kp0myyYd4Z-UN~L z-{Hg{y)N?EB6}INcr2TV#qAq7K;fa07g5A6q1WjA+8JhNhR+IQ(dmbofz879H7FX= z6nJuuK_}jU-_m2hg~Wu^MUCu0Vp1rBz#wNh_wKH)u0nnVO3PWHjfWX<>G{TgDIqyJ zegqvqym46pR7EqHN}-fR!t{!~ZtAkgE2K-XEpjg8Wxpf9hrKMNcmPjU=)etd_+knz zEH1ct@Ju_o7=jo+>!{qrs#)g~!I()Hn>2h@q26Qc*I8aIRzk*jQ@}LTKUFnaF=p$Pybbr7 zC0i0FLT@)*4)D!ip!gEk`ip{Dh^m53@AA8kCYaI^p~7?24GqJevx{tsk-?+yR} diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/txtbase.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/txtbase.cpython-310.pyc deleted file mode 100644 index 2e093b0b2bebef06e1103e7d086d48e67bb95755..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3154 zcmZ`*TW=f372cV>aCb#gm&jHm%jq_4>M~7~20_puFod?Y+y)6)Ad%B{p<=b-45_7- zyY$S^mIw+cDgp6Ze?U<{ddy$xPneei>68CK<2X^znI&b}X_lBXw=d-~YbY`Y!K~O~gwdP~XiNuoY!95+8Mv`K@M3RJi)#eu?c9$8 zQ-{-fZd%u;bt4XV&~Nsezq6Rb+*6CW(4X%woY*HMUS#%XR?8bNZ~tlg?L0f+(OxQf z)X7sRH=e*fU{c$^DUP&rH|r?vf26ob_j0cNKMYk?7HO{C?a>eh-1`Oe+Z|kV^;?*B zUZ0`2GevLU$`~84X9`ZR}=Z!91wN|aJ_l4CZ%w^tbJ#GfI zz-OWLVt19Vj*8*bNm(F;LEsz;Yy!1So744ukq`+BB-&|@127?tn|OX*TR*( z>!7pRU+Xs6B3n9j0k9ivjV-flrzBqI*VzqrovoY_7{B?2(U%vN#YeUzh5?Rrcx+a)$ ziS`6jM?>Cmt{{wU4~h*%Zh}zOiFHOMWJ1p=u^wAzbYdG2flsIYIely;wsIa@eP95y z52(1QT;`mRzX8mK4gdP6$W)f**_cP>f)zE)^*6#WntpFiZ}sL|QCdX1yIG-jchNGn z&nsKarK7TIMm|OBUtEs1{P1d={lUdkXmE9;kbtPUySsO!xZK^nykmy|AhQqK7-g?O zkr0B2jWscGc8+mix3`~Mz;KJiL6XYEY}O*09DYf(BYEEa(t7&woey{JOD^QjuvZTF z&Rs4KR5{%FyzsI$?QQLqBI{*vpx}9`vWGx4O%EOc zy}25RqJvbPeKlxc`521)00bk)4itA{^{utMc_eVC>3IOEgbLt{$e*N)vObqV;5{=Go}`!gUldgqVuU%-LiiA}7+e;2Ot2uAVu zXDAPBW`Tcb`w3=*mTSzZfb#`F!UY%cd_`Ko8KS(W_O<&+Kz3?*hUePpX853Y$^qy} zX#mpoPFj>j25AR^Q~VS*e;FMgJ^3gTJb_8W_>e3B4C@#4uP?;?RP6;Qkm{H8{t!Aq zZ?~d1BS6*_Xd}J7i3`scL^MER$d9wqpOVuxxB#`MwX@H__to@dS#R54G853QR} za=S}uWb79;9YAGn4; I&t4<{1DC@gP5=M^ diff --git a/venv/Lib/site-packages/dns/rdtypes/__pycache__/util.cpython-310.pyc b/venv/Lib/site-packages/dns/rdtypes/__pycache__/util.cpython-310.pyc deleted file mode 100644 index e40393db5917981537e7179e071e5ec9c9ea16fe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7165 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 diff --git a/venv/Lib/site-packages/dns/rdtypes/dnskeybase.py b/venv/Lib/site-packages/dns/rdtypes/dnskeybase.py deleted file mode 100644 index db300f8..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/dnskeybase.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2004-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import base64 -import enum -import struct - -import dns.dnssectypes -import dns.exception -import dns.immutable -import dns.rdata - -# wildcard import -__all__ = ["SEP", "REVOKE", "ZONE"] # noqa: F822 - - -class Flag(enum.IntFlag): - SEP = 0x0001 - REVOKE = 0x0080 - ZONE = 0x0100 - - -@dns.immutable.immutable -class DNSKEYBase(dns.rdata.Rdata): - """Base class for rdata that is like a DNSKEY record""" - - __slots__ = ["flags", "protocol", "algorithm", "key"] - - def __init__(self, rdclass, rdtype, flags, protocol, algorithm, key): - super().__init__(rdclass, rdtype) - self.flags = Flag(self._as_uint16(flags)) - self.protocol = self._as_uint8(protocol) - self.algorithm = dns.dnssectypes.Algorithm.make(algorithm) - self.key = self._as_bytes(key) - - def to_text(self, origin=None, relativize=True, **kw): - return "%d %d %d %s" % ( - self.flags, - self.protocol, - self.algorithm, - dns.rdata._base64ify(self.key, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - flags = tok.get_uint16() - protocol = tok.get_uint8() - algorithm = tok.get_string() - b64 = tok.concatenate_remaining_identifiers().encode() - key = base64.b64decode(b64) - return cls(rdclass, rdtype, flags, protocol, algorithm, key) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack("!HBB", self.flags, self.protocol, self.algorithm) - file.write(header) - file.write(self.key) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("!HBB") - key = parser.get_remaining() - return cls(rdclass, rdtype, header[0], header[1], header[2], key) - - -### BEGIN generated Flag constants - -SEP = Flag.SEP -REVOKE = Flag.REVOKE -ZONE = Flag.ZONE - -### END generated Flag constants diff --git a/venv/Lib/site-packages/dns/rdtypes/dsbase.py b/venv/Lib/site-packages/dns/rdtypes/dsbase.py deleted file mode 100644 index cd21f02..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/dsbase.py +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2010, 2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii -import struct - -import dns.dnssectypes -import dns.immutable -import dns.rdata -import dns.rdatatype - - -@dns.immutable.immutable -class DSBase(dns.rdata.Rdata): - """Base class for rdata that is like a DS record""" - - __slots__ = ["key_tag", "algorithm", "digest_type", "digest"] - - # Digest types registry: - # https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml - _digest_length_by_type = { - 1: 20, # SHA-1, RFC 3658 Sec. 2.4 - 2: 32, # SHA-256, RFC 4509 Sec. 2.2 - 3: 32, # GOST R 34.11-94, RFC 5933 Sec. 4 in conjunction with RFC 4490 Sec. 2.1 - 4: 48, # SHA-384, RFC 6605 Sec. 2 - } - - def __init__(self, rdclass, rdtype, key_tag, algorithm, digest_type, digest): - super().__init__(rdclass, rdtype) - self.key_tag = self._as_uint16(key_tag) - self.algorithm = dns.dnssectypes.Algorithm.make(algorithm) - self.digest_type = dns.dnssectypes.DSDigest.make(self._as_uint8(digest_type)) - self.digest = self._as_bytes(digest) - try: - if len(self.digest) != self._digest_length_by_type[self.digest_type]: - raise ValueError("digest length inconsistent with digest type") - except KeyError: - if self.digest_type == 0: # reserved, RFC 3658 Sec. 2.4 - raise ValueError("digest type 0 is reserved") - - def to_text(self, origin=None, relativize=True, **kw): - kw = kw.copy() - chunksize = kw.pop("chunksize", 128) - return "%d %d %d %s" % ( - self.key_tag, - self.algorithm, - self.digest_type, - dns.rdata._hexify(self.digest, chunksize=chunksize, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - key_tag = tok.get_uint16() - algorithm = tok.get_string() - digest_type = tok.get_uint8() - digest = tok.concatenate_remaining_identifiers().encode() - digest = binascii.unhexlify(digest) - return cls(rdclass, rdtype, key_tag, algorithm, digest_type, digest) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack("!HBB", self.key_tag, self.algorithm, self.digest_type) - file.write(header) - file.write(self.digest) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("!HBB") - digest = parser.get_remaining() - return cls(rdclass, rdtype, header[0], header[1], header[2], digest) diff --git a/venv/Lib/site-packages/dns/rdtypes/euibase.py b/venv/Lib/site-packages/dns/rdtypes/euibase.py deleted file mode 100644 index a39c166..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/euibase.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) 2015 Red Hat, Inc. -# Author: Petr Spacek -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED 'AS IS' AND RED HAT DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii - -import dns.immutable -import dns.rdata - - -@dns.immutable.immutable -class EUIBase(dns.rdata.Rdata): - """EUIxx record""" - - # see: rfc7043.txt - - __slots__ = ["eui"] - # define these in subclasses - # byte_len = 6 # 0123456789ab (in hex) - # text_len = byte_len * 3 - 1 # 01-23-45-67-89-ab - - def __init__(self, rdclass, rdtype, eui): - super().__init__(rdclass, rdtype) - self.eui = self._as_bytes(eui) - if len(self.eui) != self.byte_len: - raise dns.exception.FormError( - f"EUI{self.byte_len * 8} rdata has to have {self.byte_len} bytes" - ) - - def to_text(self, origin=None, relativize=True, **kw): - return dns.rdata._hexify(self.eui, chunksize=2, separator=b"-", **kw) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - text = tok.get_string() - if len(text) != cls.text_len: - raise dns.exception.SyntaxError( - f"Input text must have {cls.text_len} characters" - ) - for i in range(2, cls.byte_len * 3 - 1, 3): - if text[i] != "-": - raise dns.exception.SyntaxError(f"Dash expected at position {i}") - text = text.replace("-", "") - try: - data = binascii.unhexlify(text.encode()) - except (ValueError, TypeError) as ex: - raise dns.exception.SyntaxError(f"Hex decoding error: {str(ex)}") - return cls(rdclass, rdtype, data) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(self.eui) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - eui = parser.get_bytes(cls.byte_len) - return cls(rdclass, rdtype, eui) diff --git a/venv/Lib/site-packages/dns/rdtypes/mxbase.py b/venv/Lib/site-packages/dns/rdtypes/mxbase.py deleted file mode 100644 index 6d5e3d8..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/mxbase.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""MX-like base classes.""" - -import struct - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata -import dns.rdtypes.util - - -@dns.immutable.immutable -class MXBase(dns.rdata.Rdata): - """Base class for rdata that is like an MX record.""" - - __slots__ = ["preference", "exchange"] - - def __init__(self, rdclass, rdtype, preference, exchange): - super().__init__(rdclass, rdtype) - self.preference = self._as_uint16(preference) - self.exchange = self._as_name(exchange) - - def to_text(self, origin=None, relativize=True, **kw): - exchange = self.exchange.choose_relativity(origin, relativize) - return "%d %s" % (self.preference, exchange) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - preference = tok.get_uint16() - exchange = tok.get_name(origin, relativize, relativize_to) - return cls(rdclass, rdtype, preference, exchange) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - pref = struct.pack("!H", self.preference) - file.write(pref) - self.exchange.to_wire(file, compress, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - preference = parser.get_uint16() - exchange = parser.get_name(origin) - return cls(rdclass, rdtype, preference, exchange) - - def _processing_priority(self): - return self.preference - - @classmethod - def _processing_order(cls, iterable): - return dns.rdtypes.util.priority_processing_order(iterable) - - -@dns.immutable.immutable -class UncompressedMX(MXBase): - """Base class for rdata that is like an MX record, but whose name - is not compressed when converted to DNS wire format, and whose - digestable form is not downcased.""" - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - super()._to_wire(file, None, origin, False) - - -@dns.immutable.immutable -class UncompressedDowncasingMX(MXBase): - """Base class for rdata that is like an MX record, but whose name - is not compressed when convert to DNS wire format.""" - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - super()._to_wire(file, None, origin, canonicalize) diff --git a/venv/Lib/site-packages/dns/rdtypes/nsbase.py b/venv/Lib/site-packages/dns/rdtypes/nsbase.py deleted file mode 100644 index 904224f..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/nsbase.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""NS-like base classes.""" - -import dns.exception -import dns.immutable -import dns.name -import dns.rdata - - -@dns.immutable.immutable -class NSBase(dns.rdata.Rdata): - """Base class for rdata that is like an NS record.""" - - __slots__ = ["target"] - - def __init__(self, rdclass, rdtype, target): - super().__init__(rdclass, rdtype) - self.target = self._as_name(target) - - def to_text(self, origin=None, relativize=True, **kw): - target = self.target.choose_relativity(origin, relativize) - return str(target) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - target = tok.get_name(origin, relativize, relativize_to) - return cls(rdclass, rdtype, target) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.target.to_wire(file, compress, origin, canonicalize) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - target = parser.get_name(origin) - return cls(rdclass, rdtype, target) - - -@dns.immutable.immutable -class UncompressedNS(NSBase): - """Base class for rdata that is like an NS record, but whose name - is not compressed when convert to DNS wire format, and whose - digestable form is not downcased.""" - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - self.target.to_wire(file, None, origin, False) diff --git a/venv/Lib/site-packages/dns/rdtypes/svcbbase.py b/venv/Lib/site-packages/dns/rdtypes/svcbbase.py deleted file mode 100644 index a2b15b9..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/svcbbase.py +++ /dev/null @@ -1,585 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import base64 -import enum -import struct - -import dns.enum -import dns.exception -import dns.immutable -import dns.ipv4 -import dns.ipv6 -import dns.name -import dns.rdata -import dns.rdtypes.util -import dns.renderer -import dns.tokenizer -import dns.wire - -# Until there is an RFC, this module is experimental and may be changed in -# incompatible ways. - - -class UnknownParamKey(dns.exception.DNSException): - """Unknown SVCB ParamKey""" - - -class ParamKey(dns.enum.IntEnum): - """SVCB ParamKey""" - - MANDATORY = 0 - ALPN = 1 - NO_DEFAULT_ALPN = 2 - PORT = 3 - IPV4HINT = 4 - ECH = 5 - IPV6HINT = 6 - DOHPATH = 7 - OHTTP = 8 - - @classmethod - def _maximum(cls): - return 65535 - - @classmethod - def _short_name(cls): - return "SVCBParamKey" - - @classmethod - def _prefix(cls): - return "KEY" - - @classmethod - def _unknown_exception_class(cls): - return UnknownParamKey - - -class Emptiness(enum.IntEnum): - NEVER = 0 - ALWAYS = 1 - ALLOWED = 2 - - -def _validate_key(key): - force_generic = False - if isinstance(key, bytes): - # We decode to latin-1 so we get 0-255 as valid and do NOT interpret - # UTF-8 sequences - key = key.decode("latin-1") - if isinstance(key, str): - if key.lower().startswith("key"): - force_generic = True - if key[3:].startswith("0") and len(key) != 4: - # key has leading zeros - raise ValueError("leading zeros in key") - key = key.replace("-", "_") - return (ParamKey.make(key), force_generic) - - -def key_to_text(key): - return ParamKey.to_text(key).replace("_", "-").lower() - - -# Like rdata escapify, but escapes ',' too. - -_escaped = b'",\\' - - -def _escapify(qstring): - text = "" - for c in qstring: - if c in _escaped: - text += "\\" + chr(c) - elif c >= 0x20 and c < 0x7F: - text += chr(c) - else: - text += "\\%03d" % c - return text - - -def _unescape(value): - if value == "": - return value - unescaped = b"" - l = len(value) - i = 0 - while i < l: - c = value[i] - i += 1 - if c == "\\": - if i >= l: # pragma: no cover (can't happen via tokenizer get()) - raise dns.exception.UnexpectedEnd - c = value[i] - i += 1 - if c.isdigit(): - if i >= l: - raise dns.exception.UnexpectedEnd - c2 = value[i] - i += 1 - if i >= l: - raise dns.exception.UnexpectedEnd - c3 = value[i] - i += 1 - if not (c2.isdigit() and c3.isdigit()): - raise dns.exception.SyntaxError - codepoint = int(c) * 100 + int(c2) * 10 + int(c3) - if codepoint > 255: - raise dns.exception.SyntaxError - unescaped += b"%c" % (codepoint) - continue - unescaped += c.encode() - return unescaped - - -def _split(value): - l = len(value) - i = 0 - items = [] - unescaped = b"" - while i < l: - c = value[i] - i += 1 - if c == ord("\\"): - if i >= l: # pragma: no cover (can't happen via tokenizer get()) - raise dns.exception.UnexpectedEnd - c = value[i] - i += 1 - unescaped += b"%c" % (c) - elif c == ord(","): - items.append(unescaped) - unescaped = b"" - else: - unescaped += b"%c" % (c) - items.append(unescaped) - return items - - -@dns.immutable.immutable -class Param: - """Abstract base class for SVCB parameters""" - - @classmethod - def emptiness(cls): - return Emptiness.NEVER - - -@dns.immutable.immutable -class GenericParam(Param): - """Generic SVCB parameter""" - - def __init__(self, value): - self.value = dns.rdata.Rdata._as_bytes(value, True) - - @classmethod - def emptiness(cls): - return Emptiness.ALLOWED - - @classmethod - def from_value(cls, value): - if value is None or len(value) == 0: - return None - else: - return cls(_unescape(value)) - - def to_text(self): - return '"' + dns.rdata._escapify(self.value) + '"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - value = parser.get_bytes(parser.remaining()) - if len(value) == 0: - return None - else: - return cls(value) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - file.write(self.value) - - -@dns.immutable.immutable -class MandatoryParam(Param): - def __init__(self, keys): - # check for duplicates - keys = sorted([_validate_key(key)[0] for key in keys]) - prior_k = None - for k in keys: - if k == prior_k: - raise ValueError(f"duplicate key {k:d}") - prior_k = k - if k == ParamKey.MANDATORY: - raise ValueError("listed the mandatory key as mandatory") - self.keys = tuple(keys) - - @classmethod - def from_value(cls, value): - keys = [k.encode() for k in value.split(",")] - return cls(keys) - - def to_text(self): - return '"' + ",".join([key_to_text(key) for key in self.keys]) + '"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - keys = [] - last_key = -1 - while parser.remaining() > 0: - key = parser.get_uint16() - if key < last_key: - raise dns.exception.FormError("manadatory keys not ascending") - last_key = key - keys.append(key) - return cls(keys) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - for key in self.keys: - file.write(struct.pack("!H", key)) - - -@dns.immutable.immutable -class ALPNParam(Param): - def __init__(self, ids): - self.ids = dns.rdata.Rdata._as_tuple( - ids, lambda x: dns.rdata.Rdata._as_bytes(x, True, 255, False) - ) - - @classmethod - def from_value(cls, value): - return cls(_split(_unescape(value))) - - def to_text(self): - value = ",".join([_escapify(id) for id in self.ids]) - return '"' + dns.rdata._escapify(value.encode()) + '"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - ids = [] - while parser.remaining() > 0: - id = parser.get_counted_bytes() - ids.append(id) - return cls(ids) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - for id in self.ids: - file.write(struct.pack("!B", len(id))) - file.write(id) - - -@dns.immutable.immutable -class NoDefaultALPNParam(Param): - # We don't ever expect to instantiate this class, but we need - # a from_value() and a from_wire_parser(), so we just return None - # from the class methods when things are OK. - - @classmethod - def emptiness(cls): - return Emptiness.ALWAYS - - @classmethod - def from_value(cls, value): - if value is None or value == "": - return None - else: - raise ValueError("no-default-alpn with non-empty value") - - def to_text(self): - raise NotImplementedError # pragma: no cover - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - if parser.remaining() != 0: - raise dns.exception.FormError - return None - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - raise NotImplementedError # pragma: no cover - - -@dns.immutable.immutable -class PortParam(Param): - def __init__(self, port): - self.port = dns.rdata.Rdata._as_uint16(port) - - @classmethod - def from_value(cls, value): - value = int(value) - return cls(value) - - def to_text(self): - return f'"{self.port}"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - port = parser.get_uint16() - return cls(port) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - file.write(struct.pack("!H", self.port)) - - -@dns.immutable.immutable -class IPv4HintParam(Param): - def __init__(self, addresses): - self.addresses = dns.rdata.Rdata._as_tuple( - addresses, dns.rdata.Rdata._as_ipv4_address - ) - - @classmethod - def from_value(cls, value): - addresses = value.split(",") - return cls(addresses) - - def to_text(self): - return '"' + ",".join(self.addresses) + '"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - addresses = [] - while parser.remaining() > 0: - ip = parser.get_bytes(4) - addresses.append(dns.ipv4.inet_ntoa(ip)) - return cls(addresses) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - for address in self.addresses: - file.write(dns.ipv4.inet_aton(address)) - - -@dns.immutable.immutable -class IPv6HintParam(Param): - def __init__(self, addresses): - self.addresses = dns.rdata.Rdata._as_tuple( - addresses, dns.rdata.Rdata._as_ipv6_address - ) - - @classmethod - def from_value(cls, value): - addresses = value.split(",") - return cls(addresses) - - def to_text(self): - return '"' + ",".join(self.addresses) + '"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - addresses = [] - while parser.remaining() > 0: - ip = parser.get_bytes(16) - addresses.append(dns.ipv6.inet_ntoa(ip)) - return cls(addresses) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - for address in self.addresses: - file.write(dns.ipv6.inet_aton(address)) - - -@dns.immutable.immutable -class ECHParam(Param): - def __init__(self, ech): - self.ech = dns.rdata.Rdata._as_bytes(ech, True) - - @classmethod - def from_value(cls, value): - if "\\" in value: - raise ValueError("escape in ECH value") - value = base64.b64decode(value.encode()) - return cls(value) - - def to_text(self): - b64 = base64.b64encode(self.ech).decode("ascii") - return f'"{b64}"' - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - value = parser.get_bytes(parser.remaining()) - return cls(value) - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - file.write(self.ech) - - -@dns.immutable.immutable -class OHTTPParam(Param): - # We don't ever expect to instantiate this class, but we need - # a from_value() and a from_wire_parser(), so we just return None - # from the class methods when things are OK. - - @classmethod - def emptiness(cls): - return Emptiness.ALWAYS - - @classmethod - def from_value(cls, value): - if value is None or value == "": - return None - else: - raise ValueError("ohttp with non-empty value") - - def to_text(self): - raise NotImplementedError # pragma: no cover - - @classmethod - def from_wire_parser(cls, parser, origin=None): # pylint: disable=W0613 - if parser.remaining() != 0: - raise dns.exception.FormError - return None - - def to_wire(self, file, origin=None): # pylint: disable=W0613 - raise NotImplementedError # pragma: no cover - - -_class_for_key = { - ParamKey.MANDATORY: MandatoryParam, - ParamKey.ALPN: ALPNParam, - ParamKey.NO_DEFAULT_ALPN: NoDefaultALPNParam, - ParamKey.PORT: PortParam, - ParamKey.IPV4HINT: IPv4HintParam, - ParamKey.ECH: ECHParam, - ParamKey.IPV6HINT: IPv6HintParam, - ParamKey.OHTTP: OHTTPParam, -} - - -def _validate_and_define(params, key, value): - (key, force_generic) = _validate_key(_unescape(key)) - if key in params: - raise SyntaxError(f'duplicate key "{key:d}"') - cls = _class_for_key.get(key, GenericParam) - emptiness = cls.emptiness() - if value is None: - if emptiness == Emptiness.NEVER: - raise SyntaxError("value cannot be empty") - value = cls.from_value(value) - else: - if force_generic: - value = cls.from_wire_parser(dns.wire.Parser(_unescape(value))) - else: - value = cls.from_value(value) - params[key] = value - - -@dns.immutable.immutable -class SVCBBase(dns.rdata.Rdata): - """Base class for SVCB-like records""" - - # see: draft-ietf-dnsop-svcb-https-11 - - __slots__ = ["priority", "target", "params"] - - def __init__(self, rdclass, rdtype, priority, target, params): - super().__init__(rdclass, rdtype) - self.priority = self._as_uint16(priority) - self.target = self._as_name(target) - for k, v in params.items(): - k = ParamKey.make(k) - if not isinstance(v, Param) and v is not None: - raise ValueError(f"{k:d} not a Param") - self.params = dns.immutable.Dict(params) - # Make sure any parameter listed as mandatory is present in the - # record. - mandatory = params.get(ParamKey.MANDATORY) - if mandatory: - for key in mandatory.keys: - # Note we have to say "not in" as we have None as a value - # so a get() and a not None test would be wrong. - if key not in params: - raise ValueError(f"key {key:d} declared mandatory but not present") - # The no-default-alpn parameter requires the alpn parameter. - if ParamKey.NO_DEFAULT_ALPN in params: - if ParamKey.ALPN not in params: - raise ValueError("no-default-alpn present, but alpn missing") - - def to_text(self, origin=None, relativize=True, **kw): - target = self.target.choose_relativity(origin, relativize) - params = [] - for key in sorted(self.params.keys()): - value = self.params[key] - if value is None: - params.append(key_to_text(key)) - else: - kv = key_to_text(key) + "=" + value.to_text() - params.append(kv) - if len(params) > 0: - space = " " - else: - space = "" - return "%d %s%s%s" % (self.priority, target, space, " ".join(params)) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - priority = tok.get_uint16() - target = tok.get_name(origin, relativize, relativize_to) - if priority == 0: - token = tok.get() - if not token.is_eol_or_eof(): - raise SyntaxError("parameters in AliasMode") - tok.unget(token) - params = {} - while True: - token = tok.get() - if token.is_eol_or_eof(): - tok.unget(token) - break - if token.ttype != dns.tokenizer.IDENTIFIER: - raise SyntaxError("parameter is not an identifier") - equals = token.value.find("=") - if equals == len(token.value) - 1: - # 'key=', so next token should be a quoted string without - # any intervening whitespace. - key = token.value[:-1] - token = tok.get(want_leading=True) - if token.ttype != dns.tokenizer.QUOTED_STRING: - raise SyntaxError("whitespace after =") - value = token.value - elif equals > 0: - # key=value - key = token.value[:equals] - value = token.value[equals + 1 :] - elif equals == 0: - # =key - raise SyntaxError('parameter cannot start with "="') - else: - # key - key = token.value - value = None - _validate_and_define(params, key, value) - return cls(rdclass, rdtype, priority, target, params) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - file.write(struct.pack("!H", self.priority)) - self.target.to_wire(file, None, origin, False) - for key in sorted(self.params): - file.write(struct.pack("!H", key)) - value = self.params[key] - with dns.renderer.prefixed_length(file, 2): - # Note that we're still writing a length of zero if the value is None - if value is not None: - value.to_wire(file, origin) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - priority = parser.get_uint16() - target = parser.get_name(origin) - if priority == 0 and parser.remaining() != 0: - raise dns.exception.FormError("parameters in AliasMode") - params = {} - prior_key = -1 - while parser.remaining() > 0: - key = parser.get_uint16() - if key < prior_key: - raise dns.exception.FormError("keys not in order") - prior_key = key - vlen = parser.get_uint16() - pcls = _class_for_key.get(key, GenericParam) - with parser.restrict_to(vlen): - value = pcls.from_wire_parser(parser, origin) - params[key] = value - return cls(rdclass, rdtype, priority, target, params) - - def _processing_priority(self): - return self.priority - - @classmethod - def _processing_order(cls, iterable): - return dns.rdtypes.util.priority_processing_order(iterable) diff --git a/venv/Lib/site-packages/dns/rdtypes/tlsabase.py b/venv/Lib/site-packages/dns/rdtypes/tlsabase.py deleted file mode 100644 index a059d2c..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/tlsabase.py +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2005-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import binascii -import struct - -import dns.immutable -import dns.rdata -import dns.rdatatype - - -@dns.immutable.immutable -class TLSABase(dns.rdata.Rdata): - """Base class for TLSA and SMIMEA records""" - - # see: RFC 6698 - - __slots__ = ["usage", "selector", "mtype", "cert"] - - def __init__(self, rdclass, rdtype, usage, selector, mtype, cert): - super().__init__(rdclass, rdtype) - self.usage = self._as_uint8(usage) - self.selector = self._as_uint8(selector) - self.mtype = self._as_uint8(mtype) - self.cert = self._as_bytes(cert) - - def to_text(self, origin=None, relativize=True, **kw): - kw = kw.copy() - chunksize = kw.pop("chunksize", 128) - return "%d %d %d %s" % ( - self.usage, - self.selector, - self.mtype, - dns.rdata._hexify(self.cert, chunksize=chunksize, **kw), - ) - - @classmethod - def from_text( - cls, rdclass, rdtype, tok, origin=None, relativize=True, relativize_to=None - ): - usage = tok.get_uint8() - selector = tok.get_uint8() - mtype = tok.get_uint8() - cert = tok.concatenate_remaining_identifiers().encode() - cert = binascii.unhexlify(cert) - return cls(rdclass, rdtype, usage, selector, mtype, cert) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - header = struct.pack("!BBB", self.usage, self.selector, self.mtype) - file.write(header) - file.write(self.cert) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - header = parser.get_struct("BBB") - cert = parser.get_remaining() - return cls(rdclass, rdtype, header[0], header[1], header[2], cert) diff --git a/venv/Lib/site-packages/dns/rdtypes/txtbase.py b/venv/Lib/site-packages/dns/rdtypes/txtbase.py deleted file mode 100644 index 73db6d9..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/txtbase.py +++ /dev/null @@ -1,106 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""TXT-like base class.""" - -from typing import Any, Dict, Iterable, Optional, Tuple, Union - -import dns.exception -import dns.immutable -import dns.rdata -import dns.renderer -import dns.tokenizer - - -@dns.immutable.immutable -class TXTBase(dns.rdata.Rdata): - """Base class for rdata that is like a TXT record (see RFC 1035).""" - - __slots__ = ["strings"] - - def __init__( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - strings: Iterable[Union[bytes, str]], - ): - """Initialize a TXT-like rdata. - - *rdclass*, an ``int`` is the rdataclass of the Rdata. - - *rdtype*, an ``int`` is the rdatatype of the Rdata. - - *strings*, a tuple of ``bytes`` - """ - super().__init__(rdclass, rdtype) - self.strings: Tuple[bytes] = self._as_tuple( - strings, lambda x: self._as_bytes(x, True, 255) - ) - if len(self.strings) == 0: - raise ValueError("the list of strings must not be empty") - - def to_text( - self, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - **kw: Dict[str, Any], - ) -> str: - txt = "" - prefix = "" - for s in self.strings: - txt += f'{prefix}"{dns.rdata._escapify(s)}"' - prefix = " " - return txt - - @classmethod - def from_text( - cls, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - tok: dns.tokenizer.Tokenizer, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - relativize_to: Optional[dns.name.Name] = None, - ) -> dns.rdata.Rdata: - strings = [] - for token in tok.get_remaining(): - token = token.unescape_to_bytes() - # The 'if' below is always true in the current code, but we - # are leaving this check in in case things change some day. - if not ( - token.is_quoted_string() or token.is_identifier() - ): # pragma: no cover - raise dns.exception.SyntaxError("expected a string") - if len(token.value) > 255: - raise dns.exception.SyntaxError("string too long") - strings.append(token.value) - if len(strings) == 0: - raise dns.exception.UnexpectedEnd - return cls(rdclass, rdtype, strings) - - def _to_wire(self, file, compress=None, origin=None, canonicalize=False): - for s in self.strings: - with dns.renderer.prefixed_length(file, 1): - file.write(s) - - @classmethod - def from_wire_parser(cls, rdclass, rdtype, parser, origin=None): - strings = [] - while parser.remaining() > 0: - s = parser.get_counted_bytes() - strings.append(s) - return cls(rdclass, rdtype, strings) diff --git a/venv/Lib/site-packages/dns/rdtypes/util.py b/venv/Lib/site-packages/dns/rdtypes/util.py deleted file mode 100644 index 653a0bf..0000000 --- a/venv/Lib/site-packages/dns/rdtypes/util.py +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006, 2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import collections -import random -import struct -from typing import Any, List - -import dns.exception -import dns.ipv4 -import dns.ipv6 -import dns.name -import dns.rdata - - -class Gateway: - """A helper class for the IPSECKEY gateway and AMTRELAY relay fields""" - - name = "" - - def __init__(self, type, gateway=None): - self.type = dns.rdata.Rdata._as_uint8(type) - self.gateway = gateway - self._check() - - @classmethod - def _invalid_type(cls, gateway_type): - return f"invalid {cls.name} type: {gateway_type}" - - def _check(self): - if self.type == 0: - if self.gateway not in (".", None): - raise SyntaxError(f"invalid {self.name} for type 0") - self.gateway = None - elif self.type == 1: - # check that it's OK - dns.ipv4.inet_aton(self.gateway) - elif self.type == 2: - # check that it's OK - dns.ipv6.inet_aton(self.gateway) - elif self.type == 3: - if not isinstance(self.gateway, dns.name.Name): - raise SyntaxError(f"invalid {self.name}; not a name") - else: - raise SyntaxError(self._invalid_type(self.type)) - - def to_text(self, origin=None, relativize=True): - if self.type == 0: - return "." - elif self.type in (1, 2): - return self.gateway - elif self.type == 3: - return str(self.gateway.choose_relativity(origin, relativize)) - else: - raise ValueError(self._invalid_type(self.type)) # pragma: no cover - - @classmethod - def from_text( - cls, gateway_type, tok, origin=None, relativize=True, relativize_to=None - ): - if gateway_type in (0, 1, 2): - gateway = tok.get_string() - elif gateway_type == 3: - gateway = tok.get_name(origin, relativize, relativize_to) - else: - raise dns.exception.SyntaxError( - cls._invalid_type(gateway_type) - ) # pragma: no cover - return cls(gateway_type, gateway) - - # pylint: disable=unused-argument - def to_wire(self, file, compress=None, origin=None, canonicalize=False): - if self.type == 0: - pass - elif self.type == 1: - file.write(dns.ipv4.inet_aton(self.gateway)) - elif self.type == 2: - file.write(dns.ipv6.inet_aton(self.gateway)) - elif self.type == 3: - self.gateway.to_wire(file, None, origin, False) - else: - raise ValueError(self._invalid_type(self.type)) # pragma: no cover - - # pylint: enable=unused-argument - - @classmethod - def from_wire_parser(cls, gateway_type, parser, origin=None): - if gateway_type == 0: - gateway = None - elif gateway_type == 1: - gateway = dns.ipv4.inet_ntoa(parser.get_bytes(4)) - elif gateway_type == 2: - gateway = dns.ipv6.inet_ntoa(parser.get_bytes(16)) - elif gateway_type == 3: - gateway = parser.get_name(origin) - else: - raise dns.exception.FormError(cls._invalid_type(gateway_type)) - return cls(gateway_type, gateway) - - -class Bitmap: - """A helper class for the NSEC/NSEC3/CSYNC type bitmaps""" - - type_name = "" - - def __init__(self, windows=None): - last_window = -1 - self.windows = windows - for window, bitmap in self.windows: - if not isinstance(window, int): - raise ValueError(f"bad {self.type_name} window type") - if window <= last_window: - raise ValueError(f"bad {self.type_name} window order") - if window > 256: - raise ValueError(f"bad {self.type_name} window number") - last_window = window - if not isinstance(bitmap, bytes): - raise ValueError(f"bad {self.type_name} octets type") - if len(bitmap) == 0 or len(bitmap) > 32: - raise ValueError(f"bad {self.type_name} octets") - - def to_text(self) -> str: - text = "" - for window, bitmap in self.windows: - bits = [] - for i, byte in enumerate(bitmap): - for j in range(0, 8): - if byte & (0x80 >> j): - rdtype = window * 256 + i * 8 + j - bits.append(dns.rdatatype.to_text(rdtype)) - text += " " + " ".join(bits) - return text - - @classmethod - def from_text(cls, tok: "dns.tokenizer.Tokenizer") -> "Bitmap": - rdtypes = [] - for token in tok.get_remaining(): - rdtype = dns.rdatatype.from_text(token.unescape().value) - if rdtype == 0: - raise dns.exception.SyntaxError(f"{cls.type_name} with bit 0") - rdtypes.append(rdtype) - return cls.from_rdtypes(rdtypes) - - @classmethod - def from_rdtypes(cls, rdtypes: List[dns.rdatatype.RdataType]) -> "Bitmap": - rdtypes = sorted(rdtypes) - window = 0 - octets = 0 - prior_rdtype = 0 - bitmap = bytearray(b"\0" * 32) - windows = [] - for rdtype in rdtypes: - if rdtype == prior_rdtype: - continue - prior_rdtype = rdtype - new_window = rdtype // 256 - if new_window != window: - if octets != 0: - windows.append((window, bytes(bitmap[0:octets]))) - bitmap = bytearray(b"\0" * 32) - window = new_window - offset = rdtype % 256 - byte = offset // 8 - bit = offset % 8 - octets = byte + 1 - bitmap[byte] = bitmap[byte] | (0x80 >> bit) - if octets != 0: - windows.append((window, bytes(bitmap[0:octets]))) - return cls(windows) - - def to_wire(self, file: Any) -> None: - for window, bitmap in self.windows: - file.write(struct.pack("!BB", window, len(bitmap))) - file.write(bitmap) - - @classmethod - def from_wire_parser(cls, parser: "dns.wire.Parser") -> "Bitmap": - windows = [] - while parser.remaining() > 0: - window = parser.get_uint8() - bitmap = parser.get_counted_bytes() - windows.append((window, bitmap)) - return cls(windows) - - -def _priority_table(items): - by_priority = collections.defaultdict(list) - for rdata in items: - by_priority[rdata._processing_priority()].append(rdata) - return by_priority - - -def priority_processing_order(iterable): - items = list(iterable) - if len(items) == 1: - return items - by_priority = _priority_table(items) - ordered = [] - for k in sorted(by_priority.keys()): - rdatas = by_priority[k] - random.shuffle(rdatas) - ordered.extend(rdatas) - return ordered - - -_no_weight = 0.1 - - -def weighted_processing_order(iterable): - items = list(iterable) - if len(items) == 1: - return items - by_priority = _priority_table(items) - ordered = [] - for k in sorted(by_priority.keys()): - rdatas = by_priority[k] - total = sum(rdata._processing_weight() or _no_weight for rdata in rdatas) - while len(rdatas) > 1: - r = random.uniform(0, total) - for n, rdata in enumerate(rdatas): # noqa: B007 - weight = rdata._processing_weight() or _no_weight - if weight > r: - break - r -= weight - total -= weight - ordered.append(rdata) # pylint: disable=undefined-loop-variable - del rdatas[n] # pylint: disable=undefined-loop-variable - ordered.append(rdatas[0]) - return ordered - - -def parse_formatted_hex(formatted, num_chunks, chunk_size, separator): - if len(formatted) != num_chunks * (chunk_size + 1) - 1: - raise ValueError("invalid formatted hex string") - value = b"" - for _ in range(num_chunks): - chunk = formatted[0:chunk_size] - value += int(chunk, 16).to_bytes(chunk_size // 2, "big") - formatted = formatted[chunk_size:] - if len(formatted) > 0 and formatted[0] != separator: - raise ValueError("invalid formatted hex string") - formatted = formatted[1:] - return value diff --git a/venv/Lib/site-packages/dns/renderer.py b/venv/Lib/site-packages/dns/renderer.py deleted file mode 100644 index a77481f..0000000 --- a/venv/Lib/site-packages/dns/renderer.py +++ /dev/null @@ -1,346 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Help for building DNS wire format messages""" - -import contextlib -import io -import random -import struct -import time - -import dns.exception -import dns.tsig - -QUESTION = 0 -ANSWER = 1 -AUTHORITY = 2 -ADDITIONAL = 3 - - -@contextlib.contextmanager -def prefixed_length(output, length_length): - output.write(b"\00" * length_length) - start = output.tell() - yield - end = output.tell() - length = end - start - if length > 0: - try: - output.seek(start - length_length) - try: - output.write(length.to_bytes(length_length, "big")) - except OverflowError: - raise dns.exception.FormError - finally: - output.seek(end) - - -class Renderer: - """Helper class for building DNS wire-format messages. - - Most applications can use the higher-level L{dns.message.Message} - class and its to_wire() method to generate wire-format messages. - This class is for those applications which need finer control - over the generation of messages. - - Typical use:: - - r = dns.renderer.Renderer(id=1, flags=0x80, max_size=512) - r.add_question(qname, qtype, qclass) - r.add_rrset(dns.renderer.ANSWER, rrset_1) - r.add_rrset(dns.renderer.ANSWER, rrset_2) - r.add_rrset(dns.renderer.AUTHORITY, ns_rrset) - r.add_rrset(dns.renderer.ADDITIONAL, ad_rrset_1) - r.add_rrset(dns.renderer.ADDITIONAL, ad_rrset_2) - r.add_edns(0, 0, 4096) - r.write_header() - r.add_tsig(keyname, secret, 300, 1, 0, '', request_mac) - wire = r.get_wire() - - If padding is going to be used, then the OPT record MUST be - written after everything else in the additional section except for - the TSIG (if any). - - output, an io.BytesIO, where rendering is written - - id: the message id - - flags: the message flags - - max_size: the maximum size of the message - - origin: the origin to use when rendering relative names - - compress: the compression table - - section: an int, the section currently being rendered - - counts: list of the number of RRs in each section - - mac: the MAC of the rendered message (if TSIG was used) - """ - - def __init__(self, id=None, flags=0, max_size=65535, origin=None): - """Initialize a new renderer.""" - - self.output = io.BytesIO() - if id is None: - self.id = random.randint(0, 65535) - else: - self.id = id - self.flags = flags - self.max_size = max_size - self.origin = origin - self.compress = {} - self.section = QUESTION - self.counts = [0, 0, 0, 0] - self.output.write(b"\x00" * 12) - self.mac = "" - self.reserved = 0 - self.was_padded = False - - def _rollback(self, where): - """Truncate the output buffer at offset *where*, and remove any - compression table entries that pointed beyond the truncation - point. - """ - - self.output.seek(where) - self.output.truncate() - keys_to_delete = [] - for k, v in self.compress.items(): - if v >= where: - keys_to_delete.append(k) - for k in keys_to_delete: - del self.compress[k] - - def _set_section(self, section): - """Set the renderer's current section. - - Sections must be rendered order: QUESTION, ANSWER, AUTHORITY, - ADDITIONAL. Sections may be empty. - - Raises dns.exception.FormError if an attempt was made to set - a section value less than the current section. - """ - - if self.section != section: - if self.section > section: - raise dns.exception.FormError - self.section = section - - @contextlib.contextmanager - def _track_size(self): - start = self.output.tell() - yield start - if self.output.tell() > self.max_size: - self._rollback(start) - raise dns.exception.TooBig - - @contextlib.contextmanager - def _temporarily_seek_to(self, where): - current = self.output.tell() - try: - self.output.seek(where) - yield - finally: - self.output.seek(current) - - def add_question(self, qname, rdtype, rdclass=dns.rdataclass.IN): - """Add a question to the message.""" - - self._set_section(QUESTION) - with self._track_size(): - qname.to_wire(self.output, self.compress, self.origin) - self.output.write(struct.pack("!HH", rdtype, rdclass)) - self.counts[QUESTION] += 1 - - def add_rrset(self, section, rrset, **kw): - """Add the rrset to the specified section. - - Any keyword arguments are passed on to the rdataset's to_wire() - routine. - """ - - self._set_section(section) - with self._track_size(): - n = rrset.to_wire(self.output, self.compress, self.origin, **kw) - self.counts[section] += n - - def add_rdataset(self, section, name, rdataset, **kw): - """Add the rdataset to the specified section, using the specified - name as the owner name. - - Any keyword arguments are passed on to the rdataset's to_wire() - routine. - """ - - self._set_section(section) - with self._track_size(): - n = rdataset.to_wire(name, self.output, self.compress, self.origin, **kw) - self.counts[section] += n - - def add_opt(self, opt, pad=0, opt_size=0, tsig_size=0): - """Add *opt* to the additional section, applying padding if desired. The - padding will take the specified precomputed OPT size and TSIG size into - account. - - Note that we don't have reliable way of knowing how big a GSS-TSIG digest - might be, so we we might not get an even multiple of the pad in that case.""" - if pad: - ttl = opt.ttl - assert opt_size >= 11 - opt_rdata = opt[0] - size_without_padding = self.output.tell() + opt_size + tsig_size - remainder = size_without_padding % pad - if remainder: - pad = b"\x00" * (pad - remainder) - else: - pad = b"" - options = list(opt_rdata.options) - options.append(dns.edns.GenericOption(dns.edns.OptionType.PADDING, pad)) - opt = dns.message.Message._make_opt(ttl, opt_rdata.rdclass, options) - self.was_padded = True - self.add_rrset(ADDITIONAL, opt) - - def add_edns(self, edns, ednsflags, payload, options=None): - """Add an EDNS OPT record to the message.""" - - # make sure the EDNS version in ednsflags agrees with edns - ednsflags &= 0xFF00FFFF - ednsflags |= edns << 16 - opt = dns.message.Message._make_opt(ednsflags, payload, options) - self.add_opt(opt) - - def add_tsig( - self, - keyname, - secret, - fudge, - id, - tsig_error, - other_data, - request_mac, - algorithm=dns.tsig.default_algorithm, - ): - """Add a TSIG signature to the message.""" - - s = self.output.getvalue() - - if isinstance(secret, dns.tsig.Key): - key = secret - else: - key = dns.tsig.Key(keyname, secret, algorithm) - tsig = dns.message.Message._make_tsig( - keyname, algorithm, 0, fudge, b"", id, tsig_error, other_data - ) - (tsig, _) = dns.tsig.sign(s, key, tsig[0], int(time.time()), request_mac) - self._write_tsig(tsig, keyname) - - def add_multi_tsig( - self, - ctx, - keyname, - secret, - fudge, - id, - tsig_error, - other_data, - request_mac, - algorithm=dns.tsig.default_algorithm, - ): - """Add a TSIG signature to the message. Unlike add_tsig(), this can be - used for a series of consecutive DNS envelopes, e.g. for a zone - transfer over TCP [RFC2845, 4.4]. - - For the first message in the sequence, give ctx=None. For each - subsequent message, give the ctx that was returned from the - add_multi_tsig() call for the previous message.""" - - s = self.output.getvalue() - - if isinstance(secret, dns.tsig.Key): - key = secret - else: - key = dns.tsig.Key(keyname, secret, algorithm) - tsig = dns.message.Message._make_tsig( - keyname, algorithm, 0, fudge, b"", id, tsig_error, other_data - ) - (tsig, ctx) = dns.tsig.sign( - s, key, tsig[0], int(time.time()), request_mac, ctx, True - ) - self._write_tsig(tsig, keyname) - return ctx - - def _write_tsig(self, tsig, keyname): - if self.was_padded: - compress = None - else: - compress = self.compress - self._set_section(ADDITIONAL) - with self._track_size(): - keyname.to_wire(self.output, compress, self.origin) - self.output.write( - struct.pack("!HHI", dns.rdatatype.TSIG, dns.rdataclass.ANY, 0) - ) - with prefixed_length(self.output, 2): - tsig.to_wire(self.output) - - self.counts[ADDITIONAL] += 1 - with self._temporarily_seek_to(10): - self.output.write(struct.pack("!H", self.counts[ADDITIONAL])) - - def write_header(self): - """Write the DNS message header. - - Writing the DNS message header is done after all sections - have been rendered, but before the optional TSIG signature - is added. - """ - - with self._temporarily_seek_to(0): - self.output.write( - struct.pack( - "!HHHHHH", - self.id, - self.flags, - self.counts[0], - self.counts[1], - self.counts[2], - self.counts[3], - ) - ) - - def get_wire(self): - """Return the wire format message.""" - - return self.output.getvalue() - - def reserve(self, size: int) -> None: - """Reserve *size* bytes.""" - if size < 0: - raise ValueError("reserved amount must be non-negative") - if size > self.max_size: - raise ValueError("cannot reserve more than the maximum size") - self.reserved += size - self.max_size -= size - - def release_reserved(self) -> None: - """Release the reserved bytes.""" - self.max_size += self.reserved - self.reserved = 0 diff --git a/venv/Lib/site-packages/dns/resolver.py b/venv/Lib/site-packages/dns/resolver.py deleted file mode 100644 index 3ba76e3..0000000 --- a/venv/Lib/site-packages/dns/resolver.py +++ /dev/null @@ -1,2053 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS stub resolver.""" - -import contextlib -import random -import socket -import sys -import threading -import time -import warnings -from typing import Any, Dict, Iterator, List, Optional, Sequence, Tuple, Union -from urllib.parse import urlparse - -import dns._ddr -import dns.edns -import dns.exception -import dns.flags -import dns.inet -import dns.ipv4 -import dns.ipv6 -import dns.message -import dns.name -import dns.rdata -import dns.nameserver -import dns.query -import dns.rcode -import dns.rdataclass -import dns.rdatatype -import dns.rdtypes.svcbbase -import dns.reversename -import dns.tsig - -if sys.platform == "win32": # pragma: no cover - import dns.win32util - - -class NXDOMAIN(dns.exception.DNSException): - """The DNS query name does not exist.""" - - supp_kwargs = {"qnames", "responses"} - fmt = None # we have our own __str__ implementation - - # pylint: disable=arguments-differ - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - def _check_kwargs(self, qnames, responses=None): - if not isinstance(qnames, (list, tuple, set)): - raise AttributeError("qnames must be a list, tuple or set") - if len(qnames) == 0: - raise AttributeError("qnames must contain at least one element") - if responses is None: - responses = {} - elif not isinstance(responses, dict): - raise AttributeError("responses must be a dict(qname=response)") - kwargs = dict(qnames=qnames, responses=responses) - return kwargs - - def __str__(self) -> str: - if "qnames" not in self.kwargs: - return super().__str__() - qnames = self.kwargs["qnames"] - if len(qnames) > 1: - msg = "None of DNS query names exist" - else: - msg = "The DNS query name does not exist" - qnames = ", ".join(map(str, qnames)) - return f"{msg}: {qnames}" - - @property - def canonical_name(self): - """Return the unresolved canonical name.""" - if "qnames" not in self.kwargs: - raise TypeError("parametrized exception required") - for qname in self.kwargs["qnames"]: - response = self.kwargs["responses"][qname] - try: - cname = response.canonical_name() - if cname != qname: - return cname - except Exception: # pragma: no cover - # We can just eat this exception as it means there was - # something wrong with the response. - pass - return self.kwargs["qnames"][0] - - def __add__(self, e_nx): - """Augment by results from another NXDOMAIN exception.""" - qnames0 = list(self.kwargs.get("qnames", [])) - responses0 = dict(self.kwargs.get("responses", {})) - responses1 = e_nx.kwargs.get("responses", {}) - for qname1 in e_nx.kwargs.get("qnames", []): - if qname1 not in qnames0: - qnames0.append(qname1) - if qname1 in responses1: - responses0[qname1] = responses1[qname1] - return NXDOMAIN(qnames=qnames0, responses=responses0) - - def qnames(self): - """All of the names that were tried. - - Returns a list of ``dns.name.Name``. - """ - return self.kwargs["qnames"] - - def responses(self): - """A map from queried names to their NXDOMAIN responses. - - Returns a dict mapping a ``dns.name.Name`` to a - ``dns.message.Message``. - """ - return self.kwargs["responses"] - - def response(self, qname): - """The response for query *qname*. - - Returns a ``dns.message.Message``. - """ - return self.kwargs["responses"][qname] - - -class YXDOMAIN(dns.exception.DNSException): - """The DNS query name is too long after DNAME substitution.""" - - -ErrorTuple = Tuple[ - Optional[str], - bool, - int, - Union[Exception, str], - Optional[dns.message.Message], -] - - -def _errors_to_text(errors: List[ErrorTuple]) -> List[str]: - """Turn a resolution errors trace into a list of text.""" - texts = [] - for err in errors: - texts.append(f"Server {err[0]} answered {err[3]}") - return texts - - -class LifetimeTimeout(dns.exception.Timeout): - """The resolution lifetime expired.""" - - msg = "The resolution lifetime expired." - fmt = f"{msg[:-1]} after {{timeout:.3f}} seconds: {{errors}}" - supp_kwargs = {"timeout", "errors"} - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - def _fmt_kwargs(self, **kwargs): - srv_msgs = _errors_to_text(kwargs["errors"]) - return super()._fmt_kwargs( - timeout=kwargs["timeout"], errors="; ".join(srv_msgs) - ) - - -# We added more detail to resolution timeouts, but they are still -# subclasses of dns.exception.Timeout for backwards compatibility. We also -# keep dns.resolver.Timeout defined for backwards compatibility. -Timeout = LifetimeTimeout - - -class NoAnswer(dns.exception.DNSException): - """The DNS response does not contain an answer to the question.""" - - fmt = "The DNS response does not contain an answer to the question: {query}" - supp_kwargs = {"response"} - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - def _fmt_kwargs(self, **kwargs): - return super()._fmt_kwargs(query=kwargs["response"].question) - - def response(self): - return self.kwargs["response"] - - -class NoNameservers(dns.exception.DNSException): - """All nameservers failed to answer the query. - - errors: list of servers and respective errors - The type of errors is - [(server IP address, any object convertible to string)]. - Non-empty errors list will add explanatory message () - """ - - msg = "All nameservers failed to answer the query." - fmt = f"{msg[:-1]} {{query}}: {{errors}}" - supp_kwargs = {"request", "errors"} - - # We do this as otherwise mypy complains about unexpected keyword argument - # idna_exception - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - def _fmt_kwargs(self, **kwargs): - srv_msgs = _errors_to_text(kwargs["errors"]) - return super()._fmt_kwargs( - query=kwargs["request"].question, errors="; ".join(srv_msgs) - ) - - -class NotAbsolute(dns.exception.DNSException): - """An absolute domain name is required but a relative name was provided.""" - - -class NoRootSOA(dns.exception.DNSException): - """There is no SOA RR at the DNS root name. This should never happen!""" - - -class NoMetaqueries(dns.exception.DNSException): - """DNS metaqueries are not allowed.""" - - -class NoResolverConfiguration(dns.exception.DNSException): - """Resolver configuration could not be read or specified no nameservers.""" - - -class Answer: - """DNS stub resolver answer. - - Instances of this class bundle up the result of a successful DNS - resolution. - - For convenience, the answer object implements much of the sequence - protocol, forwarding to its ``rrset`` attribute. E.g. - ``for a in answer`` is equivalent to ``for a in answer.rrset``. - ``answer[i]`` is equivalent to ``answer.rrset[i]``, and - ``answer[i:j]`` is equivalent to ``answer.rrset[i:j]``. - - Note that CNAMEs or DNAMEs in the response may mean that answer - RRset's name might not be the query name. - """ - - def __init__( - self, - qname: dns.name.Name, - rdtype: dns.rdatatype.RdataType, - rdclass: dns.rdataclass.RdataClass, - response: dns.message.QueryMessage, - nameserver: Optional[str] = None, - port: Optional[int] = None, - ) -> None: - self.qname = qname - self.rdtype = rdtype - self.rdclass = rdclass - self.response = response - self.nameserver = nameserver - self.port = port - self.chaining_result = response.resolve_chaining() - # Copy some attributes out of chaining_result for backwards - # compatibility and convenience. - self.canonical_name = self.chaining_result.canonical_name - self.rrset = self.chaining_result.answer - self.expiration = time.time() + self.chaining_result.minimum_ttl - - def __getattr__(self, attr): # pragma: no cover - if attr == "name": - return self.rrset.name - elif attr == "ttl": - return self.rrset.ttl - elif attr == "covers": - return self.rrset.covers - elif attr == "rdclass": - return self.rrset.rdclass - elif attr == "rdtype": - return self.rrset.rdtype - else: - raise AttributeError(attr) - - def __len__(self) -> int: - return self.rrset and len(self.rrset) or 0 - - def __iter__(self) -> Iterator[dns.rdata.Rdata]: - return self.rrset and iter(self.rrset) or iter(tuple()) - - def __getitem__(self, i): - if self.rrset is None: - raise IndexError - return self.rrset[i] - - def __delitem__(self, i): - if self.rrset is None: - raise IndexError - del self.rrset[i] - - -class Answers(dict): - """A dict of DNS stub resolver answers, indexed by type.""" - - -class HostAnswers(Answers): - """A dict of DNS stub resolver answers to a host name lookup, indexed by - type. - """ - - @classmethod - def make( - cls, - v6: Optional[Answer] = None, - v4: Optional[Answer] = None, - add_empty: bool = True, - ) -> "HostAnswers": - answers = HostAnswers() - if v6 is not None and (add_empty or v6.rrset): - answers[dns.rdatatype.AAAA] = v6 - if v4 is not None and (add_empty or v4.rrset): - answers[dns.rdatatype.A] = v4 - return answers - - # Returns pairs of (address, family) from this result, potentially - # filtering by address family. - def addresses_and_families( - self, family: int = socket.AF_UNSPEC - ) -> Iterator[Tuple[str, int]]: - if family == socket.AF_UNSPEC: - yield from self.addresses_and_families(socket.AF_INET6) - yield from self.addresses_and_families(socket.AF_INET) - return - elif family == socket.AF_INET6: - answer = self.get(dns.rdatatype.AAAA) - elif family == socket.AF_INET: - answer = self.get(dns.rdatatype.A) - else: # pragma: no cover - raise NotImplementedError(f"unknown address family {family}") - if answer: - for rdata in answer: - yield (rdata.address, family) - - # Returns addresses from this result, potentially filtering by - # address family. - def addresses(self, family: int = socket.AF_UNSPEC) -> Iterator[str]: - return (pair[0] for pair in self.addresses_and_families(family)) - - # Returns the canonical name from this result. - def canonical_name(self) -> dns.name.Name: - answer = self.get(dns.rdatatype.AAAA, self.get(dns.rdatatype.A)) - return answer.canonical_name - - -class CacheStatistics: - """Cache Statistics""" - - def __init__(self, hits: int = 0, misses: int = 0) -> None: - self.hits = hits - self.misses = misses - - def reset(self) -> None: - self.hits = 0 - self.misses = 0 - - def clone(self) -> "CacheStatistics": - return CacheStatistics(self.hits, self.misses) - - -class CacheBase: - def __init__(self) -> None: - self.lock = threading.Lock() - self.statistics = CacheStatistics() - - def reset_statistics(self) -> None: - """Reset all statistics to zero.""" - with self.lock: - self.statistics.reset() - - def hits(self) -> int: - """How many hits has the cache had?""" - with self.lock: - return self.statistics.hits - - def misses(self) -> int: - """How many misses has the cache had?""" - with self.lock: - return self.statistics.misses - - def get_statistics_snapshot(self) -> CacheStatistics: - """Return a consistent snapshot of all the statistics. - - If running with multiple threads, it's better to take a - snapshot than to call statistics methods such as hits() and - misses() individually. - """ - with self.lock: - return self.statistics.clone() - - -CacheKey = Tuple[dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass] - - -class Cache(CacheBase): - """Simple thread-safe DNS answer cache.""" - - def __init__(self, cleaning_interval: float = 300.0) -> None: - """*cleaning_interval*, a ``float`` is the number of seconds between - periodic cleanings. - """ - - super().__init__() - self.data: Dict[CacheKey, Answer] = {} - self.cleaning_interval = cleaning_interval - self.next_cleaning: float = time.time() + self.cleaning_interval - - def _maybe_clean(self) -> None: - """Clean the cache if it's time to do so.""" - - now = time.time() - if self.next_cleaning <= now: - keys_to_delete = [] - for k, v in self.data.items(): - if v.expiration <= now: - keys_to_delete.append(k) - for k in keys_to_delete: - del self.data[k] - now = time.time() - self.next_cleaning = now + self.cleaning_interval - - def get(self, key: CacheKey) -> Optional[Answer]: - """Get the answer associated with *key*. - - Returns None if no answer is cached for the key. - - *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` - tuple whose values are the query name, rdtype, and rdclass respectively. - - Returns a ``dns.resolver.Answer`` or ``None``. - """ - - with self.lock: - self._maybe_clean() - v = self.data.get(key) - if v is None or v.expiration <= time.time(): - self.statistics.misses += 1 - return None - self.statistics.hits += 1 - return v - - def put(self, key: CacheKey, value: Answer) -> None: - """Associate key and value in the cache. - - *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` - tuple whose values are the query name, rdtype, and rdclass respectively. - - *value*, a ``dns.resolver.Answer``, the answer. - """ - - with self.lock: - self._maybe_clean() - self.data[key] = value - - def flush(self, key: Optional[CacheKey] = None) -> None: - """Flush the cache. - - If *key* is not ``None``, only that item is flushed. Otherwise the entire cache - is flushed. - - *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` - tuple whose values are the query name, rdtype, and rdclass respectively. - """ - - with self.lock: - if key is not None: - if key in self.data: - del self.data[key] - else: - self.data = {} - self.next_cleaning = time.time() + self.cleaning_interval - - -class LRUCacheNode: - """LRUCache node.""" - - def __init__(self, key, value): - self.key = key - self.value = value - self.hits = 0 - self.prev = self - self.next = self - - def link_after(self, node: "LRUCacheNode") -> None: - self.prev = node - self.next = node.next - node.next.prev = self - node.next = self - - def unlink(self) -> None: - self.next.prev = self.prev - self.prev.next = self.next - - -class LRUCache(CacheBase): - """Thread-safe, bounded, least-recently-used DNS answer cache. - - This cache is better than the simple cache (above) if you're - running a web crawler or other process that does a lot of - resolutions. The LRUCache has a maximum number of nodes, and when - it is full, the least-recently used node is removed to make space - for a new one. - """ - - def __init__(self, max_size: int = 100000) -> None: - """*max_size*, an ``int``, is the maximum number of nodes to cache; - it must be greater than 0. - """ - - super().__init__() - self.data: Dict[CacheKey, LRUCacheNode] = {} - self.set_max_size(max_size) - self.sentinel: LRUCacheNode = LRUCacheNode(None, None) - self.sentinel.prev = self.sentinel - self.sentinel.next = self.sentinel - - def set_max_size(self, max_size: int) -> None: - if max_size < 1: - max_size = 1 - self.max_size = max_size - - def get(self, key: CacheKey) -> Optional[Answer]: - """Get the answer associated with *key*. - - Returns None if no answer is cached for the key. - - *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` - tuple whose values are the query name, rdtype, and rdclass respectively. - - Returns a ``dns.resolver.Answer`` or ``None``. - """ - - with self.lock: - node = self.data.get(key) - if node is None: - self.statistics.misses += 1 - return None - # Unlink because we're either going to move the node to the front - # of the LRU list or we're going to free it. - node.unlink() - if node.value.expiration <= time.time(): - del self.data[node.key] - self.statistics.misses += 1 - return None - node.link_after(self.sentinel) - self.statistics.hits += 1 - node.hits += 1 - return node.value - - def get_hits_for_key(self, key: CacheKey) -> int: - """Return the number of cache hits associated with the specified key.""" - with self.lock: - node = self.data.get(key) - if node is None or node.value.expiration <= time.time(): - return 0 - else: - return node.hits - - def put(self, key: CacheKey, value: Answer) -> None: - """Associate key and value in the cache. - - *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` - tuple whose values are the query name, rdtype, and rdclass respectively. - - *value*, a ``dns.resolver.Answer``, the answer. - """ - - with self.lock: - node = self.data.get(key) - if node is not None: - node.unlink() - del self.data[node.key] - while len(self.data) >= self.max_size: - gnode = self.sentinel.prev - gnode.unlink() - del self.data[gnode.key] - node = LRUCacheNode(key, value) - node.link_after(self.sentinel) - self.data[key] = node - - def flush(self, key: Optional[CacheKey] = None) -> None: - """Flush the cache. - - If *key* is not ``None``, only that item is flushed. Otherwise the entire cache - is flushed. - - *key*, a ``(dns.name.Name, dns.rdatatype.RdataType, dns.rdataclass.RdataClass)`` - tuple whose values are the query name, rdtype, and rdclass respectively. - """ - - with self.lock: - if key is not None: - node = self.data.get(key) - if node is not None: - node.unlink() - del self.data[node.key] - else: - gnode = self.sentinel.next - while gnode != self.sentinel: - next = gnode.next - gnode.unlink() - gnode = next - self.data = {} - - -class _Resolution: - """Helper class for dns.resolver.Resolver.resolve(). - - All of the "business logic" of resolution is encapsulated in this - class, allowing us to have multiple resolve() implementations - using different I/O schemes without copying all of the - complicated logic. - - This class is a "friend" to dns.resolver.Resolver and manipulates - resolver data structures directly. - """ - - def __init__( - self, - resolver: "BaseResolver", - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - rdclass: Union[dns.rdataclass.RdataClass, str], - tcp: bool, - raise_on_no_answer: bool, - search: Optional[bool], - ) -> None: - if isinstance(qname, str): - qname = dns.name.from_text(qname, None) - rdtype = dns.rdatatype.RdataType.make(rdtype) - if dns.rdatatype.is_metatype(rdtype): - raise NoMetaqueries - rdclass = dns.rdataclass.RdataClass.make(rdclass) - if dns.rdataclass.is_metaclass(rdclass): - raise NoMetaqueries - self.resolver = resolver - self.qnames_to_try = resolver._get_qnames_to_try(qname, search) - self.qnames = self.qnames_to_try[:] - self.rdtype = rdtype - self.rdclass = rdclass - self.tcp = tcp - self.raise_on_no_answer = raise_on_no_answer - self.nxdomain_responses: Dict[dns.name.Name, dns.message.QueryMessage] = {} - # Initialize other things to help analysis tools - self.qname = dns.name.empty - self.nameservers: List[dns.nameserver.Nameserver] = [] - self.current_nameservers: List[dns.nameserver.Nameserver] = [] - self.errors: List[ErrorTuple] = [] - self.nameserver: Optional[dns.nameserver.Nameserver] = None - self.tcp_attempt = False - self.retry_with_tcp = False - self.request: Optional[dns.message.QueryMessage] = None - self.backoff = 0.0 - - def next_request( - self, - ) -> Tuple[Optional[dns.message.QueryMessage], Optional[Answer]]: - """Get the next request to send, and check the cache. - - Returns a (request, answer) tuple. At most one of request or - answer will not be None. - """ - - # We return a tuple instead of Union[Message,Answer] as it lets - # the caller avoid isinstance(). - - while len(self.qnames) > 0: - self.qname = self.qnames.pop(0) - - # Do we know the answer? - if self.resolver.cache: - answer = self.resolver.cache.get( - (self.qname, self.rdtype, self.rdclass) - ) - if answer is not None: - if answer.rrset is None and self.raise_on_no_answer: - raise NoAnswer(response=answer.response) - else: - return (None, answer) - answer = self.resolver.cache.get( - (self.qname, dns.rdatatype.ANY, self.rdclass) - ) - if answer is not None and answer.response.rcode() == dns.rcode.NXDOMAIN: - # cached NXDOMAIN; record it and continue to next - # name. - self.nxdomain_responses[self.qname] = answer.response - continue - - # Build the request - request = dns.message.make_query(self.qname, self.rdtype, self.rdclass) - if self.resolver.keyname is not None: - request.use_tsig( - self.resolver.keyring, - self.resolver.keyname, - algorithm=self.resolver.keyalgorithm, - ) - request.use_edns( - self.resolver.edns, - self.resolver.ednsflags, - self.resolver.payload, - options=self.resolver.ednsoptions, - ) - if self.resolver.flags is not None: - request.flags = self.resolver.flags - - self.nameservers = self.resolver._enrich_nameservers( - self.resolver._nameservers, - self.resolver.nameserver_ports, - self.resolver.port, - ) - if self.resolver.rotate: - random.shuffle(self.nameservers) - self.current_nameservers = self.nameservers[:] - self.errors = [] - self.nameserver = None - self.tcp_attempt = False - self.retry_with_tcp = False - self.request = request - self.backoff = 0.10 - - return (request, None) - - # - # We've tried everything and only gotten NXDOMAINs. (We know - # it's only NXDOMAINs as anything else would have returned - # before now.) - # - raise NXDOMAIN(qnames=self.qnames_to_try, responses=self.nxdomain_responses) - - def next_nameserver(self) -> Tuple[dns.nameserver.Nameserver, bool, float]: - if self.retry_with_tcp: - assert self.nameserver is not None - assert not self.nameserver.is_always_max_size() - self.tcp_attempt = True - self.retry_with_tcp = False - return (self.nameserver, True, 0) - - backoff = 0.0 - if not self.current_nameservers: - if len(self.nameservers) == 0: - # Out of things to try! - raise NoNameservers(request=self.request, errors=self.errors) - self.current_nameservers = self.nameservers[:] - backoff = self.backoff - self.backoff = min(self.backoff * 2, 2) - - self.nameserver = self.current_nameservers.pop(0) - self.tcp_attempt = self.tcp or self.nameserver.is_always_max_size() - return (self.nameserver, self.tcp_attempt, backoff) - - def query_result( - self, response: Optional[dns.message.Message], ex: Optional[Exception] - ) -> Tuple[Optional[Answer], bool]: - # - # returns an (answer: Answer, end_loop: bool) tuple. - # - assert self.nameserver is not None - if ex: - # Exception during I/O or from_wire() - assert response is None - self.errors.append( - ( - str(self.nameserver), - self.tcp_attempt, - self.nameserver.answer_port(), - ex, - response, - ) - ) - if ( - isinstance(ex, dns.exception.FormError) - or isinstance(ex, EOFError) - or isinstance(ex, OSError) - or isinstance(ex, NotImplementedError) - ): - # This nameserver is no good, take it out of the mix. - self.nameservers.remove(self.nameserver) - elif isinstance(ex, dns.message.Truncated): - if self.tcp_attempt: - # Truncation with TCP is no good! - self.nameservers.remove(self.nameserver) - else: - self.retry_with_tcp = True - return (None, False) - # We got an answer! - assert response is not None - assert isinstance(response, dns.message.QueryMessage) - rcode = response.rcode() - if rcode == dns.rcode.NOERROR: - try: - answer = Answer( - self.qname, - self.rdtype, - self.rdclass, - response, - self.nameserver.answer_nameserver(), - self.nameserver.answer_port(), - ) - except Exception as e: - self.errors.append( - ( - str(self.nameserver), - self.tcp_attempt, - self.nameserver.answer_port(), - e, - response, - ) - ) - # The nameserver is no good, take it out of the mix. - self.nameservers.remove(self.nameserver) - return (None, False) - if self.resolver.cache: - self.resolver.cache.put((self.qname, self.rdtype, self.rdclass), answer) - if answer.rrset is None and self.raise_on_no_answer: - raise NoAnswer(response=answer.response) - return (answer, True) - elif rcode == dns.rcode.NXDOMAIN: - # Further validate the response by making an Answer, even - # if we aren't going to cache it. - try: - answer = Answer( - self.qname, dns.rdatatype.ANY, dns.rdataclass.IN, response - ) - except Exception as e: - self.errors.append( - ( - str(self.nameserver), - self.tcp_attempt, - self.nameserver.answer_port(), - e, - response, - ) - ) - # The nameserver is no good, take it out of the mix. - self.nameservers.remove(self.nameserver) - return (None, False) - self.nxdomain_responses[self.qname] = response - if self.resolver.cache: - self.resolver.cache.put( - (self.qname, dns.rdatatype.ANY, self.rdclass), answer - ) - # Make next_nameserver() return None, so caller breaks its - # inner loop and calls next_request(). - return (None, True) - elif rcode == dns.rcode.YXDOMAIN: - yex = YXDOMAIN() - self.errors.append( - ( - str(self.nameserver), - self.tcp_attempt, - self.nameserver.answer_port(), - yex, - response, - ) - ) - raise yex - else: - # - # We got a response, but we're not happy with the - # rcode in it. - # - if rcode != dns.rcode.SERVFAIL or not self.resolver.retry_servfail: - self.nameservers.remove(self.nameserver) - self.errors.append( - ( - str(self.nameserver), - self.tcp_attempt, - self.nameserver.answer_port(), - dns.rcode.to_text(rcode), - response, - ) - ) - return (None, False) - - -class BaseResolver: - """DNS stub resolver.""" - - # We initialize in reset() - # - # pylint: disable=attribute-defined-outside-init - - domain: dns.name.Name - nameserver_ports: Dict[str, int] - port: int - search: List[dns.name.Name] - use_search_by_default: bool - timeout: float - lifetime: float - keyring: Optional[Any] - keyname: Optional[Union[dns.name.Name, str]] - keyalgorithm: Union[dns.name.Name, str] - edns: int - ednsflags: int - ednsoptions: Optional[List[dns.edns.Option]] - payload: int - cache: Any - flags: Optional[int] - retry_servfail: bool - rotate: bool - ndots: Optional[int] - _nameservers: Sequence[Union[str, dns.nameserver.Nameserver]] - - def __init__( - self, filename: str = "/etc/resolv.conf", configure: bool = True - ) -> None: - """*filename*, a ``str`` or file object, specifying a file - in standard /etc/resolv.conf format. This parameter is meaningful - only when *configure* is true and the platform is POSIX. - - *configure*, a ``bool``. If True (the default), the resolver - instance is configured in the normal fashion for the operating - system the resolver is running on. (I.e. by reading a - /etc/resolv.conf file on POSIX systems and from the registry - on Windows systems.) - """ - - self.reset() - if configure: - if sys.platform == "win32": # pragma: no cover - self.read_registry() - elif filename: - self.read_resolv_conf(filename) - - def reset(self) -> None: - """Reset all resolver configuration to the defaults.""" - - self.domain = dns.name.Name(dns.name.from_text(socket.gethostname())[1:]) - if len(self.domain) == 0: # pragma: no cover - self.domain = dns.name.root - self._nameservers = [] - self.nameserver_ports = {} - self.port = 53 - self.search = [] - self.use_search_by_default = False - self.timeout = 2.0 - self.lifetime = 5.0 - self.keyring = None - self.keyname = None - self.keyalgorithm = dns.tsig.default_algorithm - self.edns = -1 - self.ednsflags = 0 - self.ednsoptions = None - self.payload = 0 - self.cache = None - self.flags = None - self.retry_servfail = False - self.rotate = False - self.ndots = None - - def read_resolv_conf(self, f: Any) -> None: - """Process *f* as a file in the /etc/resolv.conf format. If f is - a ``str``, it is used as the name of the file to open; otherwise it - is treated as the file itself. - - Interprets the following items: - - - nameserver - name server IP address - - - domain - local domain name - - - search - search list for host-name lookup - - - options - supported options are rotate, timeout, edns0, and ndots - - """ - - nameservers = [] - if isinstance(f, str): - try: - cm: contextlib.AbstractContextManager = open(f) - except OSError: - # /etc/resolv.conf doesn't exist, can't be read, etc. - raise NoResolverConfiguration(f"cannot open {f}") - else: - cm = contextlib.nullcontext(f) - with cm as f: - for l in f: - if len(l) == 0 or l[0] == "#" or l[0] == ";": - continue - tokens = l.split() - - # Any line containing less than 2 tokens is malformed - if len(tokens) < 2: - continue - - if tokens[0] == "nameserver": - nameservers.append(tokens[1]) - elif tokens[0] == "domain": - self.domain = dns.name.from_text(tokens[1]) - # domain and search are exclusive - self.search = [] - elif tokens[0] == "search": - # the last search wins - self.search = [] - for suffix in tokens[1:]: - self.search.append(dns.name.from_text(suffix)) - # We don't set domain as it is not used if - # len(self.search) > 0 - elif tokens[0] == "options": - for opt in tokens[1:]: - if opt == "rotate": - self.rotate = True - elif opt == "edns0": - self.use_edns() - elif "timeout" in opt: - try: - self.timeout = int(opt.split(":")[1]) - except (ValueError, IndexError): - pass - elif "ndots" in opt: - try: - self.ndots = int(opt.split(":")[1]) - except (ValueError, IndexError): - pass - if len(nameservers) == 0: - raise NoResolverConfiguration("no nameservers") - # Assigning directly instead of appending means we invoke the - # setter logic, with additonal checking and enrichment. - self.nameservers = nameservers - - def read_registry(self) -> None: # pragma: no cover - """Extract resolver configuration from the Windows registry.""" - try: - info = dns.win32util.get_dns_info() # type: ignore - if info.domain is not None: - self.domain = info.domain - self.nameservers = info.nameservers - self.search = info.search - except AttributeError: - raise NotImplementedError - - def _compute_timeout( - self, - start: float, - lifetime: Optional[float] = None, - errors: Optional[List[ErrorTuple]] = None, - ) -> float: - lifetime = self.lifetime if lifetime is None else lifetime - now = time.time() - duration = now - start - if errors is None: - errors = [] - if duration < 0: - if duration < -1: - # Time going backwards is bad. Just give up. - raise LifetimeTimeout(timeout=duration, errors=errors) - else: - # Time went backwards, but only a little. This can - # happen, e.g. under vmware with older linux kernels. - # Pretend it didn't happen. - duration = 0 - if duration >= lifetime: - raise LifetimeTimeout(timeout=duration, errors=errors) - return min(lifetime - duration, self.timeout) - - def _get_qnames_to_try( - self, qname: dns.name.Name, search: Optional[bool] - ) -> List[dns.name.Name]: - # This is a separate method so we can unit test the search - # rules without requiring the Internet. - if search is None: - search = self.use_search_by_default - qnames_to_try = [] - if qname.is_absolute(): - qnames_to_try.append(qname) - else: - abs_qname = qname.concatenate(dns.name.root) - if search: - if len(self.search) > 0: - # There is a search list, so use it exclusively - search_list = self.search[:] - elif self.domain != dns.name.root and self.domain is not None: - # We have some notion of a domain that isn't the root, so - # use it as the search list. - search_list = [self.domain] - else: - search_list = [] - # Figure out the effective ndots (default is 1) - if self.ndots is None: - ndots = 1 - else: - ndots = self.ndots - for suffix in search_list: - qnames_to_try.append(qname + suffix) - if len(qname) > ndots: - # The name has at least ndots dots, so we should try an - # absolute query first. - qnames_to_try.insert(0, abs_qname) - else: - # The name has less than ndots dots, so we should search - # first, then try the absolute name. - qnames_to_try.append(abs_qname) - else: - qnames_to_try.append(abs_qname) - return qnames_to_try - - def use_tsig( - self, - keyring: Any, - keyname: Optional[Union[dns.name.Name, str]] = None, - algorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm, - ) -> None: - """Add a TSIG signature to each query. - - The parameters are passed to ``dns.message.Message.use_tsig()``; - see its documentation for details. - """ - - self.keyring = keyring - self.keyname = keyname - self.keyalgorithm = algorithm - - def use_edns( - self, - edns: Optional[Union[int, bool]] = 0, - ednsflags: int = 0, - payload: int = dns.message.DEFAULT_EDNS_PAYLOAD, - options: Optional[List[dns.edns.Option]] = None, - ) -> None: - """Configure EDNS behavior. - - *edns*, an ``int``, is the EDNS level to use. Specifying - ``None``, ``False``, or ``-1`` means "do not use EDNS", and in this case - the other parameters are ignored. Specifying ``True`` is - equivalent to specifying 0, i.e. "use EDNS0". - - *ednsflags*, an ``int``, the EDNS flag values. - - *payload*, an ``int``, is the EDNS sender's payload field, which is the - maximum size of UDP datagram the sender can handle. I.e. how big - a response to this message can be. - - *options*, a list of ``dns.edns.Option`` objects or ``None``, the EDNS - options. - """ - - if edns is None or edns is False: - edns = -1 - elif edns is True: - edns = 0 - self.edns = edns - self.ednsflags = ednsflags - self.payload = payload - self.ednsoptions = options - - def set_flags(self, flags: int) -> None: - """Overrides the default flags with your own. - - *flags*, an ``int``, the message flags to use. - """ - - self.flags = flags - - @classmethod - def _enrich_nameservers( - cls, - nameservers: Sequence[Union[str, dns.nameserver.Nameserver]], - nameserver_ports: Dict[str, int], - default_port: int, - ) -> List[dns.nameserver.Nameserver]: - enriched_nameservers = [] - if isinstance(nameservers, list): - for nameserver in nameservers: - enriched_nameserver: dns.nameserver.Nameserver - if isinstance(nameserver, dns.nameserver.Nameserver): - enriched_nameserver = nameserver - elif dns.inet.is_address(nameserver): - port = nameserver_ports.get(nameserver, default_port) - enriched_nameserver = dns.nameserver.Do53Nameserver( - nameserver, port - ) - else: - try: - if urlparse(nameserver).scheme != "https": - raise NotImplementedError - except Exception: - raise ValueError( - f"nameserver {nameserver} is not a " - "dns.nameserver.Nameserver instance or text form, " - "IP address, nor a valid https URL" - ) - enriched_nameserver = dns.nameserver.DoHNameserver(nameserver) - enriched_nameservers.append(enriched_nameserver) - else: - raise ValueError( - f"nameservers must be a list or tuple (not a {type(nameservers)})" - ) - return enriched_nameservers - - @property - def nameservers( - self, - ) -> Sequence[Union[str, dns.nameserver.Nameserver]]: - return self._nameservers - - @nameservers.setter - def nameservers( - self, nameservers: Sequence[Union[str, dns.nameserver.Nameserver]] - ) -> None: - """ - *nameservers*, a ``list`` of nameservers, where a nameserver is either - a string interpretable as a nameserver, or a ``dns.nameserver.Nameserver`` - instance. - - Raises ``ValueError`` if *nameservers* is not a list of nameservers. - """ - # We just call _enrich_nameservers() for checking - self._enrich_nameservers(nameservers, self.nameserver_ports, self.port) - self._nameservers = nameservers - - -class Resolver(BaseResolver): - """DNS stub resolver.""" - - def resolve( - self, - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - search: Optional[bool] = None, - ) -> Answer: # pylint: disable=arguments-differ - """Query nameservers to find the answer to the question. - - The *qname*, *rdtype*, and *rdclass* parameters may be objects - of the appropriate type, or strings that can be converted into objects - of the appropriate type. - - *qname*, a ``dns.name.Name`` or ``str``, the query name. - - *rdtype*, an ``int`` or ``str``, the query type. - - *rdclass*, an ``int`` or ``str``, the query class. - - *tcp*, a ``bool``. If ``True``, use TCP to make the query. - - *source*, a ``str`` or ``None``. If not ``None``, bind to this IP - address when making queries. - - *raise_on_no_answer*, a ``bool``. If ``True``, raise - ``dns.resolver.NoAnswer`` if there's no answer to the question. - - *source_port*, an ``int``, the port from which to send the message. - - *lifetime*, a ``float``, how many seconds a query should run - before timing out. - - *search*, a ``bool`` or ``None``, determines whether the - search list configured in the system's resolver configuration - are used for relative names, and whether the resolver's domain - may be added to relative names. The default is ``None``, - which causes the value of the resolver's - ``use_search_by_default`` attribute to be used. - - Raises ``dns.resolver.LifetimeTimeout`` if no answers could be found - in the specified lifetime. - - Raises ``dns.resolver.NXDOMAIN`` if the query name does not exist. - - Raises ``dns.resolver.YXDOMAIN`` if the query name is too long after - DNAME substitution. - - Raises ``dns.resolver.NoAnswer`` if *raise_on_no_answer* is - ``True`` and the query name exists but has no RRset of the - desired type and class. - - Raises ``dns.resolver.NoNameservers`` if no non-broken - nameservers are available to answer the question. - - Returns a ``dns.resolver.Answer`` instance. - - """ - - resolution = _Resolution( - self, qname, rdtype, rdclass, tcp, raise_on_no_answer, search - ) - start = time.time() - while True: - (request, answer) = resolution.next_request() - # Note we need to say "if answer is not None" and not just - # "if answer" because answer implements __len__, and python - # will call that. We want to return if we have an answer - # object, including in cases where its length is 0. - if answer is not None: - # cache hit! - return answer - assert request is not None # needed for type checking - done = False - while not done: - (nameserver, tcp, backoff) = resolution.next_nameserver() - if backoff: - time.sleep(backoff) - timeout = self._compute_timeout(start, lifetime, resolution.errors) - try: - response = nameserver.query( - request, - timeout=timeout, - source=source, - source_port=source_port, - max_size=tcp, - ) - except Exception as ex: - (_, done) = resolution.query_result(None, ex) - continue - (answer, done) = resolution.query_result(response, None) - # Note we need to say "if answer is not None" and not just - # "if answer" because answer implements __len__, and python - # will call that. We want to return if we have an answer - # object, including in cases where its length is 0. - if answer is not None: - return answer - - def query( - self, - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - ) -> Answer: # pragma: no cover - """Query nameservers to find the answer to the question. - - This method calls resolve() with ``search=True``, and is - provided for backwards compatibility with prior versions of - dnspython. See the documentation for the resolve() method for - further details. - """ - warnings.warn( - "please use dns.resolver.Resolver.resolve() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.resolve( - qname, - rdtype, - rdclass, - tcp, - source, - raise_on_no_answer, - source_port, - lifetime, - True, - ) - - def resolve_address(self, ipaddr: str, *args: Any, **kwargs: Any) -> Answer: - """Use a resolver to run a reverse query for PTR records. - - This utilizes the resolve() method to perform a PTR lookup on the - specified IP address. - - *ipaddr*, a ``str``, the IPv4 or IPv6 address you want to get - the PTR record for. - - All other arguments that can be passed to the resolve() function - except for rdtype and rdclass are also supported by this - function. - """ - # We make a modified kwargs for type checking happiness, as otherwise - # we get a legit warning about possibly having rdtype and rdclass - # in the kwargs more than once. - modified_kwargs: Dict[str, Any] = {} - modified_kwargs.update(kwargs) - modified_kwargs["rdtype"] = dns.rdatatype.PTR - modified_kwargs["rdclass"] = dns.rdataclass.IN - return self.resolve( - dns.reversename.from_address(ipaddr), *args, **modified_kwargs - ) - - def resolve_name( - self, - name: Union[dns.name.Name, str], - family: int = socket.AF_UNSPEC, - **kwargs: Any, - ) -> HostAnswers: - """Use a resolver to query for address records. - - This utilizes the resolve() method to perform A and/or AAAA lookups on - the specified name. - - *qname*, a ``dns.name.Name`` or ``str``, the name to resolve. - - *family*, an ``int``, the address family. If socket.AF_UNSPEC - (the default), both A and AAAA records will be retrieved. - - All other arguments that can be passed to the resolve() function - except for rdtype and rdclass are also supported by this - function. - """ - # We make a modified kwargs for type checking happiness, as otherwise - # we get a legit warning about possibly having rdtype and rdclass - # in the kwargs more than once. - modified_kwargs: Dict[str, Any] = {} - modified_kwargs.update(kwargs) - modified_kwargs.pop("rdtype", None) - modified_kwargs["rdclass"] = dns.rdataclass.IN - - if family == socket.AF_INET: - v4 = self.resolve(name, dns.rdatatype.A, **modified_kwargs) - return HostAnswers.make(v4=v4) - elif family == socket.AF_INET6: - v6 = self.resolve(name, dns.rdatatype.AAAA, **modified_kwargs) - return HostAnswers.make(v6=v6) - elif family != socket.AF_UNSPEC: # pragma: no cover - raise NotImplementedError(f"unknown address family {family}") - - raise_on_no_answer = modified_kwargs.pop("raise_on_no_answer", True) - lifetime = modified_kwargs.pop("lifetime", None) - start = time.time() - v6 = self.resolve( - name, - dns.rdatatype.AAAA, - raise_on_no_answer=False, - lifetime=self._compute_timeout(start, lifetime), - **modified_kwargs, - ) - # Note that setting name ensures we query the same name - # for A as we did for AAAA. (This is just in case search lists - # are active by default in the resolver configuration and - # we might be talking to a server that says NXDOMAIN when it - # wants to say NOERROR no data. - name = v6.qname - v4 = self.resolve( - name, - dns.rdatatype.A, - raise_on_no_answer=False, - lifetime=self._compute_timeout(start, lifetime), - **modified_kwargs, - ) - answers = HostAnswers.make(v6=v6, v4=v4, add_empty=not raise_on_no_answer) - if not answers: - raise NoAnswer(response=v6.response) - return answers - - # pylint: disable=redefined-outer-name - - def canonical_name(self, name: Union[dns.name.Name, str]) -> dns.name.Name: - """Determine the canonical name of *name*. - - The canonical name is the name the resolver uses for queries - after all CNAME and DNAME renamings have been applied. - - *name*, a ``dns.name.Name`` or ``str``, the query name. - - This method can raise any exception that ``resolve()`` can - raise, other than ``dns.resolver.NoAnswer`` and - ``dns.resolver.NXDOMAIN``. - - Returns a ``dns.name.Name``. - """ - try: - answer = self.resolve(name, raise_on_no_answer=False) - canonical_name = answer.canonical_name - except dns.resolver.NXDOMAIN as e: - canonical_name = e.canonical_name - return canonical_name - - # pylint: enable=redefined-outer-name - - def try_ddr(self, lifetime: float = 5.0) -> None: - """Try to update the resolver's nameservers using Discovery of Designated - Resolvers (DDR). If successful, the resolver will subsequently use - DNS-over-HTTPS or DNS-over-TLS for future queries. - - *lifetime*, a float, is the maximum time to spend attempting DDR. The default - is 5 seconds. - - If the SVCB query is successful and results in a non-empty list of nameservers, - then the resolver's nameservers are set to the returned servers in priority - order. - - The current implementation does not use any address hints from the SVCB record, - nor does it resolve addresses for the SCVB target name, rather it assumes that - the bootstrap nameserver will always be one of the addresses and uses it. - A future revision to the code may offer fuller support. The code verifies that - the bootstrap nameserver is in the Subject Alternative Name field of the - TLS certficate. - """ - try: - expiration = time.time() + lifetime - answer = self.resolve( - dns._ddr._local_resolver_name, "SVCB", lifetime=lifetime - ) - timeout = dns.query._remaining(expiration) - nameservers = dns._ddr._get_nameservers_sync(answer, timeout) - if len(nameservers) > 0: - self.nameservers = nameservers - except Exception: # pragma: no cover - pass - - -#: The default resolver. -default_resolver: Optional[Resolver] = None - - -def get_default_resolver() -> Resolver: - """Get the default resolver, initializing it if necessary.""" - if default_resolver is None: - reset_default_resolver() - assert default_resolver is not None - return default_resolver - - -def reset_default_resolver() -> None: - """Re-initialize default resolver. - - Note that the resolver configuration (i.e. /etc/resolv.conf on UNIX - systems) will be re-read immediately. - """ - - global default_resolver - default_resolver = Resolver() - - -def resolve( - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - search: Optional[bool] = None, -) -> Answer: # pragma: no cover - """Query nameservers to find the answer to the question. - - This is a convenience function that uses the default resolver - object to make the query. - - See ``dns.resolver.Resolver.resolve`` for more information on the - parameters. - """ - - return get_default_resolver().resolve( - qname, - rdtype, - rdclass, - tcp, - source, - raise_on_no_answer, - source_port, - lifetime, - search, - ) - - -def query( - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, -) -> Answer: # pragma: no cover - """Query nameservers to find the answer to the question. - - This method calls resolve() with ``search=True``, and is - provided for backwards compatibility with prior versions of - dnspython. See the documentation for the resolve() method for - further details. - """ - warnings.warn( - "please use dns.resolver.resolve() instead", DeprecationWarning, stacklevel=2 - ) - return resolve( - qname, - rdtype, - rdclass, - tcp, - source, - raise_on_no_answer, - source_port, - lifetime, - True, - ) - - -def resolve_address(ipaddr: str, *args: Any, **kwargs: Any) -> Answer: - """Use a resolver to run a reverse query for PTR records. - - See ``dns.resolver.Resolver.resolve_address`` for more information on the - parameters. - """ - - return get_default_resolver().resolve_address(ipaddr, *args, **kwargs) - - -def resolve_name( - name: Union[dns.name.Name, str], family: int = socket.AF_UNSPEC, **kwargs: Any -) -> HostAnswers: - """Use a resolver to query for address records. - - See ``dns.resolver.Resolver.resolve_name`` for more information on the - parameters. - """ - - return get_default_resolver().resolve_name(name, family, **kwargs) - - -def canonical_name(name: Union[dns.name.Name, str]) -> dns.name.Name: - """Determine the canonical name of *name*. - - See ``dns.resolver.Resolver.canonical_name`` for more information on the - parameters and possible exceptions. - """ - - return get_default_resolver().canonical_name(name) - - -def try_ddr(lifetime: float = 5.0) -> None: # pragma: no cover - """Try to update the default resolver's nameservers using Discovery of Designated - Resolvers (DDR). If successful, the resolver will subsequently use - DNS-over-HTTPS or DNS-over-TLS for future queries. - - See :py:func:`dns.resolver.Resolver.try_ddr` for more information. - """ - return get_default_resolver().try_ddr(lifetime) - - -def zone_for_name( - name: Union[dns.name.Name, str], - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - tcp: bool = False, - resolver: Optional[Resolver] = None, - lifetime: Optional[float] = None, -) -> dns.name.Name: - """Find the name of the zone which contains the specified name. - - *name*, an absolute ``dns.name.Name`` or ``str``, the query name. - - *rdclass*, an ``int``, the query class. - - *tcp*, a ``bool``. If ``True``, use TCP to make the query. - - *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. - If ``None``, the default, then the default resolver is used. - - *lifetime*, a ``float``, the total time to allow for the queries needed - to determine the zone. If ``None``, the default, then only the individual - query limits of the resolver apply. - - Raises ``dns.resolver.NoRootSOA`` if there is no SOA RR at the DNS - root. (This is only likely to happen if you're using non-default - root servers in your network and they are misconfigured.) - - Raises ``dns.resolver.LifetimeTimeout`` if the answer could not be - found in the allotted lifetime. - - Returns a ``dns.name.Name``. - """ - - if isinstance(name, str): - name = dns.name.from_text(name, dns.name.root) - if resolver is None: - resolver = get_default_resolver() - if not name.is_absolute(): - raise NotAbsolute(name) - start = time.time() - expiration: Optional[float] - if lifetime is not None: - expiration = start + lifetime - else: - expiration = None - while 1: - try: - rlifetime: Optional[float] - if expiration is not None: - rlifetime = expiration - time.time() - if rlifetime <= 0: - rlifetime = 0 - else: - rlifetime = None - answer = resolver.resolve( - name, dns.rdatatype.SOA, rdclass, tcp, lifetime=rlifetime - ) - assert answer.rrset is not None - if answer.rrset.name == name: - return name - # otherwise we were CNAMEd or DNAMEd and need to look higher - except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer) as e: - if isinstance(e, dns.resolver.NXDOMAIN): - response = e.responses().get(name) - else: - response = e.response() # pylint: disable=no-value-for-parameter - if response: - for rrs in response.authority: - if rrs.rdtype == dns.rdatatype.SOA and rrs.rdclass == rdclass: - (nr, _, _) = rrs.name.fullcompare(name) - if nr == dns.name.NAMERELN_SUPERDOMAIN: - # We're doing a proper superdomain check as - # if the name were equal we ought to have gotten - # it in the answer section! We are ignoring the - # possibility that the authority is insane and - # is including multiple SOA RRs for different - # authorities. - return rrs.name - # we couldn't extract anything useful from the response (e.g. it's - # a type 3 NXDOMAIN) - try: - name = name.parent() - except dns.name.NoParent: - raise NoRootSOA - - -def make_resolver_at( - where: Union[dns.name.Name, str], - port: int = 53, - family: int = socket.AF_UNSPEC, - resolver: Optional[Resolver] = None, -) -> Resolver: - """Make a stub resolver using the specified destination as the full resolver. - - *where*, a ``dns.name.Name`` or ``str`` the domain name or IP address of the - full resolver. - - *port*, an ``int``, the port to use. If not specified, the default is 53. - - *family*, an ``int``, the address family to use. This parameter is used if - *where* is not an address. The default is ``socket.AF_UNSPEC`` in which case - the first address returned by ``resolve_name()`` will be used, otherwise the - first address of the specified family will be used. - - *resolver*, a ``dns.resolver.Resolver`` or ``None``, the resolver to use for - resolution of hostnames. If not specified, the default resolver will be used. - - Returns a ``dns.resolver.Resolver`` or raises an exception. - """ - if resolver is None: - resolver = get_default_resolver() - nameservers: List[Union[str, dns.nameserver.Nameserver]] = [] - if isinstance(where, str) and dns.inet.is_address(where): - nameservers.append(dns.nameserver.Do53Nameserver(where, port)) - else: - for address in resolver.resolve_name(where, family).addresses(): - nameservers.append(dns.nameserver.Do53Nameserver(address, port)) - res = dns.resolver.Resolver(configure=False) - res.nameservers = nameservers - return res - - -def resolve_at( - where: Union[dns.name.Name, str], - qname: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.A, - rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - tcp: bool = False, - source: Optional[str] = None, - raise_on_no_answer: bool = True, - source_port: int = 0, - lifetime: Optional[float] = None, - search: Optional[bool] = None, - port: int = 53, - family: int = socket.AF_UNSPEC, - resolver: Optional[Resolver] = None, -) -> Answer: - """Query nameservers to find the answer to the question. - - This is a convenience function that calls ``dns.resolver.make_resolver_at()`` to - make a resolver, and then uses it to resolve the query. - - See ``dns.resolver.Resolver.resolve`` for more information on the resolution - parameters, and ``dns.resolver.make_resolver_at`` for information about the resolver - parameters *where*, *port*, *family*, and *resolver*. - - If making more than one query, it is more efficient to call - ``dns.resolver.make_resolver_at()`` and then use that resolver for the queries - instead of calling ``resolve_at()`` multiple times. - """ - return make_resolver_at(where, port, family, resolver).resolve( - qname, - rdtype, - rdclass, - tcp, - source, - raise_on_no_answer, - source_port, - lifetime, - search, - ) - - -# -# Support for overriding the system resolver for all python code in the -# running process. -# - -_protocols_for_socktype = { - socket.SOCK_DGRAM: [socket.SOL_UDP], - socket.SOCK_STREAM: [socket.SOL_TCP], -} - -_resolver = None -_original_getaddrinfo = socket.getaddrinfo -_original_getnameinfo = socket.getnameinfo -_original_getfqdn = socket.getfqdn -_original_gethostbyname = socket.gethostbyname -_original_gethostbyname_ex = socket.gethostbyname_ex -_original_gethostbyaddr = socket.gethostbyaddr - - -def _getaddrinfo( - host=None, service=None, family=socket.AF_UNSPEC, socktype=0, proto=0, flags=0 -): - if flags & socket.AI_NUMERICHOST != 0: - # Short circuit directly into the system's getaddrinfo(). We're - # not adding any value in this case, and this avoids infinite loops - # because dns.query.* needs to call getaddrinfo() for IPv6 scoping - # reasons. We will also do this short circuit below if we - # discover that the host is an address literal. - return _original_getaddrinfo(host, service, family, socktype, proto, flags) - if flags & (socket.AI_ADDRCONFIG | socket.AI_V4MAPPED) != 0: - # Not implemented. We raise a gaierror as opposed to a - # NotImplementedError as it helps callers handle errors more - # appropriately. [Issue #316] - # - # We raise EAI_FAIL as opposed to EAI_SYSTEM because there is - # no EAI_SYSTEM on Windows [Issue #416]. We didn't go for - # EAI_BADFLAGS as the flags aren't bad, we just don't - # implement them. - raise socket.gaierror( - socket.EAI_FAIL, "Non-recoverable failure in name resolution" - ) - if host is None and service is None: - raise socket.gaierror(socket.EAI_NONAME, "Name or service not known") - addrs = [] - canonical_name = None # pylint: disable=redefined-outer-name - # Is host None or an address literal? If so, use the system's - # getaddrinfo(). - if host is None: - return _original_getaddrinfo(host, service, family, socktype, proto, flags) - try: - # We don't care about the result of af_for_address(), we're just - # calling it so it raises an exception if host is not an IPv4 or - # IPv6 address. - dns.inet.af_for_address(host) - return _original_getaddrinfo(host, service, family, socktype, proto, flags) - except Exception: - pass - # Something needs resolution! - try: - answers = _resolver.resolve_name(host, family) - addrs = answers.addresses_and_families() - canonical_name = answers.canonical_name().to_text(True) - except dns.resolver.NXDOMAIN: - raise socket.gaierror(socket.EAI_NONAME, "Name or service not known") - except Exception: - # We raise EAI_AGAIN here as the failure may be temporary - # (e.g. a timeout) and EAI_SYSTEM isn't defined on Windows. - # [Issue #416] - raise socket.gaierror(socket.EAI_AGAIN, "Temporary failure in name resolution") - port = None - try: - # Is it a port literal? - if service is None: - port = 0 - else: - port = int(service) - except Exception: - if flags & socket.AI_NUMERICSERV == 0: - try: - port = socket.getservbyname(service) - except Exception: - pass - if port is None: - raise socket.gaierror(socket.EAI_NONAME, "Name or service not known") - tuples = [] - if socktype == 0: - socktypes = [socket.SOCK_DGRAM, socket.SOCK_STREAM] - else: - socktypes = [socktype] - if flags & socket.AI_CANONNAME != 0: - cname = canonical_name - else: - cname = "" - for addr, af in addrs: - for socktype in socktypes: - for proto in _protocols_for_socktype[socktype]: - addr_tuple = dns.inet.low_level_address_tuple((addr, port), af) - tuples.append((af, socktype, proto, cname, addr_tuple)) - if len(tuples) == 0: - raise socket.gaierror(socket.EAI_NONAME, "Name or service not known") - return tuples - - -def _getnameinfo(sockaddr, flags=0): - host = sockaddr[0] - port = sockaddr[1] - if len(sockaddr) == 4: - scope = sockaddr[3] - family = socket.AF_INET6 - else: - scope = None - family = socket.AF_INET - tuples = _getaddrinfo(host, port, family, socket.SOCK_STREAM, socket.SOL_TCP, 0) - if len(tuples) > 1: - raise OSError("sockaddr resolved to multiple addresses") - addr = tuples[0][4][0] - if flags & socket.NI_DGRAM: - pname = "udp" - else: - pname = "tcp" - qname = dns.reversename.from_address(addr) - if flags & socket.NI_NUMERICHOST == 0: - try: - answer = _resolver.resolve(qname, "PTR") - hostname = answer.rrset[0].target.to_text(True) - except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): - if flags & socket.NI_NAMEREQD: - raise socket.gaierror(socket.EAI_NONAME, "Name or service not known") - hostname = addr - if scope is not None: - hostname += "%" + str(scope) - else: - hostname = addr - if scope is not None: - hostname += "%" + str(scope) - if flags & socket.NI_NUMERICSERV: - service = str(port) - else: - service = socket.getservbyport(port, pname) - return (hostname, service) - - -def _getfqdn(name=None): - if name is None: - name = socket.gethostname() - try: - (name, _, _) = _gethostbyaddr(name) - # Python's version checks aliases too, but our gethostbyname - # ignores them, so we do so here as well. - except Exception: # pragma: no cover - pass - return name - - -def _gethostbyname(name): - return _gethostbyname_ex(name)[2][0] - - -def _gethostbyname_ex(name): - aliases = [] - addresses = [] - tuples = _getaddrinfo( - name, 0, socket.AF_INET, socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_CANONNAME - ) - canonical = tuples[0][3] - for item in tuples: - addresses.append(item[4][0]) - # XXX we just ignore aliases - return (canonical, aliases, addresses) - - -def _gethostbyaddr(ip): - try: - dns.ipv6.inet_aton(ip) - sockaddr = (ip, 80, 0, 0) - family = socket.AF_INET6 - except Exception: - try: - dns.ipv4.inet_aton(ip) - except Exception: - raise socket.gaierror(socket.EAI_NONAME, "Name or service not known") - sockaddr = (ip, 80) - family = socket.AF_INET - (name, _) = _getnameinfo(sockaddr, socket.NI_NAMEREQD) - aliases = [] - addresses = [] - tuples = _getaddrinfo( - name, 0, family, socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_CANONNAME - ) - canonical = tuples[0][3] - # We only want to include an address from the tuples if it's the - # same as the one we asked about. We do this comparison in binary - # to avoid any differences in text representations. - bin_ip = dns.inet.inet_pton(family, ip) - for item in tuples: - addr = item[4][0] - bin_addr = dns.inet.inet_pton(family, addr) - if bin_ip == bin_addr: - addresses.append(addr) - # XXX we just ignore aliases - return (canonical, aliases, addresses) - - -def override_system_resolver(resolver: Optional[Resolver] = None) -> None: - """Override the system resolver routines in the socket module with - versions which use dnspython's resolver. - - This can be useful in testing situations where you want to control - the resolution behavior of python code without having to change - the system's resolver settings (e.g. /etc/resolv.conf). - - The resolver to use may be specified; if it's not, the default - resolver will be used. - - resolver, a ``dns.resolver.Resolver`` or ``None``, the resolver to use. - """ - - if resolver is None: - resolver = get_default_resolver() - global _resolver - _resolver = resolver - socket.getaddrinfo = _getaddrinfo - socket.getnameinfo = _getnameinfo - socket.getfqdn = _getfqdn - socket.gethostbyname = _gethostbyname - socket.gethostbyname_ex = _gethostbyname_ex - socket.gethostbyaddr = _gethostbyaddr - - -def restore_system_resolver() -> None: - """Undo the effects of prior override_system_resolver().""" - - global _resolver - _resolver = None - socket.getaddrinfo = _original_getaddrinfo - socket.getnameinfo = _original_getnameinfo - socket.getfqdn = _original_getfqdn - socket.gethostbyname = _original_gethostbyname - socket.gethostbyname_ex = _original_gethostbyname_ex - socket.gethostbyaddr = _original_gethostbyaddr diff --git a/venv/Lib/site-packages/dns/reversename.py b/venv/Lib/site-packages/dns/reversename.py deleted file mode 100644 index 8236c71..0000000 --- a/venv/Lib/site-packages/dns/reversename.py +++ /dev/null @@ -1,105 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2006-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Reverse Map Names.""" - -import binascii - -import dns.ipv4 -import dns.ipv6 -import dns.name - -ipv4_reverse_domain = dns.name.from_text("in-addr.arpa.") -ipv6_reverse_domain = dns.name.from_text("ip6.arpa.") - - -def from_address( - text: str, - v4_origin: dns.name.Name = ipv4_reverse_domain, - v6_origin: dns.name.Name = ipv6_reverse_domain, -) -> dns.name.Name: - """Convert an IPv4 or IPv6 address in textual form into a Name object whose - value is the reverse-map domain name of the address. - - *text*, a ``str``, is an IPv4 or IPv6 address in textual form - (e.g. '127.0.0.1', '::1') - - *v4_origin*, a ``dns.name.Name`` to append to the labels corresponding to - the address if the address is an IPv4 address, instead of the default - (in-addr.arpa.) - - *v6_origin*, a ``dns.name.Name`` to append to the labels corresponding to - the address if the address is an IPv6 address, instead of the default - (ip6.arpa.) - - Raises ``dns.exception.SyntaxError`` if the address is badly formed. - - Returns a ``dns.name.Name``. - """ - - try: - v6 = dns.ipv6.inet_aton(text) - if dns.ipv6.is_mapped(v6): - parts = ["%d" % byte for byte in v6[12:]] - origin = v4_origin - else: - parts = [x for x in str(binascii.hexlify(v6).decode())] - origin = v6_origin - except Exception: - parts = ["%d" % byte for byte in dns.ipv4.inet_aton(text)] - origin = v4_origin - return dns.name.from_text(".".join(reversed(parts)), origin=origin) - - -def to_address( - name: dns.name.Name, - v4_origin: dns.name.Name = ipv4_reverse_domain, - v6_origin: dns.name.Name = ipv6_reverse_domain, -) -> str: - """Convert a reverse map domain name into textual address form. - - *name*, a ``dns.name.Name``, an IPv4 or IPv6 address in reverse-map name - form. - - *v4_origin*, a ``dns.name.Name`` representing the top-level domain for - IPv4 addresses, instead of the default (in-addr.arpa.) - - *v6_origin*, a ``dns.name.Name`` representing the top-level domain for - IPv4 addresses, instead of the default (ip6.arpa.) - - Raises ``dns.exception.SyntaxError`` if the name does not have a - reverse-map form. - - Returns a ``str``. - """ - - if name.is_subdomain(v4_origin): - name = name.relativize(v4_origin) - text = b".".join(reversed(name.labels)) - # run through inet_ntoa() to check syntax and make pretty. - return dns.ipv4.inet_ntoa(dns.ipv4.inet_aton(text)) - elif name.is_subdomain(v6_origin): - name = name.relativize(v6_origin) - labels = list(reversed(name.labels)) - parts = [] - for i in range(0, len(labels), 4): - parts.append(b"".join(labels[i : i + 4])) - text = b":".join(parts) - # run through inet_ntoa() to check syntax and make pretty. - return dns.ipv6.inet_ntoa(dns.ipv6.inet_aton(text)) - else: - raise dns.exception.SyntaxError("unknown reverse-map address family") diff --git a/venv/Lib/site-packages/dns/rrset.py b/venv/Lib/site-packages/dns/rrset.py deleted file mode 100644 index 6f39b10..0000000 --- a/venv/Lib/site-packages/dns/rrset.py +++ /dev/null @@ -1,285 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS RRsets (an RRset is a named rdataset)""" - -from typing import Any, Collection, Dict, Optional, Union, cast - -import dns.name -import dns.rdataclass -import dns.rdataset -import dns.renderer - - -class RRset(dns.rdataset.Rdataset): - """A DNS RRset (named rdataset). - - RRset inherits from Rdataset, and RRsets can be treated as - Rdatasets in most cases. There are, however, a few notable - exceptions. RRsets have different to_wire() and to_text() method - arguments, reflecting the fact that RRsets always have an owner - name. - """ - - __slots__ = ["name", "deleting"] - - def __init__( - self, - name: dns.name.Name, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - deleting: Optional[dns.rdataclass.RdataClass] = None, - ): - """Create a new RRset.""" - - super().__init__(rdclass, rdtype, covers) - self.name = name - self.deleting = deleting - - def _clone(self): - obj = super()._clone() - obj.name = self.name - obj.deleting = self.deleting - return obj - - def __repr__(self): - if self.covers == 0: - ctext = "" - else: - ctext = "(" + dns.rdatatype.to_text(self.covers) + ")" - if self.deleting is not None: - dtext = " delete=" + dns.rdataclass.to_text(self.deleting) - else: - dtext = "" - return ( - "" - ) - - def __str__(self): - return self.to_text() - - def __eq__(self, other): - if isinstance(other, RRset): - if self.name != other.name: - return False - elif not isinstance(other, dns.rdataset.Rdataset): - return False - return super().__eq__(other) - - def match(self, *args: Any, **kwargs: Any) -> bool: # type: ignore[override] - """Does this rrset match the specified attributes? - - Behaves as :py:func:`full_match()` if the first argument is a - ``dns.name.Name``, and as :py:func:`dns.rdataset.Rdataset.match()` - otherwise. - - (This behavior fixes a design mistake where the signature of this - method became incompatible with that of its superclass. The fix - makes RRsets matchable as Rdatasets while preserving backwards - compatibility.) - """ - if isinstance(args[0], dns.name.Name): - return self.full_match(*args, **kwargs) # type: ignore[arg-type] - else: - return super().match(*args, **kwargs) # type: ignore[arg-type] - - def full_match( - self, - name: dns.name.Name, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType, - deleting: Optional[dns.rdataclass.RdataClass] = None, - ) -> bool: - """Returns ``True`` if this rrset matches the specified name, class, - type, covers, and deletion state. - """ - if not super().match(rdclass, rdtype, covers): - return False - if self.name != name or self.deleting != deleting: - return False - return True - - # pylint: disable=arguments-differ - - def to_text( # type: ignore[override] - self, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - **kw: Dict[str, Any], - ) -> str: - """Convert the RRset into DNS zone file format. - - See ``dns.name.Name.choose_relativity`` for more information - on how *origin* and *relativize* determine the way names - are emitted. - - Any additional keyword arguments are passed on to the rdata - ``to_text()`` method. - - *origin*, a ``dns.name.Name`` or ``None``, the origin for relative - names. - - *relativize*, a ``bool``. If ``True``, names will be relativized - to *origin*. - """ - - return super().to_text( - self.name, origin, relativize, self.deleting, **kw # type: ignore - ) - - def to_wire( # type: ignore[override] - self, - file: Any, - compress: Optional[dns.name.CompressType] = None, # type: ignore - origin: Optional[dns.name.Name] = None, - **kw: Dict[str, Any], - ) -> int: - """Convert the RRset to wire format. - - All keyword arguments are passed to ``dns.rdataset.to_wire()``; see - that function for details. - - Returns an ``int``, the number of records emitted. - """ - - return super().to_wire( - self.name, file, compress, origin, self.deleting, **kw # type:ignore - ) - - # pylint: enable=arguments-differ - - def to_rdataset(self) -> dns.rdataset.Rdataset: - """Convert an RRset into an Rdataset. - - Returns a ``dns.rdataset.Rdataset``. - """ - return dns.rdataset.from_rdata_list(self.ttl, list(self)) - - -def from_text_list( - name: Union[dns.name.Name, str], - ttl: int, - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - text_rdatas: Collection[str], - idna_codec: Optional[dns.name.IDNACodec] = None, - origin: Optional[dns.name.Name] = None, - relativize: bool = True, - relativize_to: Optional[dns.name.Name] = None, -) -> RRset: - """Create an RRset with the specified name, TTL, class, and type, and with - the specified list of rdatas in text format. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder to use; if ``None``, the default IDNA 2003 - encoder/decoder is used. - - *origin*, a ``dns.name.Name`` (or ``None``), the - origin to use for relative names. - - *relativize*, a ``bool``. If true, name will be relativized. - - *relativize_to*, a ``dns.name.Name`` (or ``None``), the origin to use - when relativizing names. If not set, the *origin* value will be used. - - Returns a ``dns.rrset.RRset`` object. - """ - - if isinstance(name, str): - name = dns.name.from_text(name, None, idna_codec=idna_codec) - rdclass = dns.rdataclass.RdataClass.make(rdclass) - rdtype = dns.rdatatype.RdataType.make(rdtype) - r = RRset(name, rdclass, rdtype) - r.update_ttl(ttl) - for t in text_rdatas: - rd = dns.rdata.from_text( - r.rdclass, r.rdtype, t, origin, relativize, relativize_to, idna_codec - ) - r.add(rd) - return r - - -def from_text( - name: Union[dns.name.Name, str], - ttl: int, - rdclass: Union[dns.rdataclass.RdataClass, str], - rdtype: Union[dns.rdatatype.RdataType, str], - *text_rdatas: Any, -) -> RRset: - """Create an RRset with the specified name, TTL, class, and type and with - the specified rdatas in text format. - - Returns a ``dns.rrset.RRset`` object. - """ - - return from_text_list( - name, ttl, rdclass, rdtype, cast(Collection[str], text_rdatas) - ) - - -def from_rdata_list( - name: Union[dns.name.Name, str], - ttl: int, - rdatas: Collection[dns.rdata.Rdata], - idna_codec: Optional[dns.name.IDNACodec] = None, -) -> RRset: - """Create an RRset with the specified name and TTL, and with - the specified list of rdata objects. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder to use; if ``None``, the default IDNA 2003 - encoder/decoder is used. - - Returns a ``dns.rrset.RRset`` object. - - """ - - if isinstance(name, str): - name = dns.name.from_text(name, None, idna_codec=idna_codec) - - if len(rdatas) == 0: - raise ValueError("rdata list must not be empty") - r = None - for rd in rdatas: - if r is None: - r = RRset(name, rd.rdclass, rd.rdtype) - r.update_ttl(ttl) - r.add(rd) - assert r is not None - return r - - -def from_rdata(name: Union[dns.name.Name, str], ttl: int, *rdatas: Any) -> RRset: - """Create an RRset with the specified name and TTL, and with - the specified rdata objects. - - Returns a ``dns.rrset.RRset`` object. - """ - - return from_rdata_list(name, ttl, cast(Collection[dns.rdata.Rdata], rdatas)) diff --git a/venv/Lib/site-packages/dns/serial.py b/venv/Lib/site-packages/dns/serial.py deleted file mode 100644 index 3417299..0000000 --- a/venv/Lib/site-packages/dns/serial.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -"""Serial Number Arthimetic from RFC 1982""" - - -class Serial: - def __init__(self, value: int, bits: int = 32): - self.value = value % 2**bits - self.bits = bits - - def __repr__(self): - return f"dns.serial.Serial({self.value}, {self.bits})" - - def __eq__(self, other): - if isinstance(other, int): - other = Serial(other, self.bits) - elif not isinstance(other, Serial) or other.bits != self.bits: - return NotImplemented - return self.value == other.value - - def __ne__(self, other): - if isinstance(other, int): - other = Serial(other, self.bits) - elif not isinstance(other, Serial) or other.bits != self.bits: - return NotImplemented - return self.value != other.value - - def __lt__(self, other): - if isinstance(other, int): - other = Serial(other, self.bits) - elif not isinstance(other, Serial) or other.bits != self.bits: - return NotImplemented - if self.value < other.value and other.value - self.value < 2 ** (self.bits - 1): - return True - elif self.value > other.value and self.value - other.value > 2 ** ( - self.bits - 1 - ): - return True - else: - return False - - def __le__(self, other): - return self == other or self < other - - def __gt__(self, other): - if isinstance(other, int): - other = Serial(other, self.bits) - elif not isinstance(other, Serial) or other.bits != self.bits: - return NotImplemented - if self.value < other.value and other.value - self.value > 2 ** (self.bits - 1): - return True - elif self.value > other.value and self.value - other.value < 2 ** ( - self.bits - 1 - ): - return True - else: - return False - - def __ge__(self, other): - return self == other or self > other - - def __add__(self, other): - v = self.value - if isinstance(other, Serial): - delta = other.value - elif isinstance(other, int): - delta = other - else: - raise ValueError - if abs(delta) > (2 ** (self.bits - 1) - 1): - raise ValueError - v += delta - v = v % 2**self.bits - return Serial(v, self.bits) - - def __iadd__(self, other): - v = self.value - if isinstance(other, Serial): - delta = other.value - elif isinstance(other, int): - delta = other - else: - raise ValueError - if abs(delta) > (2 ** (self.bits - 1) - 1): - raise ValueError - v += delta - v = v % 2**self.bits - self.value = v - return self - - def __sub__(self, other): - v = self.value - if isinstance(other, Serial): - delta = other.value - elif isinstance(other, int): - delta = other - else: - raise ValueError - if abs(delta) > (2 ** (self.bits - 1) - 1): - raise ValueError - v -= delta - v = v % 2**self.bits - return Serial(v, self.bits) - - def __isub__(self, other): - v = self.value - if isinstance(other, Serial): - delta = other.value - elif isinstance(other, int): - delta = other - else: - raise ValueError - if abs(delta) > (2 ** (self.bits - 1) - 1): - raise ValueError - v -= delta - v = v % 2**self.bits - self.value = v - return self diff --git a/venv/Lib/site-packages/dns/set.py b/venv/Lib/site-packages/dns/set.py deleted file mode 100644 index ae8f0dd..0000000 --- a/venv/Lib/site-packages/dns/set.py +++ /dev/null @@ -1,308 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -import itertools - - -class Set: - """A simple set class. - - This class was originally used to deal with python not having a set class, and - originally the class used lists in its implementation. The ordered and indexable - nature of RRsets and Rdatasets is unfortunately widely used in dnspython - applications, so for backwards compatibility sets continue to be a custom class, now - based on an ordered dictionary. - """ - - __slots__ = ["items"] - - def __init__(self, items=None): - """Initialize the set. - - *items*, an iterable or ``None``, the initial set of items. - """ - - self.items = dict() - if items is not None: - for item in items: - # This is safe for how we use set, but if other code - # subclasses it could be a legitimate issue. - self.add(item) # lgtm[py/init-calls-subclass] - - def __repr__(self): - return f"dns.set.Set({repr(list(self.items.keys()))})" # pragma: no cover - - def add(self, item): - """Add an item to the set.""" - - if item not in self.items: - self.items[item] = None - - def remove(self, item): - """Remove an item from the set.""" - - try: - del self.items[item] - except KeyError: - raise ValueError - - def discard(self, item): - """Remove an item from the set if present.""" - - self.items.pop(item, None) - - def pop(self): - """Remove an arbitrary item from the set.""" - (k, _) = self.items.popitem() - return k - - def _clone(self) -> "Set": - """Make a (shallow) copy of the set. - - There is a 'clone protocol' that subclasses of this class - should use. To make a copy, first call your super's _clone() - method, and use the object returned as the new instance. Then - make shallow copies of the attributes defined in the subclass. - - This protocol allows us to write the set algorithms that - return new instances (e.g. union) once, and keep using them in - subclasses. - """ - - if hasattr(self, "_clone_class"): - cls = self._clone_class # type: ignore - else: - cls = self.__class__ - obj = cls.__new__(cls) - obj.items = dict() - obj.items.update(self.items) - return obj - - def __copy__(self): - """Make a (shallow) copy of the set.""" - - return self._clone() - - def copy(self): - """Make a (shallow) copy of the set.""" - - return self._clone() - - def union_update(self, other): - """Update the set, adding any elements from other which are not - already in the set. - """ - - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - if self is other: # lgtm[py/comparison-using-is] - return - for item in other.items: - self.add(item) - - def intersection_update(self, other): - """Update the set, removing any elements from other which are not - in both sets. - """ - - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - if self is other: # lgtm[py/comparison-using-is] - return - # we make a copy of the list so that we can remove items from - # the list without breaking the iterator. - for item in list(self.items): - if item not in other.items: - del self.items[item] - - def difference_update(self, other): - """Update the set, removing any elements from other which are in - the set. - """ - - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - if self is other: # lgtm[py/comparison-using-is] - self.items.clear() - else: - for item in other.items: - self.discard(item) - - def symmetric_difference_update(self, other): - """Update the set, retaining only elements unique to both sets.""" - - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - if self is other: # lgtm[py/comparison-using-is] - self.items.clear() - else: - overlap = self.intersection(other) - self.union_update(other) - self.difference_update(overlap) - - def union(self, other): - """Return a new set which is the union of ``self`` and ``other``. - - Returns the same Set type as this set. - """ - - obj = self._clone() - obj.union_update(other) - return obj - - def intersection(self, other): - """Return a new set which is the intersection of ``self`` and - ``other``. - - Returns the same Set type as this set. - """ - - obj = self._clone() - obj.intersection_update(other) - return obj - - def difference(self, other): - """Return a new set which ``self`` - ``other``, i.e. the items - in ``self`` which are not also in ``other``. - - Returns the same Set type as this set. - """ - - obj = self._clone() - obj.difference_update(other) - return obj - - def symmetric_difference(self, other): - """Return a new set which (``self`` - ``other``) | (``other`` - - ``self), ie: the items in either ``self`` or ``other`` which - are not contained in their intersection. - - Returns the same Set type as this set. - """ - - obj = self._clone() - obj.symmetric_difference_update(other) - return obj - - def __or__(self, other): - return self.union(other) - - def __and__(self, other): - return self.intersection(other) - - def __add__(self, other): - return self.union(other) - - def __sub__(self, other): - return self.difference(other) - - def __xor__(self, other): - return self.symmetric_difference(other) - - def __ior__(self, other): - self.union_update(other) - return self - - def __iand__(self, other): - self.intersection_update(other) - return self - - def __iadd__(self, other): - self.union_update(other) - return self - - def __isub__(self, other): - self.difference_update(other) - return self - - def __ixor__(self, other): - self.symmetric_difference_update(other) - return self - - def update(self, other): - """Update the set, adding any elements from other which are not - already in the set. - - *other*, the collection of items with which to update the set, which - may be any iterable type. - """ - - for item in other: - self.add(item) - - def clear(self): - """Make the set empty.""" - self.items.clear() - - def __eq__(self, other): - return self.items == other.items - - def __ne__(self, other): - return not self.__eq__(other) - - def __len__(self): - return len(self.items) - - def __iter__(self): - return iter(self.items) - - def __getitem__(self, i): - if isinstance(i, slice): - return list(itertools.islice(self.items, i.start, i.stop, i.step)) - else: - return next(itertools.islice(self.items, i, i + 1)) - - def __delitem__(self, i): - if isinstance(i, slice): - for elt in list(self[i]): - del self.items[elt] - else: - del self.items[self[i]] - - def issubset(self, other): - """Is this set a subset of *other*? - - Returns a ``bool``. - """ - - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - for item in self.items: - if item not in other.items: - return False - return True - - def issuperset(self, other): - """Is this set a superset of *other*? - - Returns a ``bool``. - """ - - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - for item in other.items: - if item not in self.items: - return False - return True - - def isdisjoint(self, other): - if not isinstance(other, Set): - raise ValueError("other must be a Set instance") - for item in other.items: - if item in self.items: - return False - return True diff --git a/venv/Lib/site-packages/dns/tokenizer.py b/venv/Lib/site-packages/dns/tokenizer.py deleted file mode 100644 index ab205bc..0000000 --- a/venv/Lib/site-packages/dns/tokenizer.py +++ /dev/null @@ -1,708 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""Tokenize DNS zone file format""" - -import io -import sys -from typing import Any, List, Optional, Tuple - -import dns.exception -import dns.name -import dns.ttl - -_DELIMITERS = {" ", "\t", "\n", ";", "(", ")", '"'} -_QUOTING_DELIMITERS = {'"'} - -EOF = 0 -EOL = 1 -WHITESPACE = 2 -IDENTIFIER = 3 -QUOTED_STRING = 4 -COMMENT = 5 -DELIMITER = 6 - - -class UngetBufferFull(dns.exception.DNSException): - """An attempt was made to unget a token when the unget buffer was full.""" - - -class Token: - """A DNS zone file format token. - - ttype: The token type - value: The token value - has_escape: Does the token value contain escapes? - """ - - def __init__( - self, - ttype: int, - value: Any = "", - has_escape: bool = False, - comment: Optional[str] = None, - ): - """Initialize a token instance.""" - - self.ttype = ttype - self.value = value - self.has_escape = has_escape - self.comment = comment - - def is_eof(self) -> bool: - return self.ttype == EOF - - def is_eol(self) -> bool: - return self.ttype == EOL - - def is_whitespace(self) -> bool: - return self.ttype == WHITESPACE - - def is_identifier(self) -> bool: - return self.ttype == IDENTIFIER - - def is_quoted_string(self) -> bool: - return self.ttype == QUOTED_STRING - - def is_comment(self) -> bool: - return self.ttype == COMMENT - - def is_delimiter(self) -> bool: # pragma: no cover (we don't return delimiters yet) - return self.ttype == DELIMITER - - def is_eol_or_eof(self) -> bool: - return self.ttype == EOL or self.ttype == EOF - - def __eq__(self, other): - if not isinstance(other, Token): - return False - return self.ttype == other.ttype and self.value == other.value - - def __ne__(self, other): - if not isinstance(other, Token): - return True - return self.ttype != other.ttype or self.value != other.value - - def __str__(self): - return '%d "%s"' % (self.ttype, self.value) - - def unescape(self) -> "Token": - if not self.has_escape: - return self - unescaped = "" - l = len(self.value) - i = 0 - while i < l: - c = self.value[i] - i += 1 - if c == "\\": - if i >= l: # pragma: no cover (can't happen via get()) - raise dns.exception.UnexpectedEnd - c = self.value[i] - i += 1 - if c.isdigit(): - if i >= l: - raise dns.exception.UnexpectedEnd - c2 = self.value[i] - i += 1 - if i >= l: - raise dns.exception.UnexpectedEnd - c3 = self.value[i] - i += 1 - if not (c2.isdigit() and c3.isdigit()): - raise dns.exception.SyntaxError - codepoint = int(c) * 100 + int(c2) * 10 + int(c3) - if codepoint > 255: - raise dns.exception.SyntaxError - c = chr(codepoint) - unescaped += c - return Token(self.ttype, unescaped) - - def unescape_to_bytes(self) -> "Token": - # We used to use unescape() for TXT-like records, but this - # caused problems as we'd process DNS escapes into Unicode code - # points instead of byte values, and then a to_text() of the - # processed data would not equal the original input. For - # example, \226 in the TXT record would have a to_text() of - # \195\162 because we applied UTF-8 encoding to Unicode code - # point 226. - # - # We now apply escapes while converting directly to bytes, - # avoiding this double encoding. - # - # This code also handles cases where the unicode input has - # non-ASCII code-points in it by converting it to UTF-8. TXT - # records aren't defined for Unicode, but this is the best we - # can do to preserve meaning. For example, - # - # foo\u200bbar - # - # (where \u200b is Unicode code point 0x200b) will be treated - # as if the input had been the UTF-8 encoding of that string, - # namely: - # - # foo\226\128\139bar - # - unescaped = b"" - l = len(self.value) - i = 0 - while i < l: - c = self.value[i] - i += 1 - if c == "\\": - if i >= l: # pragma: no cover (can't happen via get()) - raise dns.exception.UnexpectedEnd - c = self.value[i] - i += 1 - if c.isdigit(): - if i >= l: - raise dns.exception.UnexpectedEnd - c2 = self.value[i] - i += 1 - if i >= l: - raise dns.exception.UnexpectedEnd - c3 = self.value[i] - i += 1 - if not (c2.isdigit() and c3.isdigit()): - raise dns.exception.SyntaxError - codepoint = int(c) * 100 + int(c2) * 10 + int(c3) - if codepoint > 255: - raise dns.exception.SyntaxError - unescaped += b"%c" % (codepoint) - else: - # Note that as mentioned above, if c is a Unicode - # code point outside of the ASCII range, then this - # += is converting that code point to its UTF-8 - # encoding and appending multiple bytes to - # unescaped. - unescaped += c.encode() - else: - unescaped += c.encode() - return Token(self.ttype, bytes(unescaped)) - - -class Tokenizer: - """A DNS zone file format tokenizer. - - A token object is basically a (type, value) tuple. The valid - types are EOF, EOL, WHITESPACE, IDENTIFIER, QUOTED_STRING, - COMMENT, and DELIMITER. - - file: The file to tokenize - - ungotten_char: The most recently ungotten character, or None. - - ungotten_token: The most recently ungotten token, or None. - - multiline: The current multiline level. This value is increased - by one every time a '(' delimiter is read, and decreased by one every time - a ')' delimiter is read. - - quoting: This variable is true if the tokenizer is currently - reading a quoted string. - - eof: This variable is true if the tokenizer has encountered EOF. - - delimiters: The current delimiter dictionary. - - line_number: The current line number - - filename: A filename that will be returned by the where() method. - - idna_codec: A dns.name.IDNACodec, specifies the IDNA - encoder/decoder. If None, the default IDNA 2003 - encoder/decoder is used. - """ - - def __init__( - self, - f: Any = sys.stdin, - filename: Optional[str] = None, - idna_codec: Optional[dns.name.IDNACodec] = None, - ): - """Initialize a tokenizer instance. - - f: The file to tokenize. The default is sys.stdin. - This parameter may also be a string, in which case the tokenizer - will take its input from the contents of the string. - - filename: the name of the filename that the where() method - will return. - - idna_codec: A dns.name.IDNACodec, specifies the IDNA - encoder/decoder. If None, the default IDNA 2003 - encoder/decoder is used. - """ - - if isinstance(f, str): - f = io.StringIO(f) - if filename is None: - filename = "" - elif isinstance(f, bytes): - f = io.StringIO(f.decode()) - if filename is None: - filename = "" - else: - if filename is None: - if f is sys.stdin: - filename = "" - else: - filename = "" - self.file = f - self.ungotten_char: Optional[str] = None - self.ungotten_token: Optional[Token] = None - self.multiline = 0 - self.quoting = False - self.eof = False - self.delimiters = _DELIMITERS - self.line_number = 1 - assert filename is not None - self.filename = filename - if idna_codec is None: - self.idna_codec: dns.name.IDNACodec = dns.name.IDNA_2003 - else: - self.idna_codec = idna_codec - - def _get_char(self) -> str: - """Read a character from input.""" - - if self.ungotten_char is None: - if self.eof: - c = "" - else: - c = self.file.read(1) - if c == "": - self.eof = True - elif c == "\n": - self.line_number += 1 - else: - c = self.ungotten_char - self.ungotten_char = None - return c - - def where(self) -> Tuple[str, int]: - """Return the current location in the input. - - Returns a (string, int) tuple. The first item is the filename of - the input, the second is the current line number. - """ - - return (self.filename, self.line_number) - - def _unget_char(self, c: str) -> None: - """Unget a character. - - The unget buffer for characters is only one character large; it is - an error to try to unget a character when the unget buffer is not - empty. - - c: the character to unget - raises UngetBufferFull: there is already an ungotten char - """ - - if self.ungotten_char is not None: - # this should never happen! - raise UngetBufferFull # pragma: no cover - self.ungotten_char = c - - def skip_whitespace(self) -> int: - """Consume input until a non-whitespace character is encountered. - - The non-whitespace character is then ungotten, and the number of - whitespace characters consumed is returned. - - If the tokenizer is in multiline mode, then newlines are whitespace. - - Returns the number of characters skipped. - """ - - skipped = 0 - while True: - c = self._get_char() - if c != " " and c != "\t": - if (c != "\n") or not self.multiline: - self._unget_char(c) - return skipped - skipped += 1 - - def get(self, want_leading: bool = False, want_comment: bool = False) -> Token: - """Get the next token. - - want_leading: If True, return a WHITESPACE token if the - first character read is whitespace. The default is False. - - want_comment: If True, return a COMMENT token if the - first token read is a comment. The default is False. - - Raises dns.exception.UnexpectedEnd: input ended prematurely - - Raises dns.exception.SyntaxError: input was badly formed - - Returns a Token. - """ - - if self.ungotten_token is not None: - utoken = self.ungotten_token - self.ungotten_token = None - if utoken.is_whitespace(): - if want_leading: - return utoken - elif utoken.is_comment(): - if want_comment: - return utoken - else: - return utoken - skipped = self.skip_whitespace() - if want_leading and skipped > 0: - return Token(WHITESPACE, " ") - token = "" - ttype = IDENTIFIER - has_escape = False - while True: - c = self._get_char() - if c == "" or c in self.delimiters: - if c == "" and self.quoting: - raise dns.exception.UnexpectedEnd - if token == "" and ttype != QUOTED_STRING: - if c == "(": - self.multiline += 1 - self.skip_whitespace() - continue - elif c == ")": - if self.multiline <= 0: - raise dns.exception.SyntaxError - self.multiline -= 1 - self.skip_whitespace() - continue - elif c == '"': - if not self.quoting: - self.quoting = True - self.delimiters = _QUOTING_DELIMITERS - ttype = QUOTED_STRING - continue - else: - self.quoting = False - self.delimiters = _DELIMITERS - self.skip_whitespace() - continue - elif c == "\n": - return Token(EOL, "\n") - elif c == ";": - while 1: - c = self._get_char() - if c == "\n" or c == "": - break - token += c - if want_comment: - self._unget_char(c) - return Token(COMMENT, token) - elif c == "": - if self.multiline: - raise dns.exception.SyntaxError( - "unbalanced parentheses" - ) - return Token(EOF, comment=token) - elif self.multiline: - self.skip_whitespace() - token = "" - continue - else: - return Token(EOL, "\n", comment=token) - else: - # This code exists in case we ever want a - # delimiter to be returned. It never produces - # a token currently. - token = c - ttype = DELIMITER - else: - self._unget_char(c) - break - elif self.quoting and c == "\n": - raise dns.exception.SyntaxError("newline in quoted string") - elif c == "\\": - # - # It's an escape. Put it and the next character into - # the token; it will be checked later for goodness. - # - token += c - has_escape = True - c = self._get_char() - if c == "" or (c == "\n" and not self.quoting): - raise dns.exception.UnexpectedEnd - token += c - if token == "" and ttype != QUOTED_STRING: - if self.multiline: - raise dns.exception.SyntaxError("unbalanced parentheses") - ttype = EOF - return Token(ttype, token, has_escape) - - def unget(self, token: Token) -> None: - """Unget a token. - - The unget buffer for tokens is only one token large; it is - an error to try to unget a token when the unget buffer is not - empty. - - token: the token to unget - - Raises UngetBufferFull: there is already an ungotten token - """ - - if self.ungotten_token is not None: - raise UngetBufferFull - self.ungotten_token = token - - def next(self): - """Return the next item in an iteration. - - Returns a Token. - """ - - token = self.get() - if token.is_eof(): - raise StopIteration - return token - - __next__ = next - - def __iter__(self): - return self - - # Helpers - - def get_int(self, base: int = 10) -> int: - """Read the next token and interpret it as an unsigned integer. - - Raises dns.exception.SyntaxError if not an unsigned integer. - - Returns an int. - """ - - token = self.get().unescape() - if not token.is_identifier(): - raise dns.exception.SyntaxError("expecting an identifier") - if not token.value.isdigit(): - raise dns.exception.SyntaxError("expecting an integer") - return int(token.value, base) - - def get_uint8(self) -> int: - """Read the next token and interpret it as an 8-bit unsigned - integer. - - Raises dns.exception.SyntaxError if not an 8-bit unsigned integer. - - Returns an int. - """ - - value = self.get_int() - if value < 0 or value > 255: - raise dns.exception.SyntaxError( - "%d is not an unsigned 8-bit integer" % value - ) - return value - - def get_uint16(self, base: int = 10) -> int: - """Read the next token and interpret it as a 16-bit unsigned - integer. - - Raises dns.exception.SyntaxError if not a 16-bit unsigned integer. - - Returns an int. - """ - - value = self.get_int(base=base) - if value < 0 or value > 65535: - if base == 8: - raise dns.exception.SyntaxError( - f"{value:o} is not an octal unsigned 16-bit integer" - ) - else: - raise dns.exception.SyntaxError( - "%d is not an unsigned 16-bit integer" % value - ) - return value - - def get_uint32(self, base: int = 10) -> int: - """Read the next token and interpret it as a 32-bit unsigned - integer. - - Raises dns.exception.SyntaxError if not a 32-bit unsigned integer. - - Returns an int. - """ - - value = self.get_int(base=base) - if value < 0 or value > 4294967295: - raise dns.exception.SyntaxError( - "%d is not an unsigned 32-bit integer" % value - ) - return value - - def get_uint48(self, base: int = 10) -> int: - """Read the next token and interpret it as a 48-bit unsigned - integer. - - Raises dns.exception.SyntaxError if not a 48-bit unsigned integer. - - Returns an int. - """ - - value = self.get_int(base=base) - if value < 0 or value > 281474976710655: - raise dns.exception.SyntaxError( - "%d is not an unsigned 48-bit integer" % value - ) - return value - - def get_string(self, max_length: Optional[int] = None) -> str: - """Read the next token and interpret it as a string. - - Raises dns.exception.SyntaxError if not a string. - Raises dns.exception.SyntaxError if token value length - exceeds max_length (if specified). - - Returns a string. - """ - - token = self.get().unescape() - if not (token.is_identifier() or token.is_quoted_string()): - raise dns.exception.SyntaxError("expecting a string") - if max_length and len(token.value) > max_length: - raise dns.exception.SyntaxError("string too long") - return token.value - - def get_identifier(self) -> str: - """Read the next token, which should be an identifier. - - Raises dns.exception.SyntaxError if not an identifier. - - Returns a string. - """ - - token = self.get().unescape() - if not token.is_identifier(): - raise dns.exception.SyntaxError("expecting an identifier") - return token.value - - def get_remaining(self, max_tokens: Optional[int] = None) -> List[Token]: - """Return the remaining tokens on the line, until an EOL or EOF is seen. - - max_tokens: If not None, stop after this number of tokens. - - Returns a list of tokens. - """ - - tokens = [] - while True: - token = self.get() - if token.is_eol_or_eof(): - self.unget(token) - break - tokens.append(token) - if len(tokens) == max_tokens: - break - return tokens - - def concatenate_remaining_identifiers(self, allow_empty: bool = False) -> str: - """Read the remaining tokens on the line, which should be identifiers. - - Raises dns.exception.SyntaxError if there are no remaining tokens, - unless `allow_empty=True` is given. - - Raises dns.exception.SyntaxError if a token is seen that is not an - identifier. - - Returns a string containing a concatenation of the remaining - identifiers. - """ - s = "" - while True: - token = self.get().unescape() - if token.is_eol_or_eof(): - self.unget(token) - break - if not token.is_identifier(): - raise dns.exception.SyntaxError - s += token.value - if not (allow_empty or s): - raise dns.exception.SyntaxError("expecting another identifier") - return s - - def as_name( - self, - token: Token, - origin: Optional[dns.name.Name] = None, - relativize: bool = False, - relativize_to: Optional[dns.name.Name] = None, - ) -> dns.name.Name: - """Try to interpret the token as a DNS name. - - Raises dns.exception.SyntaxError if not a name. - - Returns a dns.name.Name. - """ - if not token.is_identifier(): - raise dns.exception.SyntaxError("expecting an identifier") - name = dns.name.from_text(token.value, origin, self.idna_codec) - return name.choose_relativity(relativize_to or origin, relativize) - - def get_name( - self, - origin: Optional[dns.name.Name] = None, - relativize: bool = False, - relativize_to: Optional[dns.name.Name] = None, - ) -> dns.name.Name: - """Read the next token and interpret it as a DNS name. - - Raises dns.exception.SyntaxError if not a name. - - Returns a dns.name.Name. - """ - - token = self.get() - return self.as_name(token, origin, relativize, relativize_to) - - def get_eol_as_token(self) -> Token: - """Read the next token and raise an exception if it isn't EOL or - EOF. - - Returns a string. - """ - - token = self.get() - if not token.is_eol_or_eof(): - raise dns.exception.SyntaxError( - 'expected EOL or EOF, got %d "%s"' % (token.ttype, token.value) - ) - return token - - def get_eol(self) -> str: - return self.get_eol_as_token().value - - def get_ttl(self) -> int: - """Read the next token and interpret it as a DNS TTL. - - Raises dns.exception.SyntaxError or dns.ttl.BadTTL if not an - identifier or badly formed. - - Returns an int. - """ - - token = self.get().unescape() - if not token.is_identifier(): - raise dns.exception.SyntaxError("expecting an identifier") - return dns.ttl.from_text(token.value) diff --git a/venv/Lib/site-packages/dns/transaction.py b/venv/Lib/site-packages/dns/transaction.py deleted file mode 100644 index aa2e116..0000000 --- a/venv/Lib/site-packages/dns/transaction.py +++ /dev/null @@ -1,649 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import collections -from typing import Any, Callable, Iterator, List, Optional, Tuple, Union - -import dns.exception -import dns.name -import dns.node -import dns.rdataclass -import dns.rdataset -import dns.rdatatype -import dns.rrset -import dns.serial -import dns.ttl - - -class TransactionManager: - def reader(self) -> "Transaction": - """Begin a read-only transaction.""" - raise NotImplementedError # pragma: no cover - - def writer(self, replacement: bool = False) -> "Transaction": - """Begin a writable transaction. - - *replacement*, a ``bool``. If `True`, the content of the - transaction completely replaces any prior content. If False, - the default, then the content of the transaction updates the - existing content. - """ - raise NotImplementedError # pragma: no cover - - def origin_information( - self, - ) -> Tuple[Optional[dns.name.Name], bool, Optional[dns.name.Name]]: - """Returns a tuple - - (absolute_origin, relativize, effective_origin) - - giving the absolute name of the default origin for any - relative domain names, the "effective origin", and whether - names should be relativized. The "effective origin" is the - absolute origin if relativize is False, and the empty name if - relativize is true. (The effective origin is provided even - though it can be computed from the absolute_origin and - relativize setting because it avoids a lot of code - duplication.) - - If the returned names are `None`, then no origin information is - available. - - This information is used by code working with transactions to - allow it to coordinate relativization. The transaction code - itself takes what it gets (i.e. does not change name - relativity). - - """ - raise NotImplementedError # pragma: no cover - - def get_class(self) -> dns.rdataclass.RdataClass: - """The class of the transaction manager.""" - raise NotImplementedError # pragma: no cover - - def from_wire_origin(self) -> Optional[dns.name.Name]: - """Origin to use in from_wire() calls.""" - (absolute_origin, relativize, _) = self.origin_information() - if relativize: - return absolute_origin - else: - return None - - -class DeleteNotExact(dns.exception.DNSException): - """Existing data did not match data specified by an exact delete.""" - - -class ReadOnly(dns.exception.DNSException): - """Tried to write to a read-only transaction.""" - - -class AlreadyEnded(dns.exception.DNSException): - """Tried to use an already-ended transaction.""" - - -def _ensure_immutable_rdataset(rdataset): - if rdataset is None or isinstance(rdataset, dns.rdataset.ImmutableRdataset): - return rdataset - return dns.rdataset.ImmutableRdataset(rdataset) - - -def _ensure_immutable_node(node): - if node is None or node.is_immutable(): - return node - return dns.node.ImmutableNode(node) - - -CheckPutRdatasetType = Callable[ - ["Transaction", dns.name.Name, dns.rdataset.Rdataset], None -] -CheckDeleteRdatasetType = Callable[ - ["Transaction", dns.name.Name, dns.rdatatype.RdataType, dns.rdatatype.RdataType], - None, -] -CheckDeleteNameType = Callable[["Transaction", dns.name.Name], None] - - -class Transaction: - def __init__( - self, - manager: TransactionManager, - replacement: bool = False, - read_only: bool = False, - ): - self.manager = manager - self.replacement = replacement - self.read_only = read_only - self._ended = False - self._check_put_rdataset: List[CheckPutRdatasetType] = [] - self._check_delete_rdataset: List[CheckDeleteRdatasetType] = [] - self._check_delete_name: List[CheckDeleteNameType] = [] - - # - # This is the high level API - # - # Note that we currently use non-immutable types in the return type signature to - # avoid covariance problems, e.g. if the caller has a List[Rdataset], mypy will be - # unhappy if we return an ImmutableRdataset. - - def get( - self, - name: Optional[Union[dns.name.Name, str]], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> dns.rdataset.Rdataset: - """Return the rdataset associated with *name*, *rdtype*, and *covers*, - or `None` if not found. - - Note that the returned rdataset is immutable. - """ - self._check_ended() - if isinstance(name, str): - name = dns.name.from_text(name, None) - rdtype = dns.rdatatype.RdataType.make(rdtype) - covers = dns.rdatatype.RdataType.make(covers) - rdataset = self._get_rdataset(name, rdtype, covers) - return _ensure_immutable_rdataset(rdataset) - - def get_node(self, name: dns.name.Name) -> Optional[dns.node.Node]: - """Return the node at *name*, if any. - - Returns an immutable node or ``None``. - """ - return _ensure_immutable_node(self._get_node(name)) - - def _check_read_only(self) -> None: - if self.read_only: - raise ReadOnly - - def add(self, *args: Any) -> None: - """Add records. - - The arguments may be: - - - rrset - - - name, rdataset... - - - name, ttl, rdata... - """ - self._check_ended() - self._check_read_only() - self._add(False, args) - - def replace(self, *args: Any) -> None: - """Replace the existing rdataset at the name with the specified - rdataset, or add the specified rdataset if there was no existing - rdataset. - - The arguments may be: - - - rrset - - - name, rdataset... - - - name, ttl, rdata... - - Note that if you want to replace the entire node, you should do - a delete of the name followed by one or more calls to add() or - replace(). - """ - self._check_ended() - self._check_read_only() - self._add(True, args) - - def delete(self, *args: Any) -> None: - """Delete records. - - It is not an error if some of the records are not in the existing - set. - - The arguments may be: - - - rrset - - - name - - - name, rdatatype, [covers] - - - name, rdataset... - - - name, rdata... - """ - self._check_ended() - self._check_read_only() - self._delete(False, args) - - def delete_exact(self, *args: Any) -> None: - """Delete records. - - The arguments may be: - - - rrset - - - name - - - name, rdatatype, [covers] - - - name, rdataset... - - - name, rdata... - - Raises dns.transaction.DeleteNotExact if some of the records - are not in the existing set. - - """ - self._check_ended() - self._check_read_only() - self._delete(True, args) - - def name_exists(self, name: Union[dns.name.Name, str]) -> bool: - """Does the specified name exist?""" - self._check_ended() - if isinstance(name, str): - name = dns.name.from_text(name, None) - return self._name_exists(name) - - def update_serial( - self, - value: int = 1, - relative: bool = True, - name: dns.name.Name = dns.name.empty, - ) -> None: - """Update the serial number. - - *value*, an `int`, is an increment if *relative* is `True`, or the - actual value to set if *relative* is `False`. - - Raises `KeyError` if there is no SOA rdataset at *name*. - - Raises `ValueError` if *value* is negative or if the increment is - so large that it would cause the new serial to be less than the - prior value. - """ - self._check_ended() - if value < 0: - raise ValueError("negative update_serial() value") - if isinstance(name, str): - name = dns.name.from_text(name, None) - rdataset = self._get_rdataset(name, dns.rdatatype.SOA, dns.rdatatype.NONE) - if rdataset is None or len(rdataset) == 0: - raise KeyError - if relative: - serial = dns.serial.Serial(rdataset[0].serial) + value - else: - serial = dns.serial.Serial(value) - serial = serial.value # convert back to int - if serial == 0: - serial = 1 - rdata = rdataset[0].replace(serial=serial) - new_rdataset = dns.rdataset.from_rdata(rdataset.ttl, rdata) - self.replace(name, new_rdataset) - - def __iter__(self): - self._check_ended() - return self._iterate_rdatasets() - - def changed(self) -> bool: - """Has this transaction changed anything? - - For read-only transactions, the result is always `False`. - - For writable transactions, the result is `True` if at some time - during the life of the transaction, the content was changed. - """ - self._check_ended() - return self._changed() - - def commit(self) -> None: - """Commit the transaction. - - Normally transactions are used as context managers and commit - or rollback automatically, but it may be done explicitly if needed. - A ``dns.transaction.Ended`` exception will be raised if you try - to use a transaction after it has been committed or rolled back. - - Raises an exception if the commit fails (in which case the transaction - is also rolled back. - """ - self._end(True) - - def rollback(self) -> None: - """Rollback the transaction. - - Normally transactions are used as context managers and commit - or rollback automatically, but it may be done explicitly if needed. - A ``dns.transaction.AlreadyEnded`` exception will be raised if you try - to use a transaction after it has been committed or rolled back. - - Rollback cannot otherwise fail. - """ - self._end(False) - - def check_put_rdataset(self, check: CheckPutRdatasetType) -> None: - """Call *check* before putting (storing) an rdataset. - - The function is called with the transaction, the name, and the rdataset. - - The check function may safely make non-mutating transaction method - calls, but behavior is undefined if mutating transaction methods are - called. The check function should raise an exception if it objects to - the put, and otherwise should return ``None``. - """ - self._check_put_rdataset.append(check) - - def check_delete_rdataset(self, check: CheckDeleteRdatasetType) -> None: - """Call *check* before deleting an rdataset. - - The function is called with the transaction, the name, the rdatatype, - and the covered rdatatype. - - The check function may safely make non-mutating transaction method - calls, but behavior is undefined if mutating transaction methods are - called. The check function should raise an exception if it objects to - the put, and otherwise should return ``None``. - """ - self._check_delete_rdataset.append(check) - - def check_delete_name(self, check: CheckDeleteNameType) -> None: - """Call *check* before putting (storing) an rdataset. - - The function is called with the transaction and the name. - - The check function may safely make non-mutating transaction method - calls, but behavior is undefined if mutating transaction methods are - called. The check function should raise an exception if it objects to - the put, and otherwise should return ``None``. - """ - self._check_delete_name.append(check) - - def iterate_rdatasets( - self, - ) -> Iterator[Tuple[dns.name.Name, dns.rdataset.Rdataset]]: - """Iterate all the rdatasets in the transaction, returning - (`dns.name.Name`, `dns.rdataset.Rdataset`) tuples. - - Note that as is usual with python iterators, adding or removing items - while iterating will invalidate the iterator and may raise `RuntimeError` - or fail to iterate over all entries.""" - self._check_ended() - return self._iterate_rdatasets() - - def iterate_names(self) -> Iterator[dns.name.Name]: - """Iterate all the names in the transaction. - - Note that as is usual with python iterators, adding or removing names - while iterating will invalidate the iterator and may raise `RuntimeError` - or fail to iterate over all entries.""" - self._check_ended() - return self._iterate_names() - - # - # Helper methods - # - - def _raise_if_not_empty(self, method, args): - if len(args) != 0: - raise TypeError(f"extra parameters to {method}") - - def _rdataset_from_args(self, method, deleting, args): - try: - arg = args.popleft() - if isinstance(arg, dns.rrset.RRset): - rdataset = arg.to_rdataset() - elif isinstance(arg, dns.rdataset.Rdataset): - rdataset = arg - else: - if deleting: - ttl = 0 - else: - if isinstance(arg, int): - ttl = arg - if ttl > dns.ttl.MAX_TTL: - raise ValueError(f"{method}: TTL value too big") - else: - raise TypeError(f"{method}: expected a TTL") - arg = args.popleft() - if isinstance(arg, dns.rdata.Rdata): - rdataset = dns.rdataset.from_rdata(ttl, arg) - else: - raise TypeError(f"{method}: expected an Rdata") - return rdataset - except IndexError: - if deleting: - return None - else: - # reraise - raise TypeError(f"{method}: expected more arguments") - - def _add(self, replace, args): - try: - args = collections.deque(args) - if replace: - method = "replace()" - else: - method = "add()" - arg = args.popleft() - if isinstance(arg, str): - arg = dns.name.from_text(arg, None) - if isinstance(arg, dns.name.Name): - name = arg - rdataset = self._rdataset_from_args(method, False, args) - elif isinstance(arg, dns.rrset.RRset): - rrset = arg - name = rrset.name - # rrsets are also rdatasets, but they don't print the - # same and can't be stored in nodes, so convert. - rdataset = rrset.to_rdataset() - else: - raise TypeError( - f"{method} requires a name or RRset as the first argument" - ) - if rdataset.rdclass != self.manager.get_class(): - raise ValueError(f"{method} has objects of wrong RdataClass") - if rdataset.rdtype == dns.rdatatype.SOA: - (_, _, origin) = self._origin_information() - if name != origin: - raise ValueError(f"{method} has non-origin SOA") - self._raise_if_not_empty(method, args) - if not replace: - existing = self._get_rdataset(name, rdataset.rdtype, rdataset.covers) - if existing is not None: - if isinstance(existing, dns.rdataset.ImmutableRdataset): - trds = dns.rdataset.Rdataset( - existing.rdclass, existing.rdtype, existing.covers - ) - trds.update(existing) - existing = trds - rdataset = existing.union(rdataset) - self._checked_put_rdataset(name, rdataset) - except IndexError: - raise TypeError(f"not enough parameters to {method}") - - def _delete(self, exact, args): - try: - args = collections.deque(args) - if exact: - method = "delete_exact()" - else: - method = "delete()" - arg = args.popleft() - if isinstance(arg, str): - arg = dns.name.from_text(arg, None) - if isinstance(arg, dns.name.Name): - name = arg - if len(args) > 0 and ( - isinstance(args[0], int) or isinstance(args[0], str) - ): - # deleting by type and (optionally) covers - rdtype = dns.rdatatype.RdataType.make(args.popleft()) - if len(args) > 0: - covers = dns.rdatatype.RdataType.make(args.popleft()) - else: - covers = dns.rdatatype.NONE - self._raise_if_not_empty(method, args) - existing = self._get_rdataset(name, rdtype, covers) - if existing is None: - if exact: - raise DeleteNotExact(f"{method}: missing rdataset") - else: - self._checked_delete_rdataset(name, rdtype, covers) - return - else: - rdataset = self._rdataset_from_args(method, True, args) - elif isinstance(arg, dns.rrset.RRset): - rdataset = arg # rrsets are also rdatasets - name = rdataset.name - else: - raise TypeError( - f"{method} requires a name or RRset as the first argument" - ) - self._raise_if_not_empty(method, args) - if rdataset: - if rdataset.rdclass != self.manager.get_class(): - raise ValueError(f"{method} has objects of wrong RdataClass") - existing = self._get_rdataset(name, rdataset.rdtype, rdataset.covers) - if existing is not None: - if exact: - intersection = existing.intersection(rdataset) - if intersection != rdataset: - raise DeleteNotExact(f"{method}: missing rdatas") - rdataset = existing.difference(rdataset) - if len(rdataset) == 0: - self._checked_delete_rdataset( - name, rdataset.rdtype, rdataset.covers - ) - else: - self._checked_put_rdataset(name, rdataset) - elif exact: - raise DeleteNotExact(f"{method}: missing rdataset") - else: - if exact and not self._name_exists(name): - raise DeleteNotExact(f"{method}: name not known") - self._checked_delete_name(name) - except IndexError: - raise TypeError(f"not enough parameters to {method}") - - def _check_ended(self): - if self._ended: - raise AlreadyEnded - - def _end(self, commit): - self._check_ended() - try: - self._end_transaction(commit) - finally: - self._ended = True - - def _checked_put_rdataset(self, name, rdataset): - for check in self._check_put_rdataset: - check(self, name, rdataset) - self._put_rdataset(name, rdataset) - - def _checked_delete_rdataset(self, name, rdtype, covers): - for check in self._check_delete_rdataset: - check(self, name, rdtype, covers) - self._delete_rdataset(name, rdtype, covers) - - def _checked_delete_name(self, name): - for check in self._check_delete_name: - check(self, name) - self._delete_name(name) - - # - # Transactions are context managers. - # - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if not self._ended: - if exc_type is None: - self.commit() - else: - self.rollback() - return False - - # - # This is the low level API, which must be implemented by subclasses - # of Transaction. - # - - def _get_rdataset(self, name, rdtype, covers): - """Return the rdataset associated with *name*, *rdtype*, and *covers*, - or `None` if not found. - """ - raise NotImplementedError # pragma: no cover - - def _put_rdataset(self, name, rdataset): - """Store the rdataset.""" - raise NotImplementedError # pragma: no cover - - def _delete_name(self, name): - """Delete all data associated with *name*. - - It is not an error if the name does not exist. - """ - raise NotImplementedError # pragma: no cover - - def _delete_rdataset(self, name, rdtype, covers): - """Delete all data associated with *name*, *rdtype*, and *covers*. - - It is not an error if the rdataset does not exist. - """ - raise NotImplementedError # pragma: no cover - - def _name_exists(self, name): - """Does name exist? - - Returns a bool. - """ - raise NotImplementedError # pragma: no cover - - def _changed(self): - """Has this transaction changed anything?""" - raise NotImplementedError # pragma: no cover - - def _end_transaction(self, commit): - """End the transaction. - - *commit*, a bool. If ``True``, commit the transaction, otherwise - roll it back. - - If committing and the commit fails, then roll back and raise an - exception. - """ - raise NotImplementedError # pragma: no cover - - def _set_origin(self, origin): - """Set the origin. - - This method is called when reading a possibly relativized - source, and an origin setting operation occurs (e.g. $ORIGIN - in a zone file). - """ - raise NotImplementedError # pragma: no cover - - def _iterate_rdatasets(self): - """Return an iterator that yields (name, rdataset) tuples.""" - raise NotImplementedError # pragma: no cover - - def _iterate_names(self): - """Return an iterator that yields a name.""" - raise NotImplementedError # pragma: no cover - - def _get_node(self, name): - """Return the node at *name*, if any. - - Returns a node or ``None``. - """ - raise NotImplementedError # pragma: no cover - - # - # Low-level API with a default implementation, in case a subclass needs - # to override. - # - - def _origin_information(self): - # This is only used by _add() - return self.manager.origin_information() diff --git a/venv/Lib/site-packages/dns/tsig.py b/venv/Lib/site-packages/dns/tsig.py deleted file mode 100644 index 780852e..0000000 --- a/venv/Lib/site-packages/dns/tsig.py +++ /dev/null @@ -1,352 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2001-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS TSIG support.""" - -import base64 -import hashlib -import hmac -import struct - -import dns.exception -import dns.name -import dns.rcode -import dns.rdataclass - - -class BadTime(dns.exception.DNSException): - """The current time is not within the TSIG's validity time.""" - - -class BadSignature(dns.exception.DNSException): - """The TSIG signature fails to verify.""" - - -class BadKey(dns.exception.DNSException): - """The TSIG record owner name does not match the key.""" - - -class BadAlgorithm(dns.exception.DNSException): - """The TSIG algorithm does not match the key.""" - - -class PeerError(dns.exception.DNSException): - """Base class for all TSIG errors generated by the remote peer""" - - -class PeerBadKey(PeerError): - """The peer didn't know the key we used""" - - -class PeerBadSignature(PeerError): - """The peer didn't like the signature we sent""" - - -class PeerBadTime(PeerError): - """The peer didn't like the time we sent""" - - -class PeerBadTruncation(PeerError): - """The peer didn't like amount of truncation in the TSIG we sent""" - - -# TSIG Algorithms - -HMAC_MD5 = dns.name.from_text("HMAC-MD5.SIG-ALG.REG.INT") -HMAC_SHA1 = dns.name.from_text("hmac-sha1") -HMAC_SHA224 = dns.name.from_text("hmac-sha224") -HMAC_SHA256 = dns.name.from_text("hmac-sha256") -HMAC_SHA256_128 = dns.name.from_text("hmac-sha256-128") -HMAC_SHA384 = dns.name.from_text("hmac-sha384") -HMAC_SHA384_192 = dns.name.from_text("hmac-sha384-192") -HMAC_SHA512 = dns.name.from_text("hmac-sha512") -HMAC_SHA512_256 = dns.name.from_text("hmac-sha512-256") -GSS_TSIG = dns.name.from_text("gss-tsig") - -default_algorithm = HMAC_SHA256 - -mac_sizes = { - HMAC_SHA1: 20, - HMAC_SHA224: 28, - HMAC_SHA256: 32, - HMAC_SHA256_128: 16, - HMAC_SHA384: 48, - HMAC_SHA384_192: 24, - HMAC_SHA512: 64, - HMAC_SHA512_256: 32, - HMAC_MD5: 16, - GSS_TSIG: 128, # This is what we assume to be the worst case! -} - - -class GSSTSig: - """ - GSS-TSIG TSIG implementation. This uses the GSS-API context established - in the TKEY message handshake to sign messages using GSS-API message - integrity codes, per the RFC. - - In order to avoid a direct GSSAPI dependency, the keyring holds a ref - to the GSSAPI object required, rather than the key itself. - """ - - def __init__(self, gssapi_context): - self.gssapi_context = gssapi_context - self.data = b"" - self.name = "gss-tsig" - - def update(self, data): - self.data += data - - def sign(self): - # defer to the GSSAPI function to sign - return self.gssapi_context.get_signature(self.data) - - def verify(self, expected): - try: - # defer to the GSSAPI function to verify - return self.gssapi_context.verify_signature(self.data, expected) - except Exception: - # note the usage of a bare exception - raise BadSignature - - -class GSSTSigAdapter: - def __init__(self, keyring): - self.keyring = keyring - - def __call__(self, message, keyname): - if keyname in self.keyring: - key = self.keyring[keyname] - if isinstance(key, Key) and key.algorithm == GSS_TSIG: - if message: - GSSTSigAdapter.parse_tkey_and_step(key, message, keyname) - return key - else: - return None - - @classmethod - def parse_tkey_and_step(cls, key, message, keyname): - # if the message is a TKEY type, absorb the key material - # into the context using step(); this is used to allow the - # client to complete the GSSAPI negotiation before attempting - # to verify the signed response to a TKEY message exchange - try: - rrset = message.find_rrset( - message.answer, keyname, dns.rdataclass.ANY, dns.rdatatype.TKEY - ) - if rrset: - token = rrset[0].key - gssapi_context = key.secret - return gssapi_context.step(token) - except KeyError: - pass - - -class HMACTSig: - """ - HMAC TSIG implementation. This uses the HMAC python module to handle the - sign/verify operations. - """ - - _hashes = { - HMAC_SHA1: hashlib.sha1, - HMAC_SHA224: hashlib.sha224, - HMAC_SHA256: hashlib.sha256, - HMAC_SHA256_128: (hashlib.sha256, 128), - HMAC_SHA384: hashlib.sha384, - HMAC_SHA384_192: (hashlib.sha384, 192), - HMAC_SHA512: hashlib.sha512, - HMAC_SHA512_256: (hashlib.sha512, 256), - HMAC_MD5: hashlib.md5, - } - - def __init__(self, key, algorithm): - try: - hashinfo = self._hashes[algorithm] - except KeyError: - raise NotImplementedError(f"TSIG algorithm {algorithm} is not supported") - - # create the HMAC context - if isinstance(hashinfo, tuple): - self.hmac_context = hmac.new(key, digestmod=hashinfo[0]) - self.size = hashinfo[1] - else: - self.hmac_context = hmac.new(key, digestmod=hashinfo) - self.size = None - self.name = self.hmac_context.name - if self.size: - self.name += f"-{self.size}" - - def update(self, data): - return self.hmac_context.update(data) - - def sign(self): - # defer to the HMAC digest() function for that digestmod - digest = self.hmac_context.digest() - if self.size: - digest = digest[: (self.size // 8)] - return digest - - def verify(self, expected): - # re-digest and compare the results - mac = self.sign() - if not hmac.compare_digest(mac, expected): - raise BadSignature - - -def _digest(wire, key, rdata, time=None, request_mac=None, ctx=None, multi=None): - """Return a context containing the TSIG rdata for the input parameters - @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object - @raises ValueError: I{other_data} is too long - @raises NotImplementedError: I{algorithm} is not supported - """ - - first = not (ctx and multi) - if first: - ctx = get_context(key) - if request_mac: - ctx.update(struct.pack("!H", len(request_mac))) - ctx.update(request_mac) - ctx.update(struct.pack("!H", rdata.original_id)) - ctx.update(wire[2:]) - if first: - ctx.update(key.name.to_digestable()) - ctx.update(struct.pack("!H", dns.rdataclass.ANY)) - ctx.update(struct.pack("!I", 0)) - if time is None: - time = rdata.time_signed - upper_time = (time >> 32) & 0xFFFF - lower_time = time & 0xFFFFFFFF - time_encoded = struct.pack("!HIH", upper_time, lower_time, rdata.fudge) - other_len = len(rdata.other) - if other_len > 65535: - raise ValueError("TSIG Other Data is > 65535 bytes") - if first: - ctx.update(key.algorithm.to_digestable() + time_encoded) - ctx.update(struct.pack("!HH", rdata.error, other_len) + rdata.other) - else: - ctx.update(time_encoded) - return ctx - - -def _maybe_start_digest(key, mac, multi): - """If this is the first message in a multi-message sequence, - start a new context. - @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object - """ - if multi: - ctx = get_context(key) - ctx.update(struct.pack("!H", len(mac))) - ctx.update(mac) - return ctx - else: - return None - - -def sign(wire, key, rdata, time=None, request_mac=None, ctx=None, multi=False): - """Return a (tsig_rdata, mac, ctx) tuple containing the HMAC TSIG rdata - for the input parameters, the HMAC MAC calculated by applying the - TSIG signature algorithm, and the TSIG digest context. - @rtype: (string, dns.tsig.HMACTSig or dns.tsig.GSSTSig object) - @raises ValueError: I{other_data} is too long - @raises NotImplementedError: I{algorithm} is not supported - """ - - ctx = _digest(wire, key, rdata, time, request_mac, ctx, multi) - mac = ctx.sign() - tsig = rdata.replace(time_signed=time, mac=mac) - - return (tsig, _maybe_start_digest(key, mac, multi)) - - -def validate( - wire, key, owner, rdata, now, request_mac, tsig_start, ctx=None, multi=False -): - """Validate the specified TSIG rdata against the other input parameters. - - @raises FormError: The TSIG is badly formed. - @raises BadTime: There is too much time skew between the client and the - server. - @raises BadSignature: The TSIG signature did not validate - @rtype: dns.tsig.HMACTSig or dns.tsig.GSSTSig object""" - - (adcount,) = struct.unpack("!H", wire[10:12]) - if adcount == 0: - raise dns.exception.FormError - adcount -= 1 - new_wire = wire[0:10] + struct.pack("!H", adcount) + wire[12:tsig_start] - if rdata.error != 0: - if rdata.error == dns.rcode.BADSIG: - raise PeerBadSignature - elif rdata.error == dns.rcode.BADKEY: - raise PeerBadKey - elif rdata.error == dns.rcode.BADTIME: - raise PeerBadTime - elif rdata.error == dns.rcode.BADTRUNC: - raise PeerBadTruncation - else: - raise PeerError("unknown TSIG error code %d" % rdata.error) - if abs(rdata.time_signed - now) > rdata.fudge: - raise BadTime - if key.name != owner: - raise BadKey - if key.algorithm != rdata.algorithm: - raise BadAlgorithm - ctx = _digest(new_wire, key, rdata, None, request_mac, ctx, multi) - ctx.verify(rdata.mac) - return _maybe_start_digest(key, rdata.mac, multi) - - -def get_context(key): - """Returns an HMAC context for the specified key. - - @rtype: HMAC context - @raises NotImplementedError: I{algorithm} is not supported - """ - - if key.algorithm == GSS_TSIG: - return GSSTSig(key.secret) - else: - return HMACTSig(key.secret, key.algorithm) - - -class Key: - def __init__(self, name, secret, algorithm=default_algorithm): - if isinstance(name, str): - name = dns.name.from_text(name) - self.name = name - if isinstance(secret, str): - secret = base64.decodebytes(secret.encode()) - self.secret = secret - if isinstance(algorithm, str): - algorithm = dns.name.from_text(algorithm) - self.algorithm = algorithm - - def __eq__(self, other): - return ( - isinstance(other, Key) - and self.name == other.name - and self.secret == other.secret - and self.algorithm == other.algorithm - ) - - def __repr__(self): - r = f" Dict[dns.name.Name, dns.tsig.Key]: - """Convert a dictionary containing (textual DNS name, base64 secret) - pairs into a binary keyring which has (dns.name.Name, bytes) pairs, or - a dictionary containing (textual DNS name, (algorithm, base64 secret)) - pairs into a binary keyring which has (dns.name.Name, dns.tsig.Key) pairs. - @rtype: dict""" - - keyring = {} - for name, value in textring.items(): - kname = dns.name.from_text(name) - if isinstance(value, str): - keyring[kname] = dns.tsig.Key(kname, value).secret - else: - (algorithm, secret) = value - keyring[kname] = dns.tsig.Key(kname, secret, algorithm) - return keyring - - -def to_text(keyring: Dict[dns.name.Name, Any]) -> Dict[str, Any]: - """Convert a dictionary containing (dns.name.Name, dns.tsig.Key) pairs - into a text keyring which has (textual DNS name, (textual algorithm, - base64 secret)) pairs, or a dictionary containing (dns.name.Name, bytes) - pairs into a text keyring which has (textual DNS name, base64 secret) pairs. - @rtype: dict""" - - textring = {} - - def b64encode(secret): - return base64.encodebytes(secret).decode().rstrip() - - for name, key in keyring.items(): - tname = name.to_text() - if isinstance(key, bytes): - textring[tname] = b64encode(key) - else: - if isinstance(key.secret, bytes): - text_secret = b64encode(key.secret) - else: - text_secret = str(key.secret) - - textring[tname] = (key.algorithm.to_text(), text_secret) - return textring diff --git a/venv/Lib/site-packages/dns/ttl.py b/venv/Lib/site-packages/dns/ttl.py deleted file mode 100644 index b9a99fe..0000000 --- a/venv/Lib/site-packages/dns/ttl.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS TTL conversion.""" - -from typing import Union - -import dns.exception - -# Technically TTLs are supposed to be between 0 and 2**31 - 1, with values -# greater than that interpreted as 0, but we do not impose this policy here -# as values > 2**31 - 1 occur in real world data. -# -# We leave it to applications to impose tighter bounds if desired. -MAX_TTL = 2**32 - 1 - - -class BadTTL(dns.exception.SyntaxError): - """DNS TTL value is not well-formed.""" - - -def from_text(text: str) -> int: - """Convert the text form of a TTL to an integer. - - The BIND 8 units syntax for TTLs (e.g. '1w6d4h3m10s') is supported. - - *text*, a ``str``, the textual TTL. - - Raises ``dns.ttl.BadTTL`` if the TTL is not well-formed. - - Returns an ``int``. - """ - - if text.isdigit(): - total = int(text) - elif len(text) == 0: - raise BadTTL - else: - total = 0 - current = 0 - need_digit = True - for c in text: - if c.isdigit(): - current *= 10 - current += int(c) - need_digit = False - else: - if need_digit: - raise BadTTL - c = c.lower() - if c == "w": - total += current * 604800 - elif c == "d": - total += current * 86400 - elif c == "h": - total += current * 3600 - elif c == "m": - total += current * 60 - elif c == "s": - total += current - else: - raise BadTTL(f"unknown unit '{c}'") - current = 0 - need_digit = True - if not current == 0: - raise BadTTL("trailing integer") - if total < 0 or total > MAX_TTL: - raise BadTTL("TTL should be between 0 and 2**32 - 1 (inclusive)") - return total - - -def make(value: Union[int, str]) -> int: - if isinstance(value, int): - return value - elif isinstance(value, str): - return dns.ttl.from_text(value) - else: - raise ValueError("cannot convert value to TTL") diff --git a/venv/Lib/site-packages/dns/update.py b/venv/Lib/site-packages/dns/update.py deleted file mode 100644 index bf1157a..0000000 --- a/venv/Lib/site-packages/dns/update.py +++ /dev/null @@ -1,386 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Dynamic Update Support""" - -from typing import Any, List, Optional, Union - -import dns.message -import dns.name -import dns.opcode -import dns.rdata -import dns.rdataclass -import dns.rdataset -import dns.rdatatype -import dns.tsig - - -class UpdateSection(dns.enum.IntEnum): - """Update sections""" - - ZONE = 0 - PREREQ = 1 - UPDATE = 2 - ADDITIONAL = 3 - - @classmethod - def _maximum(cls): - return 3 - - -class UpdateMessage(dns.message.Message): # lgtm[py/missing-equals] - # ignore the mypy error here as we mean to use a different enum - _section_enum = UpdateSection # type: ignore - - def __init__( - self, - zone: Optional[Union[dns.name.Name, str]] = None, - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - keyring: Optional[Any] = None, - keyname: Optional[dns.name.Name] = None, - keyalgorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm, - id: Optional[int] = None, - ): - """Initialize a new DNS Update object. - - See the documentation of the Message class for a complete - description of the keyring dictionary. - - *zone*, a ``dns.name.Name``, ``str``, or ``None``, the zone - which is being updated. ``None`` should only be used by dnspython's - message constructors, as a zone is required for the convenience - methods like ``add()``, ``replace()``, etc. - - *rdclass*, an ``int`` or ``str``, the class of the zone. - - The *keyring*, *keyname*, and *keyalgorithm* parameters are passed to - ``use_tsig()``; see its documentation for details. - """ - super().__init__(id=id) - self.flags |= dns.opcode.to_flags(dns.opcode.UPDATE) - if isinstance(zone, str): - zone = dns.name.from_text(zone) - self.origin = zone - rdclass = dns.rdataclass.RdataClass.make(rdclass) - self.zone_rdclass = rdclass - if self.origin: - self.find_rrset( - self.zone, - self.origin, - rdclass, - dns.rdatatype.SOA, - create=True, - force_unique=True, - ) - if keyring is not None: - self.use_tsig(keyring, keyname, algorithm=keyalgorithm) - - @property - def zone(self) -> List[dns.rrset.RRset]: - """The zone section.""" - return self.sections[0] - - @zone.setter - def zone(self, v): - self.sections[0] = v - - @property - def prerequisite(self) -> List[dns.rrset.RRset]: - """The prerequisite section.""" - return self.sections[1] - - @prerequisite.setter - def prerequisite(self, v): - self.sections[1] = v - - @property - def update(self) -> List[dns.rrset.RRset]: - """The update section.""" - return self.sections[2] - - @update.setter - def update(self, v): - self.sections[2] = v - - def _add_rr(self, name, ttl, rd, deleting=None, section=None): - """Add a single RR to the update section.""" - - if section is None: - section = self.update - covers = rd.covers() - rrset = self.find_rrset( - section, name, self.zone_rdclass, rd.rdtype, covers, deleting, True, True - ) - rrset.add(rd, ttl) - - def _add(self, replace, section, name, *args): - """Add records. - - *replace* is the replacement mode. If ``False``, - RRs are added to an existing RRset; if ``True``, the RRset - is replaced with the specified contents. The second - argument is the section to add to. The third argument - is always a name. The other arguments can be: - - - rdataset... - - - ttl, rdata... - - - ttl, rdtype, string... - """ - - if isinstance(name, str): - name = dns.name.from_text(name, None) - if isinstance(args[0], dns.rdataset.Rdataset): - for rds in args: - if replace: - self.delete(name, rds.rdtype) - for rd in rds: - self._add_rr(name, rds.ttl, rd, section=section) - else: - args = list(args) - ttl = int(args.pop(0)) - if isinstance(args[0], dns.rdata.Rdata): - if replace: - self.delete(name, args[0].rdtype) - for rd in args: - self._add_rr(name, ttl, rd, section=section) - else: - rdtype = dns.rdatatype.RdataType.make(args.pop(0)) - if replace: - self.delete(name, rdtype) - for s in args: - rd = dns.rdata.from_text(self.zone_rdclass, rdtype, s, self.origin) - self._add_rr(name, ttl, rd, section=section) - - def add(self, name: Union[dns.name.Name, str], *args: Any) -> None: - """Add records. - - The first argument is always a name. The other - arguments can be: - - - rdataset... - - - ttl, rdata... - - - ttl, rdtype, string... - """ - - self._add(False, self.update, name, *args) - - def delete(self, name: Union[dns.name.Name, str], *args: Any) -> None: - """Delete records. - - The first argument is always a name. The other - arguments can be: - - - *empty* - - - rdataset... - - - rdata... - - - rdtype, [string...] - """ - - if isinstance(name, str): - name = dns.name.from_text(name, None) - if len(args) == 0: - self.find_rrset( - self.update, - name, - dns.rdataclass.ANY, - dns.rdatatype.ANY, - dns.rdatatype.NONE, - dns.rdataclass.ANY, - True, - True, - ) - elif isinstance(args[0], dns.rdataset.Rdataset): - for rds in args: - for rd in rds: - self._add_rr(name, 0, rd, dns.rdataclass.NONE) - else: - largs = list(args) - if isinstance(largs[0], dns.rdata.Rdata): - for rd in largs: - self._add_rr(name, 0, rd, dns.rdataclass.NONE) - else: - rdtype = dns.rdatatype.RdataType.make(largs.pop(0)) - if len(largs) == 0: - self.find_rrset( - self.update, - name, - self.zone_rdclass, - rdtype, - dns.rdatatype.NONE, - dns.rdataclass.ANY, - True, - True, - ) - else: - for s in largs: - rd = dns.rdata.from_text( - self.zone_rdclass, - rdtype, - s, # type: ignore[arg-type] - self.origin, - ) - self._add_rr(name, 0, rd, dns.rdataclass.NONE) - - def replace(self, name: Union[dns.name.Name, str], *args: Any) -> None: - """Replace records. - - The first argument is always a name. The other - arguments can be: - - - rdataset... - - - ttl, rdata... - - - ttl, rdtype, string... - - Note that if you want to replace the entire node, you should do - a delete of the name followed by one or more calls to add. - """ - - self._add(True, self.update, name, *args) - - def present(self, name: Union[dns.name.Name, str], *args: Any) -> None: - """Require that an owner name (and optionally an rdata type, - or specific rdataset) exists as a prerequisite to the - execution of the update. - - The first argument is always a name. - The other arguments can be: - - - rdataset... - - - rdata... - - - rdtype, string... - """ - - if isinstance(name, str): - name = dns.name.from_text(name, None) - if len(args) == 0: - self.find_rrset( - self.prerequisite, - name, - dns.rdataclass.ANY, - dns.rdatatype.ANY, - dns.rdatatype.NONE, - None, - True, - True, - ) - elif ( - isinstance(args[0], dns.rdataset.Rdataset) - or isinstance(args[0], dns.rdata.Rdata) - or len(args) > 1 - ): - if not isinstance(args[0], dns.rdataset.Rdataset): - # Add a 0 TTL - largs = list(args) - largs.insert(0, 0) # type: ignore[arg-type] - self._add(False, self.prerequisite, name, *largs) - else: - self._add(False, self.prerequisite, name, *args) - else: - rdtype = dns.rdatatype.RdataType.make(args[0]) - self.find_rrset( - self.prerequisite, - name, - dns.rdataclass.ANY, - rdtype, - dns.rdatatype.NONE, - None, - True, - True, - ) - - def absent( - self, - name: Union[dns.name.Name, str], - rdtype: Optional[Union[dns.rdatatype.RdataType, str]] = None, - ) -> None: - """Require that an owner name (and optionally an rdata type) does - not exist as a prerequisite to the execution of the update.""" - - if isinstance(name, str): - name = dns.name.from_text(name, None) - if rdtype is None: - self.find_rrset( - self.prerequisite, - name, - dns.rdataclass.NONE, - dns.rdatatype.ANY, - dns.rdatatype.NONE, - None, - True, - True, - ) - else: - rdtype = dns.rdatatype.RdataType.make(rdtype) - self.find_rrset( - self.prerequisite, - name, - dns.rdataclass.NONE, - rdtype, - dns.rdatatype.NONE, - None, - True, - True, - ) - - def _get_one_rr_per_rrset(self, value): - # Updates are always one_rr_per_rrset - return True - - def _parse_rr_header(self, section, name, rdclass, rdtype): - deleting = None - empty = False - if section == UpdateSection.ZONE: - if ( - dns.rdataclass.is_metaclass(rdclass) - or rdtype != dns.rdatatype.SOA - or self.zone - ): - raise dns.exception.FormError - else: - if not self.zone: - raise dns.exception.FormError - if rdclass in (dns.rdataclass.ANY, dns.rdataclass.NONE): - deleting = rdclass - rdclass = self.zone[0].rdclass - empty = ( - deleting == dns.rdataclass.ANY or section == UpdateSection.PREREQ - ) - return (rdclass, rdtype, deleting, empty) - - -# backwards compatibility -Update = UpdateMessage - -### BEGIN generated UpdateSection constants - -ZONE = UpdateSection.ZONE -PREREQ = UpdateSection.PREREQ -UPDATE = UpdateSection.UPDATE -ADDITIONAL = UpdateSection.ADDITIONAL - -### END generated UpdateSection constants diff --git a/venv/Lib/site-packages/dns/version.py b/venv/Lib/site-packages/dns/version.py deleted file mode 100644 index 9ed2ce1..0000000 --- a/venv/Lib/site-packages/dns/version.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""dnspython release version information.""" - -#: MAJOR -MAJOR = 2 -#: MINOR -MINOR = 7 -#: MICRO -MICRO = 0 -#: RELEASELEVEL -RELEASELEVEL = 0x0F -#: SERIAL -SERIAL = 0 - -if RELEASELEVEL == 0x0F: # pragma: no cover lgtm[py/unreachable-statement] - #: version - version = "%d.%d.%d" % (MAJOR, MINOR, MICRO) # lgtm[py/unreachable-statement] -elif RELEASELEVEL == 0x00: # pragma: no cover lgtm[py/unreachable-statement] - version = "%d.%d.%ddev%d" % ( - MAJOR, - MINOR, - MICRO, - SERIAL, - ) # lgtm[py/unreachable-statement] -elif RELEASELEVEL == 0x0C: # pragma: no cover lgtm[py/unreachable-statement] - version = "%d.%d.%drc%d" % ( - MAJOR, - MINOR, - MICRO, - SERIAL, - ) # lgtm[py/unreachable-statement] -else: # pragma: no cover lgtm[py/unreachable-statement] - version = "%d.%d.%d%x%d" % ( - MAJOR, - MINOR, - MICRO, - RELEASELEVEL, - SERIAL, - ) # lgtm[py/unreachable-statement] - -#: hexversion -hexversion = MAJOR << 24 | MINOR << 16 | MICRO << 8 | RELEASELEVEL << 4 | SERIAL diff --git a/venv/Lib/site-packages/dns/versioned.py b/venv/Lib/site-packages/dns/versioned.py deleted file mode 100644 index fd78e67..0000000 --- a/venv/Lib/site-packages/dns/versioned.py +++ /dev/null @@ -1,318 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -"""DNS Versioned Zones.""" - -import collections -import threading -from typing import Callable, Deque, Optional, Set, Union - -import dns.exception -import dns.immutable -import dns.name -import dns.node -import dns.rdataclass -import dns.rdataset -import dns.rdatatype -import dns.rdtypes.ANY.SOA -import dns.zone - - -class UseTransaction(dns.exception.DNSException): - """To alter a versioned zone, use a transaction.""" - - -# Backwards compatibility -Node = dns.zone.VersionedNode -ImmutableNode = dns.zone.ImmutableVersionedNode -Version = dns.zone.Version -WritableVersion = dns.zone.WritableVersion -ImmutableVersion = dns.zone.ImmutableVersion -Transaction = dns.zone.Transaction - - -class Zone(dns.zone.Zone): # lgtm[py/missing-equals] - __slots__ = [ - "_versions", - "_versions_lock", - "_write_txn", - "_write_waiters", - "_write_event", - "_pruning_policy", - "_readers", - ] - - node_factory = Node - - def __init__( - self, - origin: Optional[Union[dns.name.Name, str]], - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - relativize: bool = True, - pruning_policy: Optional[Callable[["Zone", Version], Optional[bool]]] = None, - ): - """Initialize a versioned zone object. - - *origin* is the origin of the zone. It may be a ``dns.name.Name``, - a ``str``, or ``None``. If ``None``, then the zone's origin will - be set by the first ``$ORIGIN`` line in a zone file. - - *rdclass*, an ``int``, the zone's rdata class; the default is class IN. - - *relativize*, a ``bool``, determine's whether domain names are - relativized to the zone's origin. The default is ``True``. - - *pruning policy*, a function taking a ``Zone`` and a ``Version`` and returning - a ``bool``, or ``None``. Should the version be pruned? If ``None``, - the default policy, which retains one version is used. - """ - super().__init__(origin, rdclass, relativize) - self._versions: Deque[Version] = collections.deque() - self._version_lock = threading.Lock() - if pruning_policy is None: - self._pruning_policy = self._default_pruning_policy - else: - self._pruning_policy = pruning_policy - self._write_txn: Optional[Transaction] = None - self._write_event: Optional[threading.Event] = None - self._write_waiters: Deque[threading.Event] = collections.deque() - self._readers: Set[Transaction] = set() - self._commit_version_unlocked( - None, WritableVersion(self, replacement=True), origin - ) - - def reader( - self, id: Optional[int] = None, serial: Optional[int] = None - ) -> Transaction: # pylint: disable=arguments-differ - if id is not None and serial is not None: - raise ValueError("cannot specify both id and serial") - with self._version_lock: - if id is not None: - version = None - for v in reversed(self._versions): - if v.id == id: - version = v - break - if version is None: - raise KeyError("version not found") - elif serial is not None: - if self.relativize: - oname = dns.name.empty - else: - assert self.origin is not None - oname = self.origin - version = None - for v in reversed(self._versions): - n = v.nodes.get(oname) - if n: - rds = n.get_rdataset(self.rdclass, dns.rdatatype.SOA) - if rds and rds[0].serial == serial: - version = v - break - if version is None: - raise KeyError("serial not found") - else: - version = self._versions[-1] - txn = Transaction(self, False, version) - self._readers.add(txn) - return txn - - def writer(self, replacement: bool = False) -> Transaction: - event = None - while True: - with self._version_lock: - # Checking event == self._write_event ensures that either - # no one was waiting before we got lucky and found no write - # txn, or we were the one who was waiting and got woken up. - # This prevents "taking cuts" when creating a write txn. - if self._write_txn is None and event == self._write_event: - # Creating the transaction defers version setup - # (i.e. copying the nodes dictionary) until we - # give up the lock, so that we hold the lock as - # short a time as possible. This is why we call - # _setup_version() below. - self._write_txn = Transaction( - self, replacement, make_immutable=True - ) - # give up our exclusive right to make a Transaction - self._write_event = None - break - # Someone else is writing already, so we will have to - # wait, but we want to do the actual wait outside the - # lock. - event = threading.Event() - self._write_waiters.append(event) - # wait (note we gave up the lock!) - # - # We only wake one sleeper at a time, so it's important - # that no event waiter can exit this method (e.g. via - # cancellation) without returning a transaction or waking - # someone else up. - # - # This is not a problem with Threading module threads as - # they cannot be canceled, but could be an issue with trio - # tasks when we do the async version of writer(). - # I.e. we'd need to do something like: - # - # try: - # event.wait() - # except trio.Cancelled: - # with self._version_lock: - # self._maybe_wakeup_one_waiter_unlocked() - # raise - # - event.wait() - # Do the deferred version setup. - self._write_txn._setup_version() - return self._write_txn - - def _maybe_wakeup_one_waiter_unlocked(self): - if len(self._write_waiters) > 0: - self._write_event = self._write_waiters.popleft() - self._write_event.set() - - # pylint: disable=unused-argument - def _default_pruning_policy(self, zone, version): - return True - - # pylint: enable=unused-argument - - def _prune_versions_unlocked(self): - assert len(self._versions) > 0 - # Don't ever prune a version greater than or equal to one that - # a reader has open. This pins versions in memory while the - # reader is open, and importantly lets the reader open a txn on - # a successor version (e.g. if generating an IXFR). - # - # Note our definition of least_kept also ensures we do not try to - # delete the greatest version. - if len(self._readers) > 0: - least_kept = min(txn.version.id for txn in self._readers) - else: - least_kept = self._versions[-1].id - while self._versions[0].id < least_kept and self._pruning_policy( - self, self._versions[0] - ): - self._versions.popleft() - - def set_max_versions(self, max_versions: Optional[int]) -> None: - """Set a pruning policy that retains up to the specified number - of versions - """ - if max_versions is not None and max_versions < 1: - raise ValueError("max versions must be at least 1") - if max_versions is None: - - def policy(zone, _): # pylint: disable=unused-argument - return False - - else: - - def policy(zone, _): - return len(zone._versions) > max_versions - - self.set_pruning_policy(policy) - - def set_pruning_policy( - self, policy: Optional[Callable[["Zone", Version], Optional[bool]]] - ) -> None: - """Set the pruning policy for the zone. - - The *policy* function takes a `Version` and returns `True` if - the version should be pruned, and `False` otherwise. `None` - may also be specified for policy, in which case the default policy - is used. - - Pruning checking proceeds from the least version and the first - time the function returns `False`, the checking stops. I.e. the - retained versions are always a consecutive sequence. - """ - if policy is None: - policy = self._default_pruning_policy - with self._version_lock: - self._pruning_policy = policy - self._prune_versions_unlocked() - - def _end_read(self, txn): - with self._version_lock: - self._readers.remove(txn) - self._prune_versions_unlocked() - - def _end_write_unlocked(self, txn): - assert self._write_txn == txn - self._write_txn = None - self._maybe_wakeup_one_waiter_unlocked() - - def _end_write(self, txn): - with self._version_lock: - self._end_write_unlocked(txn) - - def _commit_version_unlocked(self, txn, version, origin): - self._versions.append(version) - self._prune_versions_unlocked() - self.nodes = version.nodes - if self.origin is None: - self.origin = origin - # txn can be None in __init__ when we make the empty version. - if txn is not None: - self._end_write_unlocked(txn) - - def _commit_version(self, txn, version, origin): - with self._version_lock: - self._commit_version_unlocked(txn, version, origin) - - def _get_next_version_id(self): - if len(self._versions) > 0: - id = self._versions[-1].id + 1 - else: - id = 1 - return id - - def find_node( - self, name: Union[dns.name.Name, str], create: bool = False - ) -> dns.node.Node: - if create: - raise UseTransaction - return super().find_node(name) - - def delete_node(self, name: Union[dns.name.Name, str]) -> None: - raise UseTransaction - - def find_rdataset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - create: bool = False, - ) -> dns.rdataset.Rdataset: - if create: - raise UseTransaction - rdataset = super().find_rdataset(name, rdtype, covers) - return dns.rdataset.ImmutableRdataset(rdataset) - - def get_rdataset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - create: bool = False, - ) -> Optional[dns.rdataset.Rdataset]: - if create: - raise UseTransaction - rdataset = super().get_rdataset(name, rdtype, covers) - if rdataset is not None: - return dns.rdataset.ImmutableRdataset(rdataset) - else: - return None - - def delete_rdataset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> None: - raise UseTransaction - - def replace_rdataset( - self, name: Union[dns.name.Name, str], replacement: dns.rdataset.Rdataset - ) -> None: - raise UseTransaction diff --git a/venv/Lib/site-packages/dns/win32util.py b/venv/Lib/site-packages/dns/win32util.py deleted file mode 100644 index 9ed3f11..0000000 --- a/venv/Lib/site-packages/dns/win32util.py +++ /dev/null @@ -1,242 +0,0 @@ -import sys - -import dns._features - -if sys.platform == "win32": - from typing import Any - - import dns.name - - _prefer_wmi = True - - import winreg # pylint: disable=import-error - - # Keep pylint quiet on non-windows. - try: - _ = WindowsError # pylint: disable=used-before-assignment - except NameError: - WindowsError = Exception - - if dns._features.have("wmi"): - import threading - - import pythoncom # pylint: disable=import-error - import wmi # pylint: disable=import-error - - _have_wmi = True - else: - _have_wmi = False - - def _config_domain(domain): - # Sometimes DHCP servers add a '.' prefix to the default domain, and - # Windows just stores such values in the registry (see #687). - # Check for this and fix it. - if domain.startswith("."): - domain = domain[1:] - return dns.name.from_text(domain) - - class DnsInfo: - def __init__(self): - self.domain = None - self.nameservers = [] - self.search = [] - - if _have_wmi: - - class _WMIGetter(threading.Thread): - # pylint: disable=possibly-used-before-assignment - def __init__(self): - super().__init__() - self.info = DnsInfo() - - def run(self): - pythoncom.CoInitialize() - try: - system = wmi.WMI() - for interface in system.Win32_NetworkAdapterConfiguration(): - if interface.IPEnabled and interface.DNSServerSearchOrder: - self.info.nameservers = list(interface.DNSServerSearchOrder) - if interface.DNSDomain: - self.info.domain = _config_domain(interface.DNSDomain) - if interface.DNSDomainSuffixSearchOrder: - self.info.search = [ - _config_domain(x) - for x in interface.DNSDomainSuffixSearchOrder - ] - break - finally: - pythoncom.CoUninitialize() - - def get(self): - # We always run in a separate thread to avoid any issues with - # the COM threading model. - self.start() - self.join() - return self.info - - else: - - class _WMIGetter: # type: ignore - pass - - class _RegistryGetter: - def __init__(self): - self.info = DnsInfo() - - def _split(self, text): - # The windows registry has used both " " and "," as a delimiter, and while - # it is currently using "," in Windows 10 and later, updates can seemingly - # leave a space in too, e.g. "a, b". So we just convert all commas to - # spaces, and use split() in its default configuration, which splits on - # all whitespace and ignores empty strings. - return text.replace(",", " ").split() - - def _config_nameservers(self, nameservers): - for ns in self._split(nameservers): - if ns not in self.info.nameservers: - self.info.nameservers.append(ns) - - def _config_search(self, search): - for s in self._split(search): - s = _config_domain(s) - if s not in self.info.search: - self.info.search.append(s) - - def _config_fromkey(self, key, always_try_domain): - try: - servers, _ = winreg.QueryValueEx(key, "NameServer") - except WindowsError: - servers = None - if servers: - self._config_nameservers(servers) - if servers or always_try_domain: - try: - dom, _ = winreg.QueryValueEx(key, "Domain") - if dom: - self.info.domain = _config_domain(dom) - except WindowsError: - pass - else: - try: - servers, _ = winreg.QueryValueEx(key, "DhcpNameServer") - except WindowsError: - servers = None - if servers: - self._config_nameservers(servers) - try: - dom, _ = winreg.QueryValueEx(key, "DhcpDomain") - if dom: - self.info.domain = _config_domain(dom) - except WindowsError: - pass - try: - search, _ = winreg.QueryValueEx(key, "SearchList") - except WindowsError: - search = None - if search is None: - try: - search, _ = winreg.QueryValueEx(key, "DhcpSearchList") - except WindowsError: - search = None - if search: - self._config_search(search) - - def _is_nic_enabled(self, lm, guid): - # Look in the Windows Registry to determine whether the network - # interface corresponding to the given guid is enabled. - # - # (Code contributed by Paul Marks, thanks!) - # - try: - # This hard-coded location seems to be consistent, at least - # from Windows 2000 through Vista. - connection_key = winreg.OpenKey( - lm, - r"SYSTEM\CurrentControlSet\Control\Network" - r"\{4D36E972-E325-11CE-BFC1-08002BE10318}" - rf"\{guid}\Connection", - ) - - try: - # The PnpInstanceID points to a key inside Enum - (pnp_id, ttype) = winreg.QueryValueEx( - connection_key, "PnpInstanceID" - ) - - if ttype != winreg.REG_SZ: - raise ValueError # pragma: no cover - - device_key = winreg.OpenKey( - lm, rf"SYSTEM\CurrentControlSet\Enum\{pnp_id}" - ) - - try: - # Get ConfigFlags for this device - (flags, ttype) = winreg.QueryValueEx(device_key, "ConfigFlags") - - if ttype != winreg.REG_DWORD: - raise ValueError # pragma: no cover - - # Based on experimentation, bit 0x1 indicates that the - # device is disabled. - # - # XXXRTH I suspect we really want to & with 0x03 so - # that CONFIGFLAGS_REMOVED devices are also ignored, - # but we're shifting to WMI as ConfigFlags is not - # supposed to be used. - return not flags & 0x1 - - finally: - device_key.Close() - finally: - connection_key.Close() - except Exception: # pragma: no cover - return False - - def get(self): - """Extract resolver configuration from the Windows registry.""" - - lm = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - tcp_params = winreg.OpenKey( - lm, r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" - ) - try: - self._config_fromkey(tcp_params, True) - finally: - tcp_params.Close() - interfaces = winreg.OpenKey( - lm, - r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces", - ) - try: - i = 0 - while True: - try: - guid = winreg.EnumKey(interfaces, i) - i += 1 - key = winreg.OpenKey(interfaces, guid) - try: - if not self._is_nic_enabled(lm, guid): - continue - self._config_fromkey(key, False) - finally: - key.Close() - except OSError: - break - finally: - interfaces.Close() - finally: - lm.Close() - return self.info - - _getter_class: Any - if _have_wmi and _prefer_wmi: - _getter_class = _WMIGetter - else: - _getter_class = _RegistryGetter - - def get_dns_info(): - """Extract resolver configuration.""" - getter = _getter_class() - return getter.get() diff --git a/venv/Lib/site-packages/dns/wire.py b/venv/Lib/site-packages/dns/wire.py deleted file mode 100644 index 9f9b157..0000000 --- a/venv/Lib/site-packages/dns/wire.py +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -import contextlib -import struct -from typing import Iterator, Optional, Tuple - -import dns.exception -import dns.name - - -class Parser: - def __init__(self, wire: bytes, current: int = 0): - self.wire = wire - self.current = 0 - self.end = len(self.wire) - if current: - self.seek(current) - self.furthest = current - - def remaining(self) -> int: - return self.end - self.current - - def get_bytes(self, size: int) -> bytes: - assert size >= 0 - if size > self.remaining(): - raise dns.exception.FormError - output = self.wire[self.current : self.current + size] - self.current += size - self.furthest = max(self.furthest, self.current) - return output - - def get_counted_bytes(self, length_size: int = 1) -> bytes: - length = int.from_bytes(self.get_bytes(length_size), "big") - return self.get_bytes(length) - - def get_remaining(self) -> bytes: - return self.get_bytes(self.remaining()) - - def get_uint8(self) -> int: - return struct.unpack("!B", self.get_bytes(1))[0] - - def get_uint16(self) -> int: - return struct.unpack("!H", self.get_bytes(2))[0] - - def get_uint32(self) -> int: - return struct.unpack("!I", self.get_bytes(4))[0] - - def get_uint48(self) -> int: - return int.from_bytes(self.get_bytes(6), "big") - - def get_struct(self, format: str) -> Tuple: - return struct.unpack(format, self.get_bytes(struct.calcsize(format))) - - def get_name(self, origin: Optional["dns.name.Name"] = None) -> "dns.name.Name": - name = dns.name.from_wire_parser(self) - if origin: - name = name.relativize(origin) - return name - - def seek(self, where: int) -> None: - # Note that seeking to the end is OK! (If you try to read - # after such a seek, you'll get an exception as expected.) - if where < 0 or where > self.end: - raise dns.exception.FormError - self.current = where - - @contextlib.contextmanager - def restrict_to(self, size: int) -> Iterator: - assert size >= 0 - if size > self.remaining(): - raise dns.exception.FormError - saved_end = self.end - try: - self.end = self.current + size - yield - # We make this check here and not in the finally as we - # don't want to raise if we're already raising for some - # other reason. - if self.current != self.end: - raise dns.exception.FormError - finally: - self.end = saved_end - - @contextlib.contextmanager - def restore_furthest(self) -> Iterator: - try: - yield None - finally: - self.current = self.furthest diff --git a/venv/Lib/site-packages/dns/xfr.py b/venv/Lib/site-packages/dns/xfr.py deleted file mode 100644 index 520aa32..0000000 --- a/venv/Lib/site-packages/dns/xfr.py +++ /dev/null @@ -1,343 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2017 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -from typing import Any, List, Optional, Tuple, Union - -import dns.exception -import dns.message -import dns.name -import dns.rcode -import dns.rdataset -import dns.rdatatype -import dns.serial -import dns.transaction -import dns.tsig -import dns.zone - - -class TransferError(dns.exception.DNSException): - """A zone transfer response got a non-zero rcode.""" - - def __init__(self, rcode): - message = f"Zone transfer error: {dns.rcode.to_text(rcode)}" - super().__init__(message) - self.rcode = rcode - - -class SerialWentBackwards(dns.exception.FormError): - """The current serial number is less than the serial we know.""" - - -class UseTCP(dns.exception.DNSException): - """This IXFR cannot be completed with UDP.""" - - -class Inbound: - """ - State machine for zone transfers. - """ - - def __init__( - self, - txn_manager: dns.transaction.TransactionManager, - rdtype: dns.rdatatype.RdataType = dns.rdatatype.AXFR, - serial: Optional[int] = None, - is_udp: bool = False, - ): - """Initialize an inbound zone transfer. - - *txn_manager* is a :py:class:`dns.transaction.TransactionManager`. - - *rdtype* can be `dns.rdatatype.AXFR` or `dns.rdatatype.IXFR` - - *serial* is the base serial number for IXFRs, and is required in - that case. - - *is_udp*, a ``bool`` indidicates if UDP is being used for this - XFR. - """ - self.txn_manager = txn_manager - self.txn: Optional[dns.transaction.Transaction] = None - self.rdtype = rdtype - if rdtype == dns.rdatatype.IXFR: - if serial is None: - raise ValueError("a starting serial must be supplied for IXFRs") - elif is_udp: - raise ValueError("is_udp specified for AXFR") - self.serial = serial - self.is_udp = is_udp - (_, _, self.origin) = txn_manager.origin_information() - self.soa_rdataset: Optional[dns.rdataset.Rdataset] = None - self.done = False - self.expecting_SOA = False - self.delete_mode = False - - def process_message(self, message: dns.message.Message) -> bool: - """Process one message in the transfer. - - The message should have the same relativization as was specified when - the `dns.xfr.Inbound` was created. The message should also have been - created with `one_rr_per_rrset=True` because order matters. - - Returns `True` if the transfer is complete, and `False` otherwise. - """ - if self.txn is None: - replacement = self.rdtype == dns.rdatatype.AXFR - self.txn = self.txn_manager.writer(replacement) - rcode = message.rcode() - if rcode != dns.rcode.NOERROR: - raise TransferError(rcode) - # - # We don't require a question section, but if it is present is - # should be correct. - # - if len(message.question) > 0: - if message.question[0].name != self.origin: - raise dns.exception.FormError("wrong question name") - if message.question[0].rdtype != self.rdtype: - raise dns.exception.FormError("wrong question rdatatype") - answer_index = 0 - if self.soa_rdataset is None: - # - # This is the first message. We're expecting an SOA at - # the origin. - # - if not message.answer or message.answer[0].name != self.origin: - raise dns.exception.FormError("No answer or RRset not for zone origin") - rrset = message.answer[0] - rdataset = rrset - if rdataset.rdtype != dns.rdatatype.SOA: - raise dns.exception.FormError("first RRset is not an SOA") - answer_index = 1 - self.soa_rdataset = rdataset.copy() - if self.rdtype == dns.rdatatype.IXFR: - if self.soa_rdataset[0].serial == self.serial: - # - # We're already up-to-date. - # - self.done = True - elif dns.serial.Serial(self.soa_rdataset[0].serial) < self.serial: - # It went backwards! - raise SerialWentBackwards - else: - if self.is_udp and len(message.answer[answer_index:]) == 0: - # - # There are no more records, so this is the - # "truncated" response. Say to use TCP - # - raise UseTCP - # - # Note we're expecting another SOA so we can detect - # if this IXFR response is an AXFR-style response. - # - self.expecting_SOA = True - # - # Process the answer section (other than the initial SOA in - # the first message). - # - for rrset in message.answer[answer_index:]: - name = rrset.name - rdataset = rrset - if self.done: - raise dns.exception.FormError("answers after final SOA") - assert self.txn is not None # for mypy - if rdataset.rdtype == dns.rdatatype.SOA and name == self.origin: - # - # Every time we see an origin SOA delete_mode inverts - # - if self.rdtype == dns.rdatatype.IXFR: - self.delete_mode = not self.delete_mode - # - # If this SOA Rdataset is equal to the first we saw - # then we're finished. If this is an IXFR we also - # check that we're seeing the record in the expected - # part of the response. - # - if rdataset == self.soa_rdataset and ( - self.rdtype == dns.rdatatype.AXFR - or (self.rdtype == dns.rdatatype.IXFR and self.delete_mode) - ): - # - # This is the final SOA - # - if self.expecting_SOA: - # We got an empty IXFR sequence! - raise dns.exception.FormError("empty IXFR sequence") - if ( - self.rdtype == dns.rdatatype.IXFR - and self.serial != rdataset[0].serial - ): - raise dns.exception.FormError("unexpected end of IXFR sequence") - self.txn.replace(name, rdataset) - self.txn.commit() - self.txn = None - self.done = True - else: - # - # This is not the final SOA - # - self.expecting_SOA = False - if self.rdtype == dns.rdatatype.IXFR: - if self.delete_mode: - # This is the start of an IXFR deletion set - if rdataset[0].serial != self.serial: - raise dns.exception.FormError( - "IXFR base serial mismatch" - ) - else: - # This is the start of an IXFR addition set - self.serial = rdataset[0].serial - self.txn.replace(name, rdataset) - else: - # We saw a non-final SOA for the origin in an AXFR. - raise dns.exception.FormError("unexpected origin SOA in AXFR") - continue - if self.expecting_SOA: - # - # We made an IXFR request and are expecting another - # SOA RR, but saw something else, so this must be an - # AXFR response. - # - self.rdtype = dns.rdatatype.AXFR - self.expecting_SOA = False - self.delete_mode = False - self.txn.rollback() - self.txn = self.txn_manager.writer(True) - # - # Note we are falling through into the code below - # so whatever rdataset this was gets written. - # - # Add or remove the data - if self.delete_mode: - self.txn.delete_exact(name, rdataset) - else: - self.txn.add(name, rdataset) - if self.is_udp and not self.done: - # - # This is a UDP IXFR and we didn't get to done, and we didn't - # get the proper "truncated" response - # - raise dns.exception.FormError("unexpected end of UDP IXFR") - return self.done - - # - # Inbounds are context managers. - # - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - if self.txn: - self.txn.rollback() - return False - - -def make_query( - txn_manager: dns.transaction.TransactionManager, - serial: Optional[int] = 0, - use_edns: Optional[Union[int, bool]] = None, - ednsflags: Optional[int] = None, - payload: Optional[int] = None, - request_payload: Optional[int] = None, - options: Optional[List[dns.edns.Option]] = None, - keyring: Any = None, - keyname: Optional[dns.name.Name] = None, - keyalgorithm: Union[dns.name.Name, str] = dns.tsig.default_algorithm, -) -> Tuple[dns.message.QueryMessage, Optional[int]]: - """Make an AXFR or IXFR query. - - *txn_manager* is a ``dns.transaction.TransactionManager``, typically a - ``dns.zone.Zone``. - - *serial* is an ``int`` or ``None``. If 0, then IXFR will be - attempted using the most recent serial number from the - *txn_manager*; it is the caller's responsibility to ensure there - are no write transactions active that could invalidate the - retrieved serial. If a serial cannot be determined, AXFR will be - forced. Other integer values are the starting serial to use. - ``None`` forces an AXFR. - - Please see the documentation for :py:func:`dns.message.make_query` and - :py:func:`dns.message.Message.use_tsig` for details on the other parameters - to this function. - - Returns a `(query, serial)` tuple. - """ - (zone_origin, _, origin) = txn_manager.origin_information() - if zone_origin is None: - raise ValueError("no zone origin") - if serial is None: - rdtype = dns.rdatatype.AXFR - elif not isinstance(serial, int): - raise ValueError("serial is not an integer") - elif serial == 0: - with txn_manager.reader() as txn: - rdataset = txn.get(origin, "SOA") - if rdataset: - serial = rdataset[0].serial - rdtype = dns.rdatatype.IXFR - else: - serial = None - rdtype = dns.rdatatype.AXFR - elif serial > 0 and serial < 4294967296: - rdtype = dns.rdatatype.IXFR - else: - raise ValueError("serial out-of-range") - rdclass = txn_manager.get_class() - q = dns.message.make_query( - zone_origin, - rdtype, - rdclass, - use_edns, - False, - ednsflags, - payload, - request_payload, - options, - ) - if serial is not None: - rdata = dns.rdata.from_text(rdclass, "SOA", f". . {serial} 0 0 0 0") - rrset = q.find_rrset( - q.authority, zone_origin, rdclass, dns.rdatatype.SOA, create=True - ) - rrset.add(rdata, 0) - if keyring is not None: - q.use_tsig(keyring, keyname, algorithm=keyalgorithm) - return (q, serial) - - -def extract_serial_from_query(query: dns.message.Message) -> Optional[int]: - """Extract the SOA serial number from query if it is an IXFR and return - it, otherwise return None. - - *query* is a dns.message.QueryMessage that is an IXFR or AXFR request. - - Raises if the query is not an IXFR or AXFR, or if an IXFR doesn't have - an appropriate SOA RRset in the authority section. - """ - if not isinstance(query, dns.message.QueryMessage): - raise ValueError("query not a QueryMessage") - question = query.question[0] - if question.rdtype == dns.rdatatype.AXFR: - return None - elif question.rdtype != dns.rdatatype.IXFR: - raise ValueError("query is not an AXFR or IXFR") - soa = query.find_rrset( - query.authority, question.name, question.rdclass, dns.rdatatype.SOA - ) - return soa[0].serial diff --git a/venv/Lib/site-packages/dns/zone.py b/venv/Lib/site-packages/dns/zone.py deleted file mode 100644 index 844919e..0000000 --- a/venv/Lib/site-packages/dns/zone.py +++ /dev/null @@ -1,1434 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Zones.""" - -import contextlib -import io -import os -import struct -from typing import ( - Any, - Callable, - Iterable, - Iterator, - List, - MutableMapping, - Optional, - Set, - Tuple, - Union, -) - -import dns.exception -import dns.grange -import dns.immutable -import dns.name -import dns.node -import dns.rdata -import dns.rdataclass -import dns.rdataset -import dns.rdatatype -import dns.rdtypes.ANY.SOA -import dns.rdtypes.ANY.ZONEMD -import dns.rrset -import dns.tokenizer -import dns.transaction -import dns.ttl -import dns.zonefile -from dns.zonetypes import DigestHashAlgorithm, DigestScheme, _digest_hashers - - -class BadZone(dns.exception.DNSException): - """The DNS zone is malformed.""" - - -class NoSOA(BadZone): - """The DNS zone has no SOA RR at its origin.""" - - -class NoNS(BadZone): - """The DNS zone has no NS RRset at its origin.""" - - -class UnknownOrigin(BadZone): - """The DNS zone's origin is unknown.""" - - -class UnsupportedDigestScheme(dns.exception.DNSException): - """The zone digest's scheme is unsupported.""" - - -class UnsupportedDigestHashAlgorithm(dns.exception.DNSException): - """The zone digest's origin is unsupported.""" - - -class NoDigest(dns.exception.DNSException): - """The DNS zone has no ZONEMD RRset at its origin.""" - - -class DigestVerificationFailure(dns.exception.DNSException): - """The ZONEMD digest failed to verify.""" - - -def _validate_name( - name: dns.name.Name, - origin: Optional[dns.name.Name], - relativize: bool, -) -> dns.name.Name: - # This name validation code is shared by Zone and Version - if origin is None: - # This should probably never happen as other code (e.g. - # _rr_line) will notice the lack of an origin before us, but - # we check just in case! - raise KeyError("no zone origin is defined") - if name.is_absolute(): - if not name.is_subdomain(origin): - raise KeyError("name parameter must be a subdomain of the zone origin") - if relativize: - name = name.relativize(origin) - else: - # We have a relative name. Make sure that the derelativized name is - # not too long. - try: - abs_name = name.derelativize(origin) - except dns.name.NameTooLong: - # We map dns.name.NameTooLong to KeyError to be consistent with - # the other exceptions above. - raise KeyError("relative name too long for zone") - if not relativize: - # We have a relative name in a non-relative zone, so use the - # derelativized name. - name = abs_name - return name - - -class Zone(dns.transaction.TransactionManager): - """A DNS zone. - - A ``Zone`` is a mapping from names to nodes. The zone object may be - treated like a Python dictionary, e.g. ``zone[name]`` will retrieve - the node associated with that name. The *name* may be a - ``dns.name.Name object``, or it may be a string. In either case, - if the name is relative it is treated as relative to the origin of - the zone. - """ - - node_factory: Callable[[], dns.node.Node] = dns.node.Node - map_factory: Callable[[], MutableMapping[dns.name.Name, dns.node.Node]] = dict - writable_version_factory: Optional[Callable[[], "WritableVersion"]] = None - immutable_version_factory: Optional[Callable[[], "ImmutableVersion"]] = None - - __slots__ = ["rdclass", "origin", "nodes", "relativize"] - - def __init__( - self, - origin: Optional[Union[dns.name.Name, str]], - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - relativize: bool = True, - ): - """Initialize a zone object. - - *origin* is the origin of the zone. It may be a ``dns.name.Name``, - a ``str``, or ``None``. If ``None``, then the zone's origin will - be set by the first ``$ORIGIN`` line in a zone file. - - *rdclass*, an ``int``, the zone's rdata class; the default is class IN. - - *relativize*, a ``bool``, determine's whether domain names are - relativized to the zone's origin. The default is ``True``. - """ - - if origin is not None: - if isinstance(origin, str): - origin = dns.name.from_text(origin) - elif not isinstance(origin, dns.name.Name): - raise ValueError("origin parameter must be convertible to a DNS name") - if not origin.is_absolute(): - raise ValueError("origin parameter must be an absolute name") - self.origin = origin - self.rdclass = rdclass - self.nodes: MutableMapping[dns.name.Name, dns.node.Node] = self.map_factory() - self.relativize = relativize - - def __eq__(self, other): - """Two zones are equal if they have the same origin, class, and - nodes. - - Returns a ``bool``. - """ - - if not isinstance(other, Zone): - return False - if ( - self.rdclass != other.rdclass - or self.origin != other.origin - or self.nodes != other.nodes - ): - return False - return True - - def __ne__(self, other): - """Are two zones not equal? - - Returns a ``bool``. - """ - - return not self.__eq__(other) - - def _validate_name(self, name: Union[dns.name.Name, str]) -> dns.name.Name: - # Note that any changes in this method should have corresponding changes - # made in the Version _validate_name() method. - if isinstance(name, str): - name = dns.name.from_text(name, None) - elif not isinstance(name, dns.name.Name): - raise KeyError("name parameter must be convertible to a DNS name") - return _validate_name(name, self.origin, self.relativize) - - def __getitem__(self, key): - key = self._validate_name(key) - return self.nodes[key] - - def __setitem__(self, key, value): - key = self._validate_name(key) - self.nodes[key] = value - - def __delitem__(self, key): - key = self._validate_name(key) - del self.nodes[key] - - def __iter__(self): - return self.nodes.__iter__() - - def keys(self): - return self.nodes.keys() - - def values(self): - return self.nodes.values() - - def items(self): - return self.nodes.items() - - def get(self, key): - key = self._validate_name(key) - return self.nodes.get(key) - - def __contains__(self, key): - key = self._validate_name(key) - return key in self.nodes - - def find_node( - self, name: Union[dns.name.Name, str], create: bool = False - ) -> dns.node.Node: - """Find a node in the zone, possibly creating it. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *create*, a ``bool``. If true, the node will be created if it does - not exist. - - Raises ``KeyError`` if the name is not known and create was - not specified, or if the name was not a subdomain of the origin. - - Returns a ``dns.node.Node``. - """ - - name = self._validate_name(name) - node = self.nodes.get(name) - if node is None: - if not create: - raise KeyError - node = self.node_factory() - self.nodes[name] = node - return node - - def get_node( - self, name: Union[dns.name.Name, str], create: bool = False - ) -> Optional[dns.node.Node]: - """Get a node in the zone, possibly creating it. - - This method is like ``find_node()``, except it returns None instead - of raising an exception if the node does not exist and creation - has not been requested. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *create*, a ``bool``. If true, the node will be created if it does - not exist. - - Returns a ``dns.node.Node`` or ``None``. - """ - - try: - node = self.find_node(name, create) - except KeyError: - node = None - return node - - def delete_node(self, name: Union[dns.name.Name, str]) -> None: - """Delete the specified node if it exists. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - It is not an error if the node does not exist. - """ - - name = self._validate_name(name) - if name in self.nodes: - del self.nodes[name] - - def find_rdataset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - create: bool = False, - ) -> dns.rdataset.Rdataset: - """Look for an rdataset with the specified name and type in the zone, - and return an rdataset encapsulating it. - - The rdataset returned is not a copy; changes to it will change - the zone. - - KeyError is raised if the name or type are not found. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdatatype.RdataType`` or ``str`` the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - - *create*, a ``bool``. If true, the node will be created if it does - not exist. - - Raises ``KeyError`` if the name is not known and create was - not specified, or if the name was not a subdomain of the origin. - - Returns a ``dns.rdataset.Rdataset``. - """ - - name = self._validate_name(name) - rdtype = dns.rdatatype.RdataType.make(rdtype) - covers = dns.rdatatype.RdataType.make(covers) - node = self.find_node(name, create) - return node.find_rdataset(self.rdclass, rdtype, covers, create) - - def get_rdataset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - create: bool = False, - ) -> Optional[dns.rdataset.Rdataset]: - """Look for an rdataset with the specified name and type in the zone. - - This method is like ``find_rdataset()``, except it returns None instead - of raising an exception if the rdataset does not exist and creation - has not been requested. - - The rdataset returned is not a copy; changes to it will change - the zone. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdatatype.RdataType`` or ``str``, the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - - *create*, a ``bool``. If true, the node will be created if it does - not exist. - - Raises ``KeyError`` if the name is not known and create was - not specified, or if the name was not a subdomain of the origin. - - Returns a ``dns.rdataset.Rdataset`` or ``None``. - """ - - try: - rdataset = self.find_rdataset(name, rdtype, covers, create) - except KeyError: - rdataset = None - return rdataset - - def delete_rdataset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> None: - """Delete the rdataset matching *rdtype* and *covers*, if it - exists at the node specified by *name*. - - It is not an error if the node does not exist, or if there is no matching - rdataset at the node. - - If the node has no rdatasets after the deletion, it will itself be deleted. - - *name*: the name of the node to find. The value may be a ``dns.name.Name`` or a - ``str``. If absolute, the name must be a subdomain of the zone's origin. If - ``zone.relativize`` is ``True``, then the name will be relativized. - - *rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdatatype.RdataType`` or ``str`` or ``None``, the covered - type. Usually this value is ``dns.rdatatype.NONE``, but if the rdtype is - ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, then the covers value will be - the rdata type the SIG/RRSIG covers. The library treats the SIG and RRSIG types - as if they were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). This - makes RRSIGs much easier to work with than if RRSIGs covering different rdata - types were aggregated into a single RRSIG rdataset. - """ - - name = self._validate_name(name) - rdtype = dns.rdatatype.RdataType.make(rdtype) - covers = dns.rdatatype.RdataType.make(covers) - node = self.get_node(name) - if node is not None: - node.delete_rdataset(self.rdclass, rdtype, covers) - if len(node) == 0: - self.delete_node(name) - - def replace_rdataset( - self, name: Union[dns.name.Name, str], replacement: dns.rdataset.Rdataset - ) -> None: - """Replace an rdataset at name. - - It is not an error if there is no rdataset matching I{replacement}. - - Ownership of the *replacement* object is transferred to the zone; - in other words, this method does not store a copy of *replacement* - at the node, it stores *replacement* itself. - - If the node does not exist, it is created. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *replacement*, a ``dns.rdataset.Rdataset``, the replacement rdataset. - """ - - if replacement.rdclass != self.rdclass: - raise ValueError("replacement.rdclass != zone.rdclass") - node = self.find_node(name, True) - node.replace_rdataset(replacement) - - def find_rrset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> dns.rrset.RRset: - """Look for an rdataset with the specified name and type in the zone, - and return an RRset encapsulating it. - - This method is less efficient than the similar - ``find_rdataset()`` because it creates an RRset instead of - returning the matching rdataset. It may be more convenient - for some uses since it returns an object which binds the owner - name to the rdataset. - - This method may not be used to create new nodes or rdatasets; - use ``find_rdataset`` instead. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *rdtype*, a ``dns.rdatatype.RdataType`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdatatype.RdataType`` or ``str``, the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - - *create*, a ``bool``. If true, the node will be created if it does - not exist. - - Raises ``KeyError`` if the name is not known and create was - not specified, or if the name was not a subdomain of the origin. - - Returns a ``dns.rrset.RRset`` or ``None``. - """ - - vname = self._validate_name(name) - rdtype = dns.rdatatype.RdataType.make(rdtype) - covers = dns.rdatatype.RdataType.make(covers) - rdataset = self.nodes[vname].find_rdataset(self.rdclass, rdtype, covers) - rrset = dns.rrset.RRset(vname, self.rdclass, rdtype, covers) - rrset.update(rdataset) - return rrset - - def get_rrset( - self, - name: Union[dns.name.Name, str], - rdtype: Union[dns.rdatatype.RdataType, str], - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> Optional[dns.rrset.RRset]: - """Look for an rdataset with the specified name and type in the zone, - and return an RRset encapsulating it. - - This method is less efficient than the similar ``get_rdataset()`` - because it creates an RRset instead of returning the matching - rdataset. It may be more convenient for some uses since it - returns an object which binds the owner name to the rdataset. - - This method may not be used to create new nodes or rdatasets; - use ``get_rdataset()`` instead. - - *name*: the name of the node to find. - The value may be a ``dns.name.Name`` or a ``str``. If absolute, the - name must be a subdomain of the zone's origin. If ``zone.relativize`` - is ``True``, then the name will be relativized. - - *rdtype*, a ``dns.rdataset.Rdataset`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdataset.Rdataset`` or ``str``, the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - - *create*, a ``bool``. If true, the node will be created if it does - not exist. - - Returns a ``dns.rrset.RRset`` or ``None``. - """ - - try: - rrset = self.find_rrset(name, rdtype, covers) - except KeyError: - rrset = None - return rrset - - def iterate_rdatasets( - self, - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.ANY, - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> Iterator[Tuple[dns.name.Name, dns.rdataset.Rdataset]]: - """Return a generator which yields (name, rdataset) tuples for - all rdatasets in the zone which have the specified *rdtype* - and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default, - then all rdatasets will be matched. - - *rdtype*, a ``dns.rdataset.Rdataset`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdataset.Rdataset`` or ``str``, the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - """ - - rdtype = dns.rdatatype.RdataType.make(rdtype) - covers = dns.rdatatype.RdataType.make(covers) - for name, node in self.items(): - for rds in node: - if rdtype == dns.rdatatype.ANY or ( - rds.rdtype == rdtype and rds.covers == covers - ): - yield (name, rds) - - def iterate_rdatas( - self, - rdtype: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.ANY, - covers: Union[dns.rdatatype.RdataType, str] = dns.rdatatype.NONE, - ) -> Iterator[Tuple[dns.name.Name, int, dns.rdata.Rdata]]: - """Return a generator which yields (name, ttl, rdata) tuples for - all rdatas in the zone which have the specified *rdtype* - and *covers*. If *rdtype* is ``dns.rdatatype.ANY``, the default, - then all rdatas will be matched. - - *rdtype*, a ``dns.rdataset.Rdataset`` or ``str``, the rdata type desired. - - *covers*, a ``dns.rdataset.Rdataset`` or ``str``, the covered type. - Usually this value is ``dns.rdatatype.NONE``, but if the - rdtype is ``dns.rdatatype.SIG`` or ``dns.rdatatype.RRSIG``, - then the covers value will be the rdata type the SIG/RRSIG - covers. The library treats the SIG and RRSIG types as if they - were a family of types, e.g. RRSIG(A), RRSIG(NS), RRSIG(SOA). - This makes RRSIGs much easier to work with than if RRSIGs - covering different rdata types were aggregated into a single - RRSIG rdataset. - """ - - rdtype = dns.rdatatype.RdataType.make(rdtype) - covers = dns.rdatatype.RdataType.make(covers) - for name, node in self.items(): - for rds in node: - if rdtype == dns.rdatatype.ANY or ( - rds.rdtype == rdtype and rds.covers == covers - ): - for rdata in rds: - yield (name, rds.ttl, rdata) - - def to_file( - self, - f: Any, - sorted: bool = True, - relativize: bool = True, - nl: Optional[str] = None, - want_comments: bool = False, - want_origin: bool = False, - ) -> None: - """Write a zone to a file. - - *f*, a file or `str`. If *f* is a string, it is treated - as the name of a file to open. - - *sorted*, a ``bool``. If True, the default, then the file - will be written with the names sorted in DNSSEC order from - least to greatest. Otherwise the names will be written in - whatever order they happen to have in the zone's dictionary. - - *relativize*, a ``bool``. If True, the default, then domain - names in the output will be relativized to the zone's origin - if possible. - - *nl*, a ``str`` or None. The end of line string. If not - ``None``, the output will use the platform's native - end-of-line marker (i.e. LF on POSIX, CRLF on Windows). - - *want_comments*, a ``bool``. If ``True``, emit end-of-line comments - as part of writing the file. If ``False``, the default, do not - emit them. - - *want_origin*, a ``bool``. If ``True``, emit a $ORIGIN line at - the start of the file. If ``False``, the default, do not emit - one. - """ - - if isinstance(f, str): - cm: contextlib.AbstractContextManager = open(f, "wb") - else: - cm = contextlib.nullcontext(f) - with cm as f: - # must be in this way, f.encoding may contain None, or even - # attribute may not be there - file_enc = getattr(f, "encoding", None) - if file_enc is None: - file_enc = "utf-8" - - if nl is None: - # binary mode, '\n' is not enough - nl_b = os.linesep.encode(file_enc) - nl = "\n" - elif isinstance(nl, str): - nl_b = nl.encode(file_enc) - else: - nl_b = nl - nl = nl.decode() - - if want_origin: - assert self.origin is not None - l = "$ORIGIN " + self.origin.to_text() - l_b = l.encode(file_enc) - try: - f.write(l_b) - f.write(nl_b) - except TypeError: # textual mode - f.write(l) - f.write(nl) - - if sorted: - names = list(self.keys()) - names.sort() - else: - names = self.keys() - for n in names: - l = self[n].to_text( - n, - origin=self.origin, - relativize=relativize, - want_comments=want_comments, - ) - l_b = l.encode(file_enc) - - try: - f.write(l_b) - f.write(nl_b) - except TypeError: # textual mode - f.write(l) - f.write(nl) - - def to_text( - self, - sorted: bool = True, - relativize: bool = True, - nl: Optional[str] = None, - want_comments: bool = False, - want_origin: bool = False, - ) -> str: - """Return a zone's text as though it were written to a file. - - *sorted*, a ``bool``. If True, the default, then the file - will be written with the names sorted in DNSSEC order from - least to greatest. Otherwise the names will be written in - whatever order they happen to have in the zone's dictionary. - - *relativize*, a ``bool``. If True, the default, then domain - names in the output will be relativized to the zone's origin - if possible. - - *nl*, a ``str`` or None. The end of line string. If not - ``None``, the output will use the platform's native - end-of-line marker (i.e. LF on POSIX, CRLF on Windows). - - *want_comments*, a ``bool``. If ``True``, emit end-of-line comments - as part of writing the file. If ``False``, the default, do not - emit them. - - *want_origin*, a ``bool``. If ``True``, emit a $ORIGIN line at - the start of the output. If ``False``, the default, do not emit - one. - - Returns a ``str``. - """ - temp_buffer = io.StringIO() - self.to_file(temp_buffer, sorted, relativize, nl, want_comments, want_origin) - return_value = temp_buffer.getvalue() - temp_buffer.close() - return return_value - - def check_origin(self) -> None: - """Do some simple checking of the zone's origin. - - Raises ``dns.zone.NoSOA`` if there is no SOA RRset. - - Raises ``dns.zone.NoNS`` if there is no NS RRset. - - Raises ``KeyError`` if there is no origin node. - """ - if self.relativize: - name = dns.name.empty - else: - assert self.origin is not None - name = self.origin - if self.get_rdataset(name, dns.rdatatype.SOA) is None: - raise NoSOA - if self.get_rdataset(name, dns.rdatatype.NS) is None: - raise NoNS - - def get_soa( - self, txn: Optional[dns.transaction.Transaction] = None - ) -> dns.rdtypes.ANY.SOA.SOA: - """Get the zone SOA rdata. - - Raises ``dns.zone.NoSOA`` if there is no SOA RRset. - - Returns a ``dns.rdtypes.ANY.SOA.SOA`` Rdata. - """ - if self.relativize: - origin_name = dns.name.empty - else: - if self.origin is None: - # get_soa() has been called very early, and there must not be - # an SOA if there is no origin. - raise NoSOA - origin_name = self.origin - soa: Optional[dns.rdataset.Rdataset] - if txn: - soa = txn.get(origin_name, dns.rdatatype.SOA) - else: - soa = self.get_rdataset(origin_name, dns.rdatatype.SOA) - if soa is None: - raise NoSOA - return soa[0] - - def _compute_digest( - self, - hash_algorithm: DigestHashAlgorithm, - scheme: DigestScheme = DigestScheme.SIMPLE, - ) -> bytes: - hashinfo = _digest_hashers.get(hash_algorithm) - if not hashinfo: - raise UnsupportedDigestHashAlgorithm - if scheme != DigestScheme.SIMPLE: - raise UnsupportedDigestScheme - - if self.relativize: - origin_name = dns.name.empty - else: - assert self.origin is not None - origin_name = self.origin - hasher = hashinfo() - for name, node in sorted(self.items()): - rrnamebuf = name.to_digestable(self.origin) - for rdataset in sorted(node, key=lambda rds: (rds.rdtype, rds.covers)): - if name == origin_name and dns.rdatatype.ZONEMD in ( - rdataset.rdtype, - rdataset.covers, - ): - continue - rrfixed = struct.pack( - "!HHI", rdataset.rdtype, rdataset.rdclass, rdataset.ttl - ) - rdatas = [rdata.to_digestable(self.origin) for rdata in rdataset] - for rdata in sorted(rdatas): - rrlen = struct.pack("!H", len(rdata)) - hasher.update(rrnamebuf + rrfixed + rrlen + rdata) - return hasher.digest() - - def compute_digest( - self, - hash_algorithm: DigestHashAlgorithm, - scheme: DigestScheme = DigestScheme.SIMPLE, - ) -> dns.rdtypes.ANY.ZONEMD.ZONEMD: - serial = self.get_soa().serial - digest = self._compute_digest(hash_algorithm, scheme) - return dns.rdtypes.ANY.ZONEMD.ZONEMD( - self.rdclass, dns.rdatatype.ZONEMD, serial, scheme, hash_algorithm, digest - ) - - def verify_digest( - self, zonemd: Optional[dns.rdtypes.ANY.ZONEMD.ZONEMD] = None - ) -> None: - digests: Union[dns.rdataset.Rdataset, List[dns.rdtypes.ANY.ZONEMD.ZONEMD]] - if zonemd: - digests = [zonemd] - else: - assert self.origin is not None - rds = self.get_rdataset(self.origin, dns.rdatatype.ZONEMD) - if rds is None: - raise NoDigest - digests = rds - for digest in digests: - try: - computed = self._compute_digest(digest.hash_algorithm, digest.scheme) - if computed == digest.digest: - return - except Exception: - pass - raise DigestVerificationFailure - - # TransactionManager methods - - def reader(self) -> "Transaction": - return Transaction(self, False, Version(self, 1, self.nodes, self.origin)) - - def writer(self, replacement: bool = False) -> "Transaction": - txn = Transaction(self, replacement) - txn._setup_version() - return txn - - def origin_information( - self, - ) -> Tuple[Optional[dns.name.Name], bool, Optional[dns.name.Name]]: - effective: Optional[dns.name.Name] - if self.relativize: - effective = dns.name.empty - else: - effective = self.origin - return (self.origin, self.relativize, effective) - - def get_class(self): - return self.rdclass - - # Transaction methods - - def _end_read(self, txn): - pass - - def _end_write(self, txn): - pass - - def _commit_version(self, _, version, origin): - self.nodes = version.nodes - if self.origin is None: - self.origin = origin - - def _get_next_version_id(self): - # Versions are ephemeral and all have id 1 - return 1 - - -# These classes used to be in dns.versioned, but have moved here so we can use -# the copy-on-write transaction mechanism for both kinds of zones. In a -# regular zone, the version only exists during the transaction, and the nodes -# are regular dns.node.Nodes. - -# A node with a version id. - - -class VersionedNode(dns.node.Node): # lgtm[py/missing-equals] - __slots__ = ["id"] - - def __init__(self): - super().__init__() - # A proper id will get set by the Version - self.id = 0 - - -@dns.immutable.immutable -class ImmutableVersionedNode(VersionedNode): - def __init__(self, node): - super().__init__() - self.id = node.id - self.rdatasets = tuple( - [dns.rdataset.ImmutableRdataset(rds) for rds in node.rdatasets] - ) - - def find_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - create: bool = False, - ) -> dns.rdataset.Rdataset: - if create: - raise TypeError("immutable") - return super().find_rdataset(rdclass, rdtype, covers, False) - - def get_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - create: bool = False, - ) -> Optional[dns.rdataset.Rdataset]: - if create: - raise TypeError("immutable") - return super().get_rdataset(rdclass, rdtype, covers, False) - - def delete_rdataset( - self, - rdclass: dns.rdataclass.RdataClass, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType = dns.rdatatype.NONE, - ) -> None: - raise TypeError("immutable") - - def replace_rdataset(self, replacement: dns.rdataset.Rdataset) -> None: - raise TypeError("immutable") - - def is_immutable(self) -> bool: - return True - - -class Version: - def __init__( - self, - zone: Zone, - id: int, - nodes: Optional[MutableMapping[dns.name.Name, dns.node.Node]] = None, - origin: Optional[dns.name.Name] = None, - ): - self.zone = zone - self.id = id - if nodes is not None: - self.nodes = nodes - else: - self.nodes = zone.map_factory() - self.origin = origin - - def _validate_name(self, name: dns.name.Name) -> dns.name.Name: - return _validate_name(name, self.origin, self.zone.relativize) - - def get_node(self, name: dns.name.Name) -> Optional[dns.node.Node]: - name = self._validate_name(name) - return self.nodes.get(name) - - def get_rdataset( - self, - name: dns.name.Name, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType, - ) -> Optional[dns.rdataset.Rdataset]: - node = self.get_node(name) - if node is None: - return None - return node.get_rdataset(self.zone.rdclass, rdtype, covers) - - def keys(self): - return self.nodes.keys() - - def items(self): - return self.nodes.items() - - -class WritableVersion(Version): - def __init__(self, zone: Zone, replacement: bool = False): - # The zone._versions_lock must be held by our caller in a versioned - # zone. - id = zone._get_next_version_id() - super().__init__(zone, id) - if not replacement: - # We copy the map, because that gives us a simple and thread-safe - # way of doing versions, and we have a garbage collector to help - # us. We only make new node objects if we actually change the - # node. - self.nodes.update(zone.nodes) - # We have to copy the zone origin as it may be None in the first - # version, and we don't want to mutate the zone until we commit. - self.origin = zone.origin - self.changed: Set[dns.name.Name] = set() - - def _maybe_cow(self, name: dns.name.Name) -> dns.node.Node: - name = self._validate_name(name) - node = self.nodes.get(name) - if node is None or name not in self.changed: - new_node = self.zone.node_factory() - if hasattr(new_node, "id"): - # We keep doing this for backwards compatibility, as earlier - # code used new_node.id != self.id for the "do we need to CoW?" - # test. Now we use the changed set as this works with both - # regular zones and versioned zones. - # - # We ignore the mypy error as this is safe but it doesn't see it. - new_node.id = self.id # type: ignore - if node is not None: - # moo! copy on write! - new_node.rdatasets.extend(node.rdatasets) - self.nodes[name] = new_node - self.changed.add(name) - return new_node - else: - return node - - def delete_node(self, name: dns.name.Name) -> None: - name = self._validate_name(name) - if name in self.nodes: - del self.nodes[name] - self.changed.add(name) - - def put_rdataset( - self, name: dns.name.Name, rdataset: dns.rdataset.Rdataset - ) -> None: - node = self._maybe_cow(name) - node.replace_rdataset(rdataset) - - def delete_rdataset( - self, - name: dns.name.Name, - rdtype: dns.rdatatype.RdataType, - covers: dns.rdatatype.RdataType, - ) -> None: - node = self._maybe_cow(name) - node.delete_rdataset(self.zone.rdclass, rdtype, covers) - if len(node) == 0: - del self.nodes[name] - - -@dns.immutable.immutable -class ImmutableVersion(Version): - def __init__(self, version: WritableVersion): - # We tell super() that it's a replacement as we don't want it - # to copy the nodes, as we're about to do that with an - # immutable Dict. - super().__init__(version.zone, True) - # set the right id! - self.id = version.id - # keep the origin - self.origin = version.origin - # Make changed nodes immutable - for name in version.changed: - node = version.nodes.get(name) - # it might not exist if we deleted it in the version - if node: - version.nodes[name] = ImmutableVersionedNode(node) - # We're changing the type of the nodes dictionary here on purpose, so - # we ignore the mypy error. - self.nodes = dns.immutable.Dict( - version.nodes, True, self.zone.map_factory - ) # type: ignore - - -class Transaction(dns.transaction.Transaction): - def __init__(self, zone, replacement, version=None, make_immutable=False): - read_only = version is not None - super().__init__(zone, replacement, read_only) - self.version = version - self.make_immutable = make_immutable - - @property - def zone(self): - return self.manager - - def _setup_version(self): - assert self.version is None - factory = self.manager.writable_version_factory - if factory is None: - factory = WritableVersion - self.version = factory(self.zone, self.replacement) - - def _get_rdataset(self, name, rdtype, covers): - return self.version.get_rdataset(name, rdtype, covers) - - def _put_rdataset(self, name, rdataset): - assert not self.read_only - self.version.put_rdataset(name, rdataset) - - def _delete_name(self, name): - assert not self.read_only - self.version.delete_node(name) - - def _delete_rdataset(self, name, rdtype, covers): - assert not self.read_only - self.version.delete_rdataset(name, rdtype, covers) - - def _name_exists(self, name): - return self.version.get_node(name) is not None - - def _changed(self): - if self.read_only: - return False - else: - return len(self.version.changed) > 0 - - def _end_transaction(self, commit): - if self.read_only: - self.zone._end_read(self) - elif commit and len(self.version.changed) > 0: - if self.make_immutable: - factory = self.manager.immutable_version_factory - if factory is None: - factory = ImmutableVersion - version = factory(self.version) - else: - version = self.version - self.zone._commit_version(self, version, self.version.origin) - else: - # rollback - self.zone._end_write(self) - - def _set_origin(self, origin): - if self.version.origin is None: - self.version.origin = origin - - def _iterate_rdatasets(self): - for name, node in self.version.items(): - for rdataset in node: - yield (name, rdataset) - - def _iterate_names(self): - return self.version.keys() - - def _get_node(self, name): - return self.version.get_node(name) - - def _origin_information(self): - (absolute, relativize, effective) = self.manager.origin_information() - if absolute is None and self.version.origin is not None: - # No origin has been committed yet, but we've learned one as part of - # this txn. Use it. - absolute = self.version.origin - if relativize: - effective = dns.name.empty - else: - effective = absolute - return (absolute, relativize, effective) - - -def _from_text( - text: Any, - origin: Optional[Union[dns.name.Name, str]] = None, - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - relativize: bool = True, - zone_factory: Any = Zone, - filename: Optional[str] = None, - allow_include: bool = False, - check_origin: bool = True, - idna_codec: Optional[dns.name.IDNACodec] = None, - allow_directives: Union[bool, Iterable[str]] = True, -) -> Zone: - # See the comments for the public APIs from_text() and from_file() for - # details. - - # 'text' can also be a file, but we don't publish that fact - # since it's an implementation detail. The official file - # interface is from_file(). - - if filename is None: - filename = "" - zone = zone_factory(origin, rdclass, relativize=relativize) - with zone.writer(True) as txn: - tok = dns.tokenizer.Tokenizer(text, filename, idna_codec=idna_codec) - reader = dns.zonefile.Reader( - tok, - rdclass, - txn, - allow_include=allow_include, - allow_directives=allow_directives, - ) - try: - reader.read() - except dns.zonefile.UnknownOrigin: - # for backwards compatibility - raise dns.zone.UnknownOrigin - # Now that we're done reading, do some basic checking of the zone. - if check_origin: - zone.check_origin() - return zone - - -def from_text( - text: str, - origin: Optional[Union[dns.name.Name, str]] = None, - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - relativize: bool = True, - zone_factory: Any = Zone, - filename: Optional[str] = None, - allow_include: bool = False, - check_origin: bool = True, - idna_codec: Optional[dns.name.IDNACodec] = None, - allow_directives: Union[bool, Iterable[str]] = True, -) -> Zone: - """Build a zone object from a zone file format string. - - *text*, a ``str``, the zone file format input. - - *origin*, a ``dns.name.Name``, a ``str``, or ``None``. The origin - of the zone; if not specified, the first ``$ORIGIN`` statement in the - zone file will determine the origin of the zone. - - *rdclass*, a ``dns.rdataclass.RdataClass``, the zone's rdata class; the default is - class IN. - - *relativize*, a ``bool``, determine's whether domain names are - relativized to the zone's origin. The default is ``True``. - - *zone_factory*, the zone factory to use or ``None``. If ``None``, then - ``dns.zone.Zone`` will be used. The value may be any class or callable - that returns a subclass of ``dns.zone.Zone``. - - *filename*, a ``str`` or ``None``, the filename to emit when - describing where an error occurred; the default is ``''``. - - *allow_include*, a ``bool``. If ``True``, the default, then ``$INCLUDE`` - directives are permitted. If ``False``, then encoutering a ``$INCLUDE`` - will raise a ``SyntaxError`` exception. - - *check_origin*, a ``bool``. If ``True``, the default, then sanity - checks of the origin node will be made by calling the zone's - ``check_origin()`` method. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - *allow_directives*, a ``bool`` or an iterable of `str`. If ``True``, the default, - then directives are permitted, and the *allow_include* parameter controls whether - ``$INCLUDE`` is permitted. If ``False`` or an empty iterable, then no directive - processing is done and any directive-like text will be treated as a regular owner - name. If a non-empty iterable, then only the listed directives (including the - ``$``) are allowed. - - Raises ``dns.zone.NoSOA`` if there is no SOA RRset. - - Raises ``dns.zone.NoNS`` if there is no NS RRset. - - Raises ``KeyError`` if there is no origin node. - - Returns a subclass of ``dns.zone.Zone``. - """ - return _from_text( - text, - origin, - rdclass, - relativize, - zone_factory, - filename, - allow_include, - check_origin, - idna_codec, - allow_directives, - ) - - -def from_file( - f: Any, - origin: Optional[Union[dns.name.Name, str]] = None, - rdclass: dns.rdataclass.RdataClass = dns.rdataclass.IN, - relativize: bool = True, - zone_factory: Any = Zone, - filename: Optional[str] = None, - allow_include: bool = True, - check_origin: bool = True, - idna_codec: Optional[dns.name.IDNACodec] = None, - allow_directives: Union[bool, Iterable[str]] = True, -) -> Zone: - """Read a zone file and build a zone object. - - *f*, a file or ``str``. If *f* is a string, it is treated - as the name of a file to open. - - *origin*, a ``dns.name.Name``, a ``str``, or ``None``. The origin - of the zone; if not specified, the first ``$ORIGIN`` statement in the - zone file will determine the origin of the zone. - - *rdclass*, an ``int``, the zone's rdata class; the default is class IN. - - *relativize*, a ``bool``, determine's whether domain names are - relativized to the zone's origin. The default is ``True``. - - *zone_factory*, the zone factory to use or ``None``. If ``None``, then - ``dns.zone.Zone`` will be used. The value may be any class or callable - that returns a subclass of ``dns.zone.Zone``. - - *filename*, a ``str`` or ``None``, the filename to emit when - describing where an error occurred; the default is ``''``. - - *allow_include*, a ``bool``. If ``True``, the default, then ``$INCLUDE`` - directives are permitted. If ``False``, then encoutering a ``$INCLUDE`` - will raise a ``SyntaxError`` exception. - - *check_origin*, a ``bool``. If ``True``, the default, then sanity - checks of the origin node will be made by calling the zone's - ``check_origin()`` method. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. - - *allow_directives*, a ``bool`` or an iterable of `str`. If ``True``, the default, - then directives are permitted, and the *allow_include* parameter controls whether - ``$INCLUDE`` is permitted. If ``False`` or an empty iterable, then no directive - processing is done and any directive-like text will be treated as a regular owner - name. If a non-empty iterable, then only the listed directives (including the - ``$``) are allowed. - - Raises ``dns.zone.NoSOA`` if there is no SOA RRset. - - Raises ``dns.zone.NoNS`` if there is no NS RRset. - - Raises ``KeyError`` if there is no origin node. - - Returns a subclass of ``dns.zone.Zone``. - """ - - if isinstance(f, str): - if filename is None: - filename = f - cm: contextlib.AbstractContextManager = open(f) - else: - cm = contextlib.nullcontext(f) - with cm as f: - return _from_text( - f, - origin, - rdclass, - relativize, - zone_factory, - filename, - allow_include, - check_origin, - idna_codec, - allow_directives, - ) - assert False # make mypy happy lgtm[py/unreachable-statement] - - -def from_xfr( - xfr: Any, - zone_factory: Any = Zone, - relativize: bool = True, - check_origin: bool = True, -) -> Zone: - """Convert the output of a zone transfer generator into a zone object. - - *xfr*, a generator of ``dns.message.Message`` objects, typically - ``dns.query.xfr()``. - - *relativize*, a ``bool``, determine's whether domain names are - relativized to the zone's origin. The default is ``True``. - It is essential that the relativize setting matches the one specified - to the generator. - - *check_origin*, a ``bool``. If ``True``, the default, then sanity - checks of the origin node will be made by calling the zone's - ``check_origin()`` method. - - Raises ``dns.zone.NoSOA`` if there is no SOA RRset. - - Raises ``dns.zone.NoNS`` if there is no NS RRset. - - Raises ``KeyError`` if there is no origin node. - - Raises ``ValueError`` if no messages are yielded by the generator. - - Returns a subclass of ``dns.zone.Zone``. - """ - - z = None - for r in xfr: - if z is None: - if relativize: - origin = r.origin - else: - origin = r.answer[0].name - rdclass = r.answer[0].rdclass - z = zone_factory(origin, rdclass, relativize=relativize) - for rrset in r.answer: - znode = z.nodes.get(rrset.name) - if not znode: - znode = z.node_factory() - z.nodes[rrset.name] = znode - zrds = znode.find_rdataset(rrset.rdclass, rrset.rdtype, rrset.covers, True) - zrds.update_ttl(rrset.ttl) - for rd in rrset: - zrds.add(rd) - if z is None: - raise ValueError("empty transfer") - if check_origin: - z.check_origin() - return z diff --git a/venv/Lib/site-packages/dns/zonefile.py b/venv/Lib/site-packages/dns/zonefile.py deleted file mode 100644 index d74510b..0000000 --- a/venv/Lib/site-packages/dns/zonefile.py +++ /dev/null @@ -1,744 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -# Copyright (C) 2003-2007, 2009-2011 Nominum, Inc. -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose with or without fee is hereby granted, -# provided that the above copyright notice and this permission notice -# appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -"""DNS Zones.""" - -import re -import sys -from typing import Any, Iterable, List, Optional, Set, Tuple, Union - -import dns.exception -import dns.grange -import dns.name -import dns.node -import dns.rdata -import dns.rdataclass -import dns.rdatatype -import dns.rdtypes.ANY.SOA -import dns.rrset -import dns.tokenizer -import dns.transaction -import dns.ttl - - -class UnknownOrigin(dns.exception.DNSException): - """Unknown origin""" - - -class CNAMEAndOtherData(dns.exception.DNSException): - """A node has a CNAME and other data""" - - -def _check_cname_and_other_data(txn, name, rdataset): - rdataset_kind = dns.node.NodeKind.classify_rdataset(rdataset) - node = txn.get_node(name) - if node is None: - # empty nodes are neutral. - return - node_kind = node.classify() - if ( - node_kind == dns.node.NodeKind.CNAME - and rdataset_kind == dns.node.NodeKind.REGULAR - ): - raise CNAMEAndOtherData("rdataset type is not compatible with a CNAME node") - elif ( - node_kind == dns.node.NodeKind.REGULAR - and rdataset_kind == dns.node.NodeKind.CNAME - ): - raise CNAMEAndOtherData( - "CNAME rdataset is not compatible with a regular data node" - ) - # Otherwise at least one of the node and the rdataset is neutral, so - # adding the rdataset is ok - - -SavedStateType = Tuple[ - dns.tokenizer.Tokenizer, - Optional[dns.name.Name], # current_origin - Optional[dns.name.Name], # last_name - Optional[Any], # current_file - int, # last_ttl - bool, # last_ttl_known - int, # default_ttl - bool, -] # default_ttl_known - - -def _upper_dollarize(s): - s = s.upper() - if not s.startswith("$"): - s = "$" + s - return s - - -class Reader: - """Read a DNS zone file into a transaction.""" - - def __init__( - self, - tok: dns.tokenizer.Tokenizer, - rdclass: dns.rdataclass.RdataClass, - txn: dns.transaction.Transaction, - allow_include: bool = False, - allow_directives: Union[bool, Iterable[str]] = True, - force_name: Optional[dns.name.Name] = None, - force_ttl: Optional[int] = None, - force_rdclass: Optional[dns.rdataclass.RdataClass] = None, - force_rdtype: Optional[dns.rdatatype.RdataType] = None, - default_ttl: Optional[int] = None, - ): - self.tok = tok - (self.zone_origin, self.relativize, _) = txn.manager.origin_information() - self.current_origin = self.zone_origin - self.last_ttl = 0 - self.last_ttl_known = False - if force_ttl is not None: - default_ttl = force_ttl - if default_ttl is None: - self.default_ttl = 0 - self.default_ttl_known = False - else: - self.default_ttl = default_ttl - self.default_ttl_known = True - self.last_name = self.current_origin - self.zone_rdclass = rdclass - self.txn = txn - self.saved_state: List[SavedStateType] = [] - self.current_file: Optional[Any] = None - self.allowed_directives: Set[str] - if allow_directives is True: - self.allowed_directives = {"$GENERATE", "$ORIGIN", "$TTL"} - if allow_include: - self.allowed_directives.add("$INCLUDE") - elif allow_directives is False: - # allow_include was ignored in earlier releases if allow_directives was - # False, so we continue that. - self.allowed_directives = set() - else: - # Note that if directives are explicitly specified, then allow_include - # is ignored. - self.allowed_directives = set(_upper_dollarize(d) for d in allow_directives) - self.force_name = force_name - self.force_ttl = force_ttl - self.force_rdclass = force_rdclass - self.force_rdtype = force_rdtype - self.txn.check_put_rdataset(_check_cname_and_other_data) - - def _eat_line(self): - while 1: - token = self.tok.get() - if token.is_eol_or_eof(): - break - - def _get_identifier(self): - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - return token - - def _rr_line(self): - """Process one line from a DNS zone file.""" - token = None - # Name - if self.force_name is not None: - name = self.force_name - else: - if self.current_origin is None: - raise UnknownOrigin - token = self.tok.get(want_leading=True) - if not token.is_whitespace(): - self.last_name = self.tok.as_name(token, self.current_origin) - else: - token = self.tok.get() - if token.is_eol_or_eof(): - # treat leading WS followed by EOL/EOF as if they were EOL/EOF. - return - self.tok.unget(token) - name = self.last_name - if not name.is_subdomain(self.zone_origin): - self._eat_line() - return - if self.relativize: - name = name.relativize(self.zone_origin) - - # TTL - if self.force_ttl is not None: - ttl = self.force_ttl - self.last_ttl = ttl - self.last_ttl_known = True - else: - token = self._get_identifier() - ttl = None - try: - ttl = dns.ttl.from_text(token.value) - self.last_ttl = ttl - self.last_ttl_known = True - token = None - except dns.ttl.BadTTL: - self.tok.unget(token) - - # Class - if self.force_rdclass is not None: - rdclass = self.force_rdclass - else: - token = self._get_identifier() - try: - rdclass = dns.rdataclass.from_text(token.value) - except dns.exception.SyntaxError: - raise - except Exception: - rdclass = self.zone_rdclass - self.tok.unget(token) - if rdclass != self.zone_rdclass: - raise dns.exception.SyntaxError("RR class is not zone's class") - - if ttl is None: - # support for syntax - token = self._get_identifier() - ttl = None - try: - ttl = dns.ttl.from_text(token.value) - self.last_ttl = ttl - self.last_ttl_known = True - token = None - except dns.ttl.BadTTL: - if self.default_ttl_known: - ttl = self.default_ttl - elif self.last_ttl_known: - ttl = self.last_ttl - self.tok.unget(token) - - # Type - if self.force_rdtype is not None: - rdtype = self.force_rdtype - else: - token = self._get_identifier() - try: - rdtype = dns.rdatatype.from_text(token.value) - except Exception: - raise dns.exception.SyntaxError(f"unknown rdatatype '{token.value}'") - - try: - rd = dns.rdata.from_text( - rdclass, - rdtype, - self.tok, - self.current_origin, - self.relativize, - self.zone_origin, - ) - except dns.exception.SyntaxError: - # Catch and reraise. - raise - except Exception: - # All exceptions that occur in the processing of rdata - # are treated as syntax errors. This is not strictly - # correct, but it is correct almost all of the time. - # We convert them to syntax errors so that we can emit - # helpful filename:line info. - (ty, va) = sys.exc_info()[:2] - raise dns.exception.SyntaxError(f"caught exception {str(ty)}: {str(va)}") - - if not self.default_ttl_known and rdtype == dns.rdatatype.SOA: - # The pre-RFC2308 and pre-BIND9 behavior inherits the zone default - # TTL from the SOA minttl if no $TTL statement is present before the - # SOA is parsed. - self.default_ttl = rd.minimum - self.default_ttl_known = True - if ttl is None: - # if we didn't have a TTL on the SOA, set it! - ttl = rd.minimum - - # TTL check. We had to wait until now to do this as the SOA RR's - # own TTL can be inferred from its minimum. - if ttl is None: - raise dns.exception.SyntaxError("Missing default TTL value") - - self.txn.add(name, ttl, rd) - - def _parse_modify(self, side: str) -> Tuple[str, str, int, int, str]: - # Here we catch everything in '{' '}' in a group so we can replace it - # with ''. - is_generate1 = re.compile(r"^.*\$({(\+|-?)(\d+),(\d+),(.)}).*$") - is_generate2 = re.compile(r"^.*\$({(\+|-?)(\d+)}).*$") - is_generate3 = re.compile(r"^.*\$({(\+|-?)(\d+),(\d+)}).*$") - # Sometimes there are modifiers in the hostname. These come after - # the dollar sign. They are in the form: ${offset[,width[,base]]}. - # Make names - mod = "" - sign = "+" - offset = "0" - width = "0" - base = "d" - g1 = is_generate1.match(side) - if g1: - mod, sign, offset, width, base = g1.groups() - if sign == "": - sign = "+" - else: - g2 = is_generate2.match(side) - if g2: - mod, sign, offset = g2.groups() - if sign == "": - sign = "+" - width = "0" - base = "d" - else: - g3 = is_generate3.match(side) - if g3: - mod, sign, offset, width = g3.groups() - if sign == "": - sign = "+" - base = "d" - - ioffset = int(offset) - iwidth = int(width) - - if sign not in ["+", "-"]: - raise dns.exception.SyntaxError(f"invalid offset sign {sign}") - if base not in ["d", "o", "x", "X", "n", "N"]: - raise dns.exception.SyntaxError(f"invalid type {base}") - - return mod, sign, ioffset, iwidth, base - - def _generate_line(self): - # range lhs [ttl] [class] type rhs [ comment ] - """Process one line containing the GENERATE statement from a DNS - zone file.""" - if self.current_origin is None: - raise UnknownOrigin - - token = self.tok.get() - # Range (required) - try: - start, stop, step = dns.grange.from_text(token.value) - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except Exception: - raise dns.exception.SyntaxError - - # lhs (required) - try: - lhs = token.value - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except Exception: - raise dns.exception.SyntaxError - - # TTL - try: - ttl = dns.ttl.from_text(token.value) - self.last_ttl = ttl - self.last_ttl_known = True - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except dns.ttl.BadTTL: - if not (self.last_ttl_known or self.default_ttl_known): - raise dns.exception.SyntaxError("Missing default TTL value") - if self.default_ttl_known: - ttl = self.default_ttl - elif self.last_ttl_known: - ttl = self.last_ttl - # Class - try: - rdclass = dns.rdataclass.from_text(token.value) - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except dns.exception.SyntaxError: - raise dns.exception.SyntaxError - except Exception: - rdclass = self.zone_rdclass - if rdclass != self.zone_rdclass: - raise dns.exception.SyntaxError("RR class is not zone's class") - # Type - try: - rdtype = dns.rdatatype.from_text(token.value) - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError - except Exception: - raise dns.exception.SyntaxError(f"unknown rdatatype '{token.value}'") - - # rhs (required) - rhs = token.value - - def _calculate_index(counter: int, offset_sign: str, offset: int) -> int: - """Calculate the index from the counter and offset.""" - if offset_sign == "-": - offset *= -1 - return counter + offset - - def _format_index(index: int, base: str, width: int) -> str: - """Format the index with the given base, and zero-fill it - to the given width.""" - if base in ["d", "o", "x", "X"]: - return format(index, base).zfill(width) - - # base can only be n or N here - hexa = _format_index(index, "x", width) - nibbles = ".".join(hexa[::-1])[:width] - if base == "N": - nibbles = nibbles.upper() - return nibbles - - lmod, lsign, loffset, lwidth, lbase = self._parse_modify(lhs) - rmod, rsign, roffset, rwidth, rbase = self._parse_modify(rhs) - for i in range(start, stop + 1, step): - # +1 because bind is inclusive and python is exclusive - - lindex = _calculate_index(i, lsign, loffset) - rindex = _calculate_index(i, rsign, roffset) - - lzfindex = _format_index(lindex, lbase, lwidth) - rzfindex = _format_index(rindex, rbase, rwidth) - - name = lhs.replace(f"${lmod}", lzfindex) - rdata = rhs.replace(f"${rmod}", rzfindex) - - self.last_name = dns.name.from_text( - name, self.current_origin, self.tok.idna_codec - ) - name = self.last_name - if not name.is_subdomain(self.zone_origin): - self._eat_line() - return - if self.relativize: - name = name.relativize(self.zone_origin) - - try: - rd = dns.rdata.from_text( - rdclass, - rdtype, - rdata, - self.current_origin, - self.relativize, - self.zone_origin, - ) - except dns.exception.SyntaxError: - # Catch and reraise. - raise - except Exception: - # All exceptions that occur in the processing of rdata - # are treated as syntax errors. This is not strictly - # correct, but it is correct almost all of the time. - # We convert them to syntax errors so that we can emit - # helpful filename:line info. - (ty, va) = sys.exc_info()[:2] - raise dns.exception.SyntaxError( - f"caught exception {str(ty)}: {str(va)}" - ) - - self.txn.add(name, ttl, rd) - - def read(self) -> None: - """Read a DNS zone file and build a zone object. - - @raises dns.zone.NoSOA: No SOA RR was found at the zone origin - @raises dns.zone.NoNS: No NS RRset was found at the zone origin - """ - - try: - while 1: - token = self.tok.get(True, True) - if token.is_eof(): - if self.current_file is not None: - self.current_file.close() - if len(self.saved_state) > 0: - ( - self.tok, - self.current_origin, - self.last_name, - self.current_file, - self.last_ttl, - self.last_ttl_known, - self.default_ttl, - self.default_ttl_known, - ) = self.saved_state.pop(-1) - continue - break - elif token.is_eol(): - continue - elif token.is_comment(): - self.tok.get_eol() - continue - elif token.value[0] == "$" and len(self.allowed_directives) > 0: - # Note that we only run directive processing code if at least - # one directive is allowed in order to be backwards compatible - c = token.value.upper() - if c not in self.allowed_directives: - raise dns.exception.SyntaxError( - f"zone file directive '{c}' is not allowed" - ) - if c == "$TTL": - token = self.tok.get() - if not token.is_identifier(): - raise dns.exception.SyntaxError("bad $TTL") - self.default_ttl = dns.ttl.from_text(token.value) - self.default_ttl_known = True - self.tok.get_eol() - elif c == "$ORIGIN": - self.current_origin = self.tok.get_name() - self.tok.get_eol() - if self.zone_origin is None: - self.zone_origin = self.current_origin - self.txn._set_origin(self.current_origin) - elif c == "$INCLUDE": - token = self.tok.get() - filename = token.value - token = self.tok.get() - new_origin: Optional[dns.name.Name] - if token.is_identifier(): - new_origin = dns.name.from_text( - token.value, self.current_origin, self.tok.idna_codec - ) - self.tok.get_eol() - elif not token.is_eol_or_eof(): - raise dns.exception.SyntaxError("bad origin in $INCLUDE") - else: - new_origin = self.current_origin - self.saved_state.append( - ( - self.tok, - self.current_origin, - self.last_name, - self.current_file, - self.last_ttl, - self.last_ttl_known, - self.default_ttl, - self.default_ttl_known, - ) - ) - self.current_file = open(filename) - self.tok = dns.tokenizer.Tokenizer(self.current_file, filename) - self.current_origin = new_origin - elif c == "$GENERATE": - self._generate_line() - else: - raise dns.exception.SyntaxError( - f"Unknown zone file directive '{c}'" - ) - continue - self.tok.unget(token) - self._rr_line() - except dns.exception.SyntaxError as detail: - (filename, line_number) = self.tok.where() - if detail is None: - detail = "syntax error" - ex = dns.exception.SyntaxError( - "%s:%d: %s" % (filename, line_number, detail) - ) - tb = sys.exc_info()[2] - raise ex.with_traceback(tb) from None - - -class RRsetsReaderTransaction(dns.transaction.Transaction): - def __init__(self, manager, replacement, read_only): - assert not read_only - super().__init__(manager, replacement, read_only) - self.rdatasets = {} - - def _get_rdataset(self, name, rdtype, covers): - return self.rdatasets.get((name, rdtype, covers)) - - def _get_node(self, name): - rdatasets = [] - for (rdataset_name, _, _), rdataset in self.rdatasets.items(): - if name == rdataset_name: - rdatasets.append(rdataset) - if len(rdatasets) == 0: - return None - node = dns.node.Node() - node.rdatasets = rdatasets - return node - - def _put_rdataset(self, name, rdataset): - self.rdatasets[(name, rdataset.rdtype, rdataset.covers)] = rdataset - - def _delete_name(self, name): - # First remove any changes involving the name - remove = [] - for key in self.rdatasets: - if key[0] == name: - remove.append(key) - if len(remove) > 0: - for key in remove: - del self.rdatasets[key] - - def _delete_rdataset(self, name, rdtype, covers): - try: - del self.rdatasets[(name, rdtype, covers)] - except KeyError: - pass - - def _name_exists(self, name): - for n, _, _ in self.rdatasets: - if n == name: - return True - return False - - def _changed(self): - return len(self.rdatasets) > 0 - - def _end_transaction(self, commit): - if commit and self._changed(): - rrsets = [] - for (name, _, _), rdataset in self.rdatasets.items(): - rrset = dns.rrset.RRset( - name, rdataset.rdclass, rdataset.rdtype, rdataset.covers - ) - rrset.update(rdataset) - rrsets.append(rrset) - self.manager.set_rrsets(rrsets) - - def _set_origin(self, origin): - pass - - def _iterate_rdatasets(self): - raise NotImplementedError # pragma: no cover - - def _iterate_names(self): - raise NotImplementedError # pragma: no cover - - -class RRSetsReaderManager(dns.transaction.TransactionManager): - def __init__( - self, origin=dns.name.root, relativize=False, rdclass=dns.rdataclass.IN - ): - self.origin = origin - self.relativize = relativize - self.rdclass = rdclass - self.rrsets = [] - - def reader(self): # pragma: no cover - raise NotImplementedError - - def writer(self, replacement=False): - assert replacement is True - return RRsetsReaderTransaction(self, True, False) - - def get_class(self): - return self.rdclass - - def origin_information(self): - if self.relativize: - effective = dns.name.empty - else: - effective = self.origin - return (self.origin, self.relativize, effective) - - def set_rrsets(self, rrsets): - self.rrsets = rrsets - - -def read_rrsets( - text: Any, - name: Optional[Union[dns.name.Name, str]] = None, - ttl: Optional[int] = None, - rdclass: Optional[Union[dns.rdataclass.RdataClass, str]] = dns.rdataclass.IN, - default_rdclass: Union[dns.rdataclass.RdataClass, str] = dns.rdataclass.IN, - rdtype: Optional[Union[dns.rdatatype.RdataType, str]] = None, - default_ttl: Optional[Union[int, str]] = None, - idna_codec: Optional[dns.name.IDNACodec] = None, - origin: Optional[Union[dns.name.Name, str]] = dns.name.root, - relativize: bool = False, -) -> List[dns.rrset.RRset]: - """Read one or more rrsets from the specified text, possibly subject - to restrictions. - - *text*, a file object or a string, is the input to process. - - *name*, a string, ``dns.name.Name``, or ``None``, is the owner name of - the rrset. If not ``None``, then the owner name is "forced", and the - input must not specify an owner name. If ``None``, then any owner names - are allowed and must be present in the input. - - *ttl*, an ``int``, string, or None. If not ``None``, the the TTL is - forced to be the specified value and the input must not specify a TTL. - If ``None``, then a TTL may be specified in the input. If it is not - specified, then the *default_ttl* will be used. - - *rdclass*, a ``dns.rdataclass.RdataClass``, string, or ``None``. If - not ``None``, then the class is forced to the specified value, and the - input must not specify a class. If ``None``, then the input may specify - a class that matches *default_rdclass*. Note that it is not possible to - return rrsets with differing classes; specifying ``None`` for the class - simply allows the user to optionally type a class as that may be convenient - when cutting and pasting. - - *default_rdclass*, a ``dns.rdataclass.RdataClass`` or string. The class - of the returned rrsets. - - *rdtype*, a ``dns.rdatatype.RdataType``, string, or ``None``. If not - ``None``, then the type is forced to the specified value, and the - input must not specify a type. If ``None``, then a type must be present - for each RR. - - *default_ttl*, an ``int``, string, or ``None``. If not ``None``, then if - the TTL is not forced and is not specified, then this value will be used. - if ``None``, then if the TTL is not forced an error will occur if the TTL - is not specified. - - *idna_codec*, a ``dns.name.IDNACodec``, specifies the IDNA - encoder/decoder. If ``None``, the default IDNA 2003 encoder/decoder - is used. Note that codecs only apply to the owner name; dnspython does - not do IDNA for names in rdata, as there is no IDNA zonefile format. - - *origin*, a string, ``dns.name.Name``, or ``None``, is the origin for any - relative names in the input, and also the origin to relativize to if - *relativize* is ``True``. - - *relativize*, a bool. If ``True``, names are relativized to the *origin*; - if ``False`` then any relative names in the input are made absolute by - appending the *origin*. - """ - if isinstance(origin, str): - origin = dns.name.from_text(origin, dns.name.root, idna_codec) - if isinstance(name, str): - name = dns.name.from_text(name, origin, idna_codec) - if isinstance(ttl, str): - ttl = dns.ttl.from_text(ttl) - if isinstance(default_ttl, str): - default_ttl = dns.ttl.from_text(default_ttl) - if rdclass is not None: - rdclass = dns.rdataclass.RdataClass.make(rdclass) - else: - rdclass = None - default_rdclass = dns.rdataclass.RdataClass.make(default_rdclass) - if rdtype is not None: - rdtype = dns.rdatatype.RdataType.make(rdtype) - else: - rdtype = None - manager = RRSetsReaderManager(origin, relativize, default_rdclass) - with manager.writer(True) as txn: - tok = dns.tokenizer.Tokenizer(text, "", idna_codec=idna_codec) - reader = Reader( - tok, - default_rdclass, - txn, - allow_directives=False, - force_name=name, - force_ttl=ttl, - force_rdclass=rdclass, - force_rdtype=rdtype, - default_ttl=default_ttl, - ) - reader.read() - return manager.rrsets diff --git a/venv/Lib/site-packages/dns/zonetypes.py b/venv/Lib/site-packages/dns/zonetypes.py deleted file mode 100644 index 195ee2e..0000000 --- a/venv/Lib/site-packages/dns/zonetypes.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license - -"""Common zone-related types.""" - -# This is a separate file to avoid import circularity between dns.zone and -# the implementation of the ZONEMD type. - -import hashlib - -import dns.enum - - -class DigestScheme(dns.enum.IntEnum): - """ZONEMD Scheme""" - - SIMPLE = 1 - - @classmethod - def _maximum(cls): - return 255 - - -class DigestHashAlgorithm(dns.enum.IntEnum): - """ZONEMD Hash Algorithm""" - - SHA384 = 1 - SHA512 = 2 - - @classmethod - def _maximum(cls): - return 255 - - -_digest_hashers = { - DigestHashAlgorithm.SHA384: hashlib.sha384, - DigestHashAlgorithm.SHA512: hashlib.sha512, -} diff --git a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/INSTALLER b/venv/Lib/site-packages/dnspython-2.7.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/METADATA b/venv/Lib/site-packages/dnspython-2.7.0.dist-info/METADATA deleted file mode 100644 index ca4a4f4..0000000 --- a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/METADATA +++ /dev/null @@ -1,149 +0,0 @@ -Metadata-Version: 2.3 -Name: dnspython -Version: 2.7.0 -Summary: DNS toolkit -Project-URL: homepage, https://www.dnspython.org -Project-URL: repository, https://github.com/rthalley/dnspython.git -Project-URL: documentation, https://dnspython.readthedocs.io/en/stable/ -Project-URL: issues, https://github.com/rthalley/dnspython/issues -Author-email: Bob Halley -License: ISC -License-File: LICENSE -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: System Administrators -Classifier: License :: OSI Approved :: ISC License (ISCL) -Classifier: Operating System :: Microsoft :: Windows -Classifier: Operating System :: POSIX -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -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: Topic :: Internet :: Name Service (DNS) -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Requires-Python: >=3.9 -Provides-Extra: dev -Requires-Dist: black>=23.1.0; extra == 'dev' -Requires-Dist: coverage>=7.0; extra == 'dev' -Requires-Dist: flake8>=7; extra == 'dev' -Requires-Dist: hypercorn>=0.16.0; extra == 'dev' -Requires-Dist: mypy>=1.8; extra == 'dev' -Requires-Dist: pylint>=3; extra == 'dev' -Requires-Dist: pytest-cov>=4.1.0; extra == 'dev' -Requires-Dist: pytest>=7.4; extra == 'dev' -Requires-Dist: quart-trio>=0.11.0; extra == 'dev' -Requires-Dist: sphinx-rtd-theme>=2.0.0; extra == 'dev' -Requires-Dist: sphinx>=7.2.0; extra == 'dev' -Requires-Dist: twine>=4.0.0; extra == 'dev' -Requires-Dist: wheel>=0.42.0; extra == 'dev' -Provides-Extra: dnssec -Requires-Dist: cryptography>=43; extra == 'dnssec' -Provides-Extra: doh -Requires-Dist: h2>=4.1.0; extra == 'doh' -Requires-Dist: httpcore>=1.0.0; extra == 'doh' -Requires-Dist: httpx>=0.26.0; extra == 'doh' -Provides-Extra: doq -Requires-Dist: aioquic>=1.0.0; extra == 'doq' -Provides-Extra: idna -Requires-Dist: idna>=3.7; extra == 'idna' -Provides-Extra: trio -Requires-Dist: trio>=0.23; extra == 'trio' -Provides-Extra: wmi -Requires-Dist: wmi>=1.5.1; extra == 'wmi' -Description-Content-Type: text/markdown - -# dnspython - -[![Build Status](https://github.com/rthalley/dnspython/actions/workflows/ci.yml/badge.svg)](https://github.com/rthalley/dnspython/actions/) -[![Documentation Status](https://readthedocs.org/projects/dnspython/badge/?version=latest)](https://dnspython.readthedocs.io/en/latest/?badge=latest) -[![PyPI version](https://badge.fury.io/py/dnspython.svg)](https://badge.fury.io/py/dnspython) -[![License: ISC](https://img.shields.io/badge/License-ISC-brightgreen.svg)](https://opensource.org/licenses/ISC) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) - -## INTRODUCTION - -dnspython is a DNS toolkit for Python. It supports almost all record types. It -can be used for queries, zone transfers, and dynamic updates. It supports TSIG -authenticated messages and EDNS0. - -dnspython provides both high and low level access to DNS. The high level classes -perform queries for data of a given name, type, and class, and return an answer -set. The low level classes allow direct manipulation of DNS zones, messages, -names, and records. - -To see a few of the ways dnspython can be used, look in the `examples/` -directory. - -dnspython is a utility to work with DNS, `/etc/hosts` is thus not used. For -simple forward DNS lookups, it's better to use `socket.getaddrinfo()` or -`socket.gethostbyname()`. - -dnspython originated at Nominum where it was developed -to facilitate the testing of DNS software. - -## ABOUT THIS RELEASE - -This is dnspython 2.7.0. -Please read -[What's New](https://dnspython.readthedocs.io/en/stable/whatsnew.html) for -information about the changes in this release. - -## INSTALLATION - -* Many distributions have dnspython packaged for you, so you should - check there first. -* To use a wheel downloaded from PyPi, run: - - pip install dnspython - -* To install from the source code, go into the top-level of the source code - and run: - -``` - pip install --upgrade pip build - python -m build - pip install dist/*.whl -``` - -* To install the latest from the main branch, run `pip install git+https://github.com/rthalley/dnspython.git` - -Dnspython's default installation does not depend on any modules other than -those in the Python standard library. To use some features, additional modules -must be installed. For convenience, pip options are defined for the -requirements. - -If you want to use DNS-over-HTTPS, run -`pip install dnspython[doh]`. - -If you want to use DNSSEC functionality, run -`pip install dnspython[dnssec]`. - -If you want to use internationalized domain names (IDNA) -functionality, you must run -`pip install dnspython[idna]` - -If you want to use the Trio asynchronous I/O package, run -`pip install dnspython[trio]`. - -If you want to use WMI on Windows to determine the active DNS settings -instead of the default registry scanning method, run -`pip install dnspython[wmi]`. - -If you want to try the experimental DNS-over-QUIC code, run -`pip install dnspython[doq]`. - -Note that you can install any combination of the above, e.g.: -`pip install dnspython[doh,dnssec,idna]` - -### Notices - -Python 2.x support ended with the release of 1.16.0. Dnspython 2.6.x supports -Python 3.8 and later, though support for 3.8 ends on October 14, 2024. -Dnspython 2.7.x supports Python 3.9 and later. Future support is aligned with the -lifetime of the Python 3 versions. - -Documentation has moved to -[dnspython.readthedocs.io](https://dnspython.readthedocs.io). diff --git a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/RECORD b/venv/Lib/site-packages/dnspython-2.7.0.dist-info/RECORD deleted file mode 100644 index 6794b95..0000000 --- a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/RECORD +++ /dev/null @@ -1,294 +0,0 @@ -dns/__init__.py,sha256=YJZtDG14Idw5ui3h1nWooSwPM9gsxQgB8M0GBZ3aly0,1663 -dns/__pycache__/__init__.cpython-310.pyc,, -dns/__pycache__/_asyncbackend.cpython-310.pyc,, -dns/__pycache__/_asyncio_backend.cpython-310.pyc,, -dns/__pycache__/_ddr.cpython-310.pyc,, -dns/__pycache__/_features.cpython-310.pyc,, -dns/__pycache__/_immutable_ctx.cpython-310.pyc,, -dns/__pycache__/_trio_backend.cpython-310.pyc,, -dns/__pycache__/asyncbackend.cpython-310.pyc,, -dns/__pycache__/asyncquery.cpython-310.pyc,, -dns/__pycache__/asyncresolver.cpython-310.pyc,, -dns/__pycache__/dnssec.cpython-310.pyc,, -dns/__pycache__/dnssectypes.cpython-310.pyc,, -dns/__pycache__/e164.cpython-310.pyc,, -dns/__pycache__/edns.cpython-310.pyc,, -dns/__pycache__/entropy.cpython-310.pyc,, -dns/__pycache__/enum.cpython-310.pyc,, -dns/__pycache__/exception.cpython-310.pyc,, -dns/__pycache__/flags.cpython-310.pyc,, -dns/__pycache__/grange.cpython-310.pyc,, -dns/__pycache__/immutable.cpython-310.pyc,, -dns/__pycache__/inet.cpython-310.pyc,, -dns/__pycache__/ipv4.cpython-310.pyc,, -dns/__pycache__/ipv6.cpython-310.pyc,, -dns/__pycache__/message.cpython-310.pyc,, -dns/__pycache__/name.cpython-310.pyc,, -dns/__pycache__/namedict.cpython-310.pyc,, -dns/__pycache__/nameserver.cpython-310.pyc,, -dns/__pycache__/node.cpython-310.pyc,, -dns/__pycache__/opcode.cpython-310.pyc,, -dns/__pycache__/query.cpython-310.pyc,, -dns/__pycache__/rcode.cpython-310.pyc,, -dns/__pycache__/rdata.cpython-310.pyc,, -dns/__pycache__/rdataclass.cpython-310.pyc,, -dns/__pycache__/rdataset.cpython-310.pyc,, -dns/__pycache__/rdatatype.cpython-310.pyc,, -dns/__pycache__/renderer.cpython-310.pyc,, -dns/__pycache__/resolver.cpython-310.pyc,, -dns/__pycache__/reversename.cpython-310.pyc,, -dns/__pycache__/rrset.cpython-310.pyc,, -dns/__pycache__/serial.cpython-310.pyc,, -dns/__pycache__/set.cpython-310.pyc,, -dns/__pycache__/tokenizer.cpython-310.pyc,, -dns/__pycache__/transaction.cpython-310.pyc,, -dns/__pycache__/tsig.cpython-310.pyc,, -dns/__pycache__/tsigkeyring.cpython-310.pyc,, -dns/__pycache__/ttl.cpython-310.pyc,, -dns/__pycache__/update.cpython-310.pyc,, -dns/__pycache__/version.cpython-310.pyc,, -dns/__pycache__/versioned.cpython-310.pyc,, -dns/__pycache__/win32util.cpython-310.pyc,, -dns/__pycache__/wire.cpython-310.pyc,, -dns/__pycache__/xfr.cpython-310.pyc,, -dns/__pycache__/zone.cpython-310.pyc,, -dns/__pycache__/zonefile.cpython-310.pyc,, -dns/__pycache__/zonetypes.cpython-310.pyc,, -dns/_asyncbackend.py,sha256=pamIAWJ73e7ic2u7Q3RJyG6_6L8t78ccttvi65682MM,2396 -dns/_asyncio_backend.py,sha256=iLqhcUXqnFWC_2tcAp9U00NOGxT5GKPn4qeXS4iKaro,9051 -dns/_ddr.py,sha256=rHXKC8kncCTT9N4KBh1flicl79nyDjQ-DDvq30MJ3B8,5247 -dns/_features.py,sha256=Ig_leAKUT9RDiOVOfA0nXmmqpiPfnOnP9TcxlISUGSk,2492 -dns/_immutable_ctx.py,sha256=gtoCLMmdHXI23zt5lRSIS3A4Ca3jZJngebdoFFOtiwU,2459 -dns/_trio_backend.py,sha256=IXNdUP1MUBPyZRgAFhGH71KHtUCh3Rm5dM8SX4bMj2U,8473 -dns/asyncbackend.py,sha256=82fXTFls_m7F_ekQbgUGOkoBbs4BI-GBLDZAWNGUvJ0,2796 -dns/asyncquery.py,sha256=PMZ_D4Z8vgSioWHftyxNw7eax1IqrPleqY5FIi40hd8,30821 -dns/asyncresolver.py,sha256=GD86dCyW9YGKs6SggWXwBKEXifW7Qdx4cEAGFKY6fA4,17852 -dns/dnssec.py,sha256=gXmIrbKK1t1hE8ht-WlhUc0giy1PpLYj07r6o0pVATY,41717 -dns/dnssecalgs/__init__.py,sha256=OWvTadxZ3oF5PxVGodNimxBt_-3YUNTOSV62HrIb4PQ,4331 -dns/dnssecalgs/__pycache__/__init__.cpython-310.pyc,, -dns/dnssecalgs/__pycache__/base.cpython-310.pyc,, -dns/dnssecalgs/__pycache__/cryptography.cpython-310.pyc,, -dns/dnssecalgs/__pycache__/dsa.cpython-310.pyc,, -dns/dnssecalgs/__pycache__/ecdsa.cpython-310.pyc,, -dns/dnssecalgs/__pycache__/eddsa.cpython-310.pyc,, -dns/dnssecalgs/__pycache__/rsa.cpython-310.pyc,, -dns/dnssecalgs/base.py,sha256=jlTV_nd1Nqkvqyf-FVHIccXKFrE2LL6GVu6AW8QUh2E,2513 -dns/dnssecalgs/cryptography.py,sha256=3uqMfRm-zCkJPOrxUqlu9CmdxIMy71dVor9eAHi0wZM,2425 -dns/dnssecalgs/dsa.py,sha256=DNO68g_lbG7_oKcDN8c2xuzYRPbLaZc9Ns7oQoa0Vbc,3564 -dns/dnssecalgs/ecdsa.py,sha256=RfvFKRNExsYgd5SoXXRxMHkoBeF2Gktkz2rOwObEYAY,3172 -dns/dnssecalgs/eddsa.py,sha256=7VGARpVUzIYRjPh0gFapTPFzmsK8WJDqDZDLw2KLc8w,1981 -dns/dnssecalgs/rsa.py,sha256=_tNABpr6iwd8STBEHYIXfyLrgBpRNCj8K0UQj32_kOU,3622 -dns/dnssectypes.py,sha256=CyeuGTS_rM3zXr8wD9qMT9jkzvVfTY2JWckUcogG83E,1799 -dns/e164.py,sha256=EsK8cnOtOx7kQ0DmSwibcwkzp6efMWjbRiTyHZO8Q-M,3978 -dns/edns.py,sha256=-XDhC2jr7BRLsJrpCAWShxLn-3eG1oI0HhduWhLxdMw,17089 -dns/entropy.py,sha256=qkG8hXDLzrJS6R5My26iA59c0RhPwJNzuOhOCAZU5Bw,4242 -dns/enum.py,sha256=EepaunPKixTSrascy7iAe9UQEXXxP_MB5Gx4jUpHIhg,3691 -dns/exception.py,sha256=8vjxLf4T3T77vfANe_iKVeButAEhSJve6UrPjiBzht4,5953 -dns/flags.py,sha256=cQ3kTFyvcKiWHAxI5AwchNqxVOrsIrgJ6brgrH42Wq8,2750 -dns/grange.py,sha256=D016OrOv3i44G3mb_CzPFjDk61uZ6BMRib3yJnDQvbw,2144 -dns/immutable.py,sha256=InrtpKvPxl-74oYbzsyneZwAuX78hUqeG22f2aniZbk,2017 -dns/inet.py,sha256=j6jQs3K_ehVhDv-i4jwCKePr5HpEiSzvOXQ4uhgn1sU,5772 -dns/ipv4.py,sha256=qEUXtlqWDH_blicj6VMvyQhfX7-BF0gB_lWJliV-2FI,2552 -dns/ipv6.py,sha256=Ww8ayshM6FxtQsRYdXXuKkPFTad5ZcGbBd9lr1nFct4,6554 -dns/message.py,sha256=QOtdFBEAORhTKN0uQg86uSNvthdxJx40HhMQXYCBHng,68185 -dns/name.py,sha256=Bf3170QHhLFLDnMsWeJyik4i9ucBDbIY6Bydcz8H-2o,42778 -dns/namedict.py,sha256=hJRYpKeQv6Bd2LaUOPV0L_a0eXEIuqgggPXaH4c3Tow,4000 -dns/nameserver.py,sha256=hH4LLOkB4jeyO3VDUWK0lNpMJNNt_cFYf23-HdhpSmE,10115 -dns/node.py,sha256=NGZa0AUMq-CNledJ6wn1Rx6TFYc703cH2OraLysoNWM,12663 -dns/opcode.py,sha256=I6JyuFUL0msja_BYm6bzXHfbbfqUod_69Ss4xcv8xWQ,2730 -dns/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -dns/query.py,sha256=_Ev7EivZNEpgrUiPIn4BVnDRFCizcayHHcBXt0Ju3As,56298 -dns/quic/__init__.py,sha256=S5_2UuYzSU_LLtrLAf8DHh3KqNF2YHeKJ_-Wv991WlI,2272 -dns/quic/__pycache__/__init__.cpython-310.pyc,, -dns/quic/__pycache__/_asyncio.cpython-310.pyc,, -dns/quic/__pycache__/_common.cpython-310.pyc,, -dns/quic/__pycache__/_sync.cpython-310.pyc,, -dns/quic/__pycache__/_trio.cpython-310.pyc,, -dns/quic/_asyncio.py,sha256=dnABPz5f-JOJsA7D_BdPfuyzpkL_87AaY4CUcmgNj-g,9870 -dns/quic/_common.py,sha256=koWf6rq9_gUorIOV60QZKAHwZF5MuSgQvBznzA5rGzk,10857 -dns/quic/_sync.py,sha256=QF-dW19NwiDW_BDoJZkSQmHz2uEpfgedsUKTPc0JAio,10436 -dns/quic/_trio.py,sha256=01HH4_hU1VRx-BWXl8bQo4-LZem_eKRBNy6RolTZZXY,9248 -dns/rcode.py,sha256=N6JjrIQjCdJy0boKIp8Hcky5tm__LSDscpDz3rE_sgU,4156 -dns/rdata.py,sha256=uk82eldqpWR8L2zp_CB8JG6wWWfK7zdYowWISfMC2XE,31022 -dns/rdataclass.py,sha256=TK4W4ywB1L_X7EZqk2Gmwnu7vdQpolQF5DtQWyNk5xo,2984 -dns/rdataset.py,sha256=BMNvGAzE4HfYHA-pnhsKwELfpr-saz73BzYwMucoKj0,16664 -dns/rdatatype.py,sha256=wgKWnu4mAbXnmG8wKHpV8dZHkhMqNeSsWWlWFo5HcDY,7448 -dns/rdtypes/ANY/AFSDB.py,sha256=k75wMwreF1DAfDymu4lHh16BUx7ulVP3PLeQBZnkurY,1661 -dns/rdtypes/ANY/AMTRELAY.py,sha256=19jfS61mT1CQT-8vf67ZylhDS9JVRVp4WCbFE-7l0jM,3381 -dns/rdtypes/ANY/AVC.py,sha256=SpsXYzlBirRWN0mGnQe0MdN6H8fvlgXPJX5PjOHnEak,1024 -dns/rdtypes/ANY/CAA.py,sha256=AHh59Is-4WiVWd26yovnPM3hXqKS-yx7IWfXSS0NZhE,2511 -dns/rdtypes/ANY/CDNSKEY.py,sha256=bJAdrBMsFHIJz8TF1AxZoNbdxVWBCRTG-bR_uR_r_G4,1225 -dns/rdtypes/ANY/CDS.py,sha256=Y9nIRUCAabztVLbxm2SXAdYapFemCOUuGh5JqroCDUs,1163 -dns/rdtypes/ANY/CERT.py,sha256=2Cu2LQM6-K4darqhHv1EM_blmpYpnrBIIX1GnL_rxKE,3533 -dns/rdtypes/ANY/CNAME.py,sha256=IHGGq2BDpeKUahTr1pvyBQgm0NGBI_vQ3Vs5mKTXO4w,1206 -dns/rdtypes/ANY/CSYNC.py,sha256=KkZ_rG6PfeL14il97nmJGWWmUGGS5o9nd2EqbJqOuYo,2439 -dns/rdtypes/ANY/DLV.py,sha256=J-pOrw5xXsDoaB9G0r6znlYXJtqtcqhsl1OXs6CPRU4,986 -dns/rdtypes/ANY/DNAME.py,sha256=yqXRtx4dAWwB4YCCv-qW6uaxeGhg2LPQ2uyKwWaMdXs,1150 -dns/rdtypes/ANY/DNSKEY.py,sha256=MD8HUVH5XXeAGOnFWg5aVz_w-2tXYwCeVXmzExhiIeQ,1223 -dns/rdtypes/ANY/DS.py,sha256=_gf8vk1O_uY8QXFjsfUw-bny-fm6e-QpCk3PT0JCyoM,995 -dns/rdtypes/ANY/EUI48.py,sha256=x0BkK0sY_tgzuCwfDYpw6tyuChHjjtbRpAgYhO0Y44o,1151 -dns/rdtypes/ANY/EUI64.py,sha256=1jCff2-SXHJLDnNDnMW8Cd_o-ok0P3x6zKy_bcCU5h4,1161 -dns/rdtypes/ANY/GPOS.py,sha256=u4qwiDBVoC7bsKfxDKGbPjnOKddpdjy2p1AhziDWcPw,4439 -dns/rdtypes/ANY/HINFO.py,sha256=D2WvjTsvD_XqT8BepBIyjPL2iYGMgYqb1VQa9ApO0qE,2217 -dns/rdtypes/ANY/HIP.py,sha256=c32Ewlk88schJ1nPOmT5BVR60ttIM-uH8I8LaRAkFOA,3226 -dns/rdtypes/ANY/ISDN.py,sha256=L4C2Rxrr4JJN17lmJRbZN8RhM_ujjwIskY_4V4Gd3r4,2723 -dns/rdtypes/ANY/L32.py,sha256=TMz2kdGCd0siiQZyiocVDCSnvkOdjhUuYRFyf8o622M,1286 -dns/rdtypes/ANY/L64.py,sha256=sb2BjuPA0PQt67nEyT9rBt759C9e6lH71d3EJHGGnww,1592 -dns/rdtypes/ANY/LOC.py,sha256=NZKIUJULZ3BcK1-gnb2Mk76Pc4UUZry47C5n9VBvhnk,11995 -dns/rdtypes/ANY/LP.py,sha256=wTsKIjtK6vh66qZRLSsiE0k54GO8ieVBGZH8dzVvFnE,1338 -dns/rdtypes/ANY/MX.py,sha256=qQk83idY0-SbRMDmB15JOpJi7cSyiheF-ALUD0Ev19E,995 -dns/rdtypes/ANY/NID.py,sha256=N7Xx4kXf3yVAocTlCXQeJ3BtiQNPFPQVdL1iMuyl5W4,1544 -dns/rdtypes/ANY/NINFO.py,sha256=bdL_-6Bejb2EH-xwR1rfSr_9E3SDXLTAnov7x2924FI,1041 -dns/rdtypes/ANY/NS.py,sha256=ThfaPalUlhbyZyNyvBM3k-7onl3eJKq5wCORrOGtkMM,995 -dns/rdtypes/ANY/NSEC.py,sha256=kicEYxcKaLBpV6C_M8cHdDaqBoiYl6EYtPvjyR6kExI,2465 -dns/rdtypes/ANY/NSEC3.py,sha256=696h-Zz30bmcT0n1rqoEtS5wqE6jIgsVGzaw5TfdGJo,4331 -dns/rdtypes/ANY/NSEC3PARAM.py,sha256=08p6NWS4DiLav1wOuPbxUxB9MtY2IPjfOMCtJwzzMuA,2635 -dns/rdtypes/ANY/OPENPGPKEY.py,sha256=Va0FGo_8vm1OeX62N5iDTWukAdLwrjTXIZeQ6oanE78,1851 -dns/rdtypes/ANY/OPT.py,sha256=W36RslT_Psp95OPUC70knumOYjKpaRHvGT27I-NV2qc,2561 -dns/rdtypes/ANY/PTR.py,sha256=5HcR1D77Otyk91vVY4tmqrfZfSxSXWyWvwIW-rIH5gc,997 -dns/rdtypes/ANY/RESINFO.py,sha256=Kf2NcKbkeI5gFE1bJfQNqQCaitYyXfV_9nQYl1luUZ0,1008 -dns/rdtypes/ANY/RP.py,sha256=8doJlhjYDYiAT6KNF1mAaemJ20YJFUPvit8LOx4-I-U,2174 -dns/rdtypes/ANY/RRSIG.py,sha256=O8vwzS7ldfaj_x8DypvEGFsDSb7al-D7OEnprA3QQoo,4922 -dns/rdtypes/ANY/RT.py,sha256=2t9q3FZQ28iEyceeU25KU2Ur0T5JxELAu8BTwfOUgVw,1013 -dns/rdtypes/ANY/SMIMEA.py,sha256=6yjHuVDfIEodBU9wxbCGCDZ5cWYwyY6FCk-aq2VNU0s,222 -dns/rdtypes/ANY/SOA.py,sha256=Cn8yrag1YvrvwivQgWg-KXmOCaVQVdFHSkFF77w-CE0,3145 -dns/rdtypes/ANY/SPF.py,sha256=rA3Srs9ECQx-37lqm7Zf7aYmMpp_asv4tGS8_fSQ-CU,1022 -dns/rdtypes/ANY/SSHFP.py,sha256=l6TZH2R0kytiZGWez_g-Lq94o5a2xMuwLKwUwsPMx5w,2530 -dns/rdtypes/ANY/TKEY.py,sha256=1ecTuBse2b4QPH2qmx3vn-gfPK0INcKXfxrIyAJxFHA,4927 -dns/rdtypes/ANY/TLSA.py,sha256=cytzebS3W7FFr9qeJ9gFSHq_bOwUk9aRVlXWHfnVrRs,218 -dns/rdtypes/ANY/TSIG.py,sha256=4fNQJSNWZXUKZejCciwQuUJtTw2g-YbPmqHrEj_pitg,4750 -dns/rdtypes/ANY/TXT.py,sha256=F1U9gIAhwXIV4UVT7CwOCEn_su6G1nJIdgWJsLktk20,1000 -dns/rdtypes/ANY/URI.py,sha256=dpcS8KwcJ2WJ7BkOp4CZYaUyRuw7U2S9GzvVwKUihQg,2921 -dns/rdtypes/ANY/WALLET.py,sha256=IaP2g7Nq26jWGKa8MVxvJjWXLQ0wrNR1IWJVyyMG8oU,219 -dns/rdtypes/ANY/X25.py,sha256=BzEM7uOY7CMAm7QN-dSLj-_LvgnnohwJDUjMstzwqYo,1942 -dns/rdtypes/ANY/ZONEMD.py,sha256=JQicv69EvUxh4FCT7eZSLzzU5L5brw_dSM65Um2t5lQ,2393 -dns/rdtypes/ANY/__init__.py,sha256=My5jT8T5bA66zBydmRSxkmDCFxwI81B4DBRA_S36IL8,1526 -dns/rdtypes/ANY/__pycache__/AFSDB.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/AMTRELAY.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/AVC.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/CAA.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/CDNSKEY.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/CDS.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/CERT.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/CNAME.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/CSYNC.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/DLV.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/DNAME.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/DNSKEY.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/DS.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/EUI48.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/EUI64.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/GPOS.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/HINFO.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/HIP.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/ISDN.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/L32.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/L64.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/LOC.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/LP.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/MX.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/NID.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/NINFO.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/NS.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/NSEC.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/NSEC3.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/NSEC3PARAM.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/OPENPGPKEY.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/OPT.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/PTR.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/RESINFO.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/RP.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/RRSIG.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/RT.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/SMIMEA.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/SOA.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/SPF.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/SSHFP.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/TKEY.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/TLSA.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/TSIG.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/TXT.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/URI.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/WALLET.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/X25.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/ZONEMD.cpython-310.pyc,, -dns/rdtypes/ANY/__pycache__/__init__.cpython-310.pyc,, -dns/rdtypes/CH/A.py,sha256=-4G3ASZGj7oUlPfDxADibAB1WfTsZBavUO8ghDWarJ8,2212 -dns/rdtypes/CH/__init__.py,sha256=GD9YeDKb9VBDo-J5rrChX1MWEGyQXuR9Htnbhg_iYLc,923 -dns/rdtypes/CH/__pycache__/A.cpython-310.pyc,, -dns/rdtypes/CH/__pycache__/__init__.cpython-310.pyc,, -dns/rdtypes/IN/A.py,sha256=FfFn3SqbpneL9Ky63COP50V2ZFxqS1ldCKJh39Enwug,1814 -dns/rdtypes/IN/AAAA.py,sha256=AxrOlYy-1TTTWeQypDKeXrDCrdHGor0EKCE4fxzSQGo,1820 -dns/rdtypes/IN/APL.py,sha256=ppyFwn0KYMdyDzphxd0BUhgTmZv0QnDMRLjzQQM793U,5097 -dns/rdtypes/IN/DHCID.py,sha256=zRUh_EOxUPVpJjWY5m7taX8q4Oz5K70785ZtKv5OTCU,1856 -dns/rdtypes/IN/HTTPS.py,sha256=P-IjwcvDQMmtoBgsDHglXF7KgLX73G6jEDqCKsnaGpQ,220 -dns/rdtypes/IN/IPSECKEY.py,sha256=RyIy9K0Yt0uJRjdr6cj5S95ELHHbl--0xV-Qq9O3QQk,3290 -dns/rdtypes/IN/KX.py,sha256=K1JwItL0n5G-YGFCjWeh0C9DyDD8G8VzicsBeQiNAv0,1013 -dns/rdtypes/IN/NAPTR.py,sha256=SaOK-0hIYImwLtb5Hqewi-e49ykJaQiLNvk8ZzNoG7Q,3750 -dns/rdtypes/IN/NSAP.py,sha256=6YfWCVSIPTTBmRAzG8nVBj3LnohncXUhSFJHgp-TRdc,2163 -dns/rdtypes/IN/NSAP_PTR.py,sha256=iTxlV6fr_Y9lqivLLncSHxEhmFqz5UEElDW3HMBtuCU,1015 -dns/rdtypes/IN/PX.py,sha256=vHDNN2rfLObuUKwpYDIvpPB482BqXlHA-ZQpQn9Sb_E,2756 -dns/rdtypes/IN/SRV.py,sha256=a0zGaUwzvih_a4Q9BViUTFs7NZaCqgl7mls3-KRVHm8,2769 -dns/rdtypes/IN/SVCB.py,sha256=HeFmi2v01F00Hott8FlvQ4R7aPxFmT7RF-gt45R5K_M,218 -dns/rdtypes/IN/WKS.py,sha256=kErSG5AO2qIuot_hkMHnQuZB1_uUzUirNdqBoCp97rk,3652 -dns/rdtypes/IN/__init__.py,sha256=HbI8aw9HWroI6SgEvl8Sx6FdkDswCCXMbSRuJy5o8LQ,1083 -dns/rdtypes/IN/__pycache__/A.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/AAAA.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/APL.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/DHCID.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/HTTPS.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/IPSECKEY.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/KX.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/NAPTR.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/NSAP.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/NSAP_PTR.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/PX.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/SRV.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/SVCB.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/WKS.cpython-310.pyc,, -dns/rdtypes/IN/__pycache__/__init__.cpython-310.pyc,, -dns/rdtypes/__init__.py,sha256=NYizfGglJfhqt_GMtSSXf7YQXIEHHCiJ_Y_qaLVeiOI,1073 -dns/rdtypes/__pycache__/__init__.cpython-310.pyc,, -dns/rdtypes/__pycache__/dnskeybase.cpython-310.pyc,, -dns/rdtypes/__pycache__/dsbase.cpython-310.pyc,, -dns/rdtypes/__pycache__/euibase.cpython-310.pyc,, -dns/rdtypes/__pycache__/mxbase.cpython-310.pyc,, -dns/rdtypes/__pycache__/nsbase.cpython-310.pyc,, -dns/rdtypes/__pycache__/svcbbase.cpython-310.pyc,, -dns/rdtypes/__pycache__/tlsabase.cpython-310.pyc,, -dns/rdtypes/__pycache__/txtbase.cpython-310.pyc,, -dns/rdtypes/__pycache__/util.cpython-310.pyc,, -dns/rdtypes/dnskeybase.py,sha256=FoDllfa9Pz2j2rf45VyUUYUsIt3kjjrwDy6LxrlPb5s,2856 -dns/rdtypes/dsbase.py,sha256=I85Aps1lBsiItdqGpsNY1O8icosfPtkWjiUn1J1lLUQ,3427 -dns/rdtypes/euibase.py,sha256=1yKWOM4xBwLLIFFfEj7M9JMankO2l8ljxhG-5OOxXDg,2618 -dns/rdtypes/mxbase.py,sha256=DzjbiKoAAgpqbhwMBIFGA081jR5_doqGAq-kLvy2mns,3196 -dns/rdtypes/nsbase.py,sha256=tueXVV6E8lelebOmrmoOPq47eeRvOpsxHVXH4cOFxcs,2323 -dns/rdtypes/svcbbase.py,sha256=YOH3Wz3fp5GQjdTF7hU-1ys9iDkYEC5p4d0F32ivv5g,17612 -dns/rdtypes/tlsabase.py,sha256=pIiWem6sF4IwyyKmyqx5xg55IG0w3K9r502Yx8PdziA,2596 -dns/rdtypes/txtbase.py,sha256=Dt9ptWSWtnq0Qwlni6IT6YUz_DCixQDDUl5d4P_AfqY,3696 -dns/rdtypes/util.py,sha256=c3eLaucwuxXZjXWuNyCGKzwltgub4AjT4uLVytEuxSk,9017 -dns/renderer.py,sha256=5THf1iKql2JPL2sKZt2-b4zqHKfk_vlx0FEfPtMJysY,11254 -dns/resolver.py,sha256=FH_hiMeCdVYonIYmE3QqEWJKgHOOxlTcHS0dwd_loGY,73730 -dns/reversename.py,sha256=zoqXEbMZXm6R13nXbJHgTsf6L2C6uReODj6mqSHrTiE,3828 -dns/rrset.py,sha256=J-oQPEPJuKueLLiz1FN08P-ys9fjHhPWuwpDdrL4UTQ,9170 -dns/serial.py,sha256=-t5rPW-TcJwzBMfIJo7Tl-uDtaYtpqOfCVYx9dMaDCY,3606 -dns/set.py,sha256=hublMKCIhd9zp5Hz_fvQTwF-Ze28jn7mjqei6vTGWfs,9213 -dns/tokenizer.py,sha256=65vVkEeTuml3l2AT-NePE6Gt6ucDQNvSpeIVgMpP6G0,23583 -dns/transaction.py,sha256=UhwD6CLQI51dguuz__dxJS8V91vKAoqHdQDCBErJWxE,22589 -dns/tsig.py,sha256=I-Y-c3WMBX11bVioy5puFly2BhlpptUz82ikahxuh1c,11413 -dns/tsigkeyring.py,sha256=Z0xZemcU3XjZ9HlxBYv2E2PSuIhaFreqLDlD7HcmZDA,2633 -dns/ttl.py,sha256=Y4inc4bvkfKpogZn5i1n-tpg1CAjDJxH4_HvfeVjVsM,2977 -dns/update.py,sha256=y9d6LOO8xrUaH2UrZhy3ssnx8bJEsxqTArw5V8XqBRs,12243 -dns/version.py,sha256=GTecBDFJx8cKnGiCmxJhSVjk1EkqnuNVt4xailIi3sk,1926 -dns/versioned.py,sha256=3YQj8mzGmZEsjnuVJJjcWopVmDKYLhEj4hEGTLEwzco,11765 -dns/win32util.py,sha256=r9dOvC0Tq288vwPk-ngugsVpwB5YnfW22DaRv6TTPcU,8874 -dns/wire.py,sha256=vy0SolgECbO1UXB4dnhXhDeFKOJT29nQxXvSfKOgA5s,2830 -dns/xfr.py,sha256=aoW0UtvweaE0NV8cmzgMKLYQOa3hwJ3NudRuqjit4SU,13271 -dns/zone.py,sha256=lLAarSxPtpx4Sw29OQ0ifPshD4QauGu8RnPh2dEropA,52086 -dns/zonefile.py,sha256=Y9lm6I7n4eRS35CyclooiQ_jxiOs3pSyH_0uD4FQyag,27926 -dns/zonetypes.py,sha256=HrQNZxZ_gWLWI9dskix71msi9wkYK5pgrBBbPb1T74Y,690 -dnspython-2.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -dnspython-2.7.0.dist-info/METADATA,sha256=1lF6uqZwb6RAQFYVtBkLic6pBCe9t14TQWtkK9U5eyY,5763 -dnspython-2.7.0.dist-info/RECORD,, -dnspython-2.7.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87 -dnspython-2.7.0.dist-info/licenses/LICENSE,sha256=w-o_9WVLMpwZ07xfdIGvYjw93tSmFFWFSZ-EOtPXQc0,1526 diff --git a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/WHEEL b/venv/Lib/site-packages/dnspython-2.7.0.dist-info/WHEEL deleted file mode 100644 index cdd68a4..0000000 --- a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.25.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/licenses/LICENSE b/venv/Lib/site-packages/dnspython-2.7.0.dist-info/licenses/LICENSE deleted file mode 100644 index 390a726..0000000 --- a/venv/Lib/site-packages/dnspython-2.7.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,35 +0,0 @@ -ISC License - -Copyright (C) Dnspython Contributors - -Permission to use, copy, modify, and/or distribute this software for -any purpose with or without fee is hereby granted, provided that the -above copyright notice and this permission notice appear in all -copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR -PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. - - - -Copyright (C) 2001-2017 Nominum, Inc. -Copyright (C) Google Inc. - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose with or without fee is hereby granted, -provided that the above copyright notice and this permission notice -appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/venv/Lib/site-packages/docutils-0.21.2.dist-info/COPYING.txt b/venv/Lib/site-packages/docutils-0.21.2.dist-info/COPYING.txt deleted file mode 100644 index 333583c..0000000 --- a/venv/Lib/site-packages/docutils-0.21.2.dist-info/COPYING.txt +++ /dev/null @@ -1,159 +0,0 @@ -.. include:: docs/header0.txt - -================== - Copying Docutils -================== - -:Author: David Goodger -:Contact: goodger@python.org -:Date: $Date: 2023-06-22 17:34:37 +0200 (Do, 22. Jun 2023) $ -:Web site: https://docutils.sourceforge.io/ -:Copyright: This document has been placed in the public domain. - -Most of the files included in this project have been placed in the -public domain, and therefore have no license requirements and no -restrictions on copying or usage; see the `Public Domain Dedication`_ -below. There are exceptions_, listed below. -Files in the Sandbox_ are not distributed with Docutils releases and -may have different license terms. - - -Public Domain Dedication -======================== - -The persons who have associated their work with this project (the -"Dedicator": David Goodger and the many contributors to the Docutils -project) hereby dedicate the entire copyright, less the exceptions_ -listed below, in the work of authorship known as "Docutils" identified -below (the "Work") to the public domain. - -The primary repository for the Work is the Internet World Wide Web -site . The Work consists of the -files within the "docutils" module of the Docutils project Subversion -repository (http://svn.code.sf.net/p/docutils/code/), -whose Internet web interface is located at -. Files dedicated to the -public domain may be identified by the inclusion, near the beginning -of each file, of a declaration of the form:: - - Copyright: This document/module/DTD/stylesheet/file/etc. has been - placed in the public domain. - -Dedicator makes this dedication for the benefit of the public at large -and to the detriment of Dedicator's heirs and successors. Dedicator -intends this dedication to be an overt act of relinquishment in -perpetuity of all present and future rights under copyright law, -whether vested or contingent, in the Work. Dedicator understands that -such relinquishment of all rights includes the relinquishment of all -rights to enforce (by lawsuit or otherwise) those copyrights in the -Work. - -Dedicator recognizes that, once placed in the public domain, the Work -may be freely reproduced, distributed, transmitted, used, modified, -built upon, or otherwise exploited by anyone for any purpose, -commercial or non-commercial, and in any way, including by methods -that have not yet been invented or conceived. - -(This dedication is derived from the text of the `Creative Commons -Public Domain Dedication`. [#]_) - -.. [#] Creative Commons has `retired this legal tool`__ and does not - recommend that it be applied to works: This tool is based on United - States law and may not be applicable outside the US. For dedicating new - works to the public domain, Creative Commons recommend the replacement - Public Domain Dedication CC0_ (CC zero, "No Rights Reserved"). So does - the Free Software Foundation in its license-list_. - - __ http://creativecommons.org/retiredlicenses - .. _CC0: http://creativecommons.org/about/cc0 - -Exceptions -========== - -The exceptions to the `Public Domain Dedication`_ above are: - -* docutils/utils/smartquotes.py - - Copyright © 2011 Günter Milde, - based on `SmartyPants`_ © 2003 John Gruber - (released under a "revised" `BSD 3-Clause License`_ included in the file) - and smartypants.py © 2004, 2007 Chad Miller. - Released under the terms of the `BSD 2-Clause License`_ - (`local copy `__). - - .. _SmartyPants: http://daringfireball.net/projects/smartypants/ - -* docutils/utils/math/latex2mathml.py - - Copyright © Jens Jørgen Mortensen, Günter Milde. - Released under the terms of the `BSD 2-Clause License`_ - (`local copy `__). - -* | docutils/utils/math/math2html.py, - | docutils/writers/html5_polyglot/math.css - - Copyright © 2009,2010 Alex Fernández; 2021 Günter Milde - - These files were part of eLyXer_, released under the `GNU - General Public License`_ version 3 or later. The author relicensed - them for Docutils under the terms of the `BSD 2-Clause License`_ - (`local copy `__). - - .. _eLyXer: https://github.com/alexfernandez/elyxer - -* | docutils/__main__.py, - | docutils/parsers/commonmark_wrapper.py, - | docutils/parsers/recommonmark_wrapper.py, - | docutils/utils/error_reporting.py, - | docutils/utils/math/__init__.py, - | docutils/utils/math/latex2mathml.py, - | docutils/utils/math/tex2mathml_extern.py, - | docutils/utils/punctuation_chars.py, - | docutils/utils/smartquotes.py, - | docutils/writers/html5_polyglot/__init__.py, - | docutils/writers/html5_polyglot/\*.css, - | docutils/writers/latex2e/docutils.sty, - | docutils/writers/xetex/__init__.py, - | test/test_parsers/test_recommonmark/\*.py, - | test/test_parsers/test_rst/test_directives/test__init__.py, - | test/test_parsers/test_rst/test_directives/test_code_parsing.py, - | test/test_parsers/test_rst/test_line_length_limit_default.py, - | test/test_parsers/test_rst/test_line_length_limit.py, - | test/test_writers/test_latex2e_misc.py, - | test/transforms/test_smartquotes.py, - | tools/docutils-cli.py, - | tools/rst2html5.py - - Copyright © Günter Milde. - Released under the terms of the `BSD 2-Clause License`_ - (`local copy `__). - -* docutils/utils/roman.py - - copyright by Mark Pilgrim, released under the - `Zope Public License Version 2.1`_ (`local copy`__). - - __ licenses/ZPL-2-1.txt - -* tools/editors/emacs/rst.el - - copyright by Free Software Foundation, Inc., - released under the `GNU General Public License`_ version 3 or later - (`local copy`__). - - __ licenses/gpl-3-0.txt - -All used licenses are OSI-approved_ and GPL-compatible_. - -Plaintext versions of all the linked-to licenses are provided in the -licenses_ directory. - -.. _sandbox: https://docutils.sourceforge.io/sandbox/README.html -.. _licenses: licenses/ -.. _GNU General Public License: https://www.gnu.org/copyleft/gpl.html -.. _BSD 2-Clause License: http://opensource.org/licenses/BSD-2-Clause -.. _BSD 3-Clause License: https://opensource.org/licenses/BSD-3-Clause -.. _Zope Public License Version 2.1: https://opensource.org/license/zpl-2-1/ -.. _OSI-approved: http://opensource.org/licenses/ -.. _license-list: -.. _GPL-compatible: https://www.gnu.org/licenses/license-list.html diff --git a/venv/Lib/site-packages/docutils-0.21.2.dist-info/INSTALLER b/venv/Lib/site-packages/docutils-0.21.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/Lib/site-packages/docutils-0.21.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/Lib/site-packages/docutils-0.21.2.dist-info/METADATA b/venv/Lib/site-packages/docutils-0.21.2.dist-info/METADATA deleted file mode 100644 index bec0da0..0000000 --- a/venv/Lib/site-packages/docutils-0.21.2.dist-info/METADATA +++ /dev/null @@ -1,63 +0,0 @@ -Metadata-Version: 2.1 -Name: docutils -Version: 0.21.2 -Summary: Docutils -- Python Documentation Utilities -Author-email: David Goodger -Maintainer-email: docutils-develop list -Requires-Python: >=3.9 -Description-Content-Type: text/plain -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Console -Classifier: Intended Audience :: End Users/Desktop -Classifier: Intended Audience :: Other Audience -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: System Administrators -Classifier: License :: Public Domain -Classifier: License :: OSI Approved :: Python Software Foundation License -Classifier: License :: OSI Approved :: BSD License -Classifier: License :: OSI Approved :: GNU General Public License (GPL) -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Topic :: Documentation -Classifier: Topic :: Software Development :: Documentation -Classifier: Topic :: Text Processing -Classifier: Natural Language :: English -Classifier: Natural Language :: Afrikaans -Classifier: Natural Language :: Arabic -Classifier: Natural Language :: Catalan -Classifier: Natural Language :: Catalan (Valencian) -Classifier: Natural Language :: Chinese (Simplified) -Classifier: Natural Language :: Chinese (Traditional) -Classifier: Natural Language :: Czech -Classifier: Natural Language :: Danish -Classifier: Natural Language :: Dutch -Classifier: Natural Language :: Esperanto -Classifier: Natural Language :: Finnish -Classifier: Natural Language :: French -Classifier: Natural Language :: Galician -Classifier: Natural Language :: Georgian -Classifier: Natural Language :: German -Classifier: Natural Language :: Hebrew -Classifier: Natural Language :: Italian -Classifier: Natural Language :: Japanese -Classifier: Natural Language :: Korean -Classifier: Natural Language :: Latvian -Classifier: Natural Language :: Lithuanian -Classifier: Natural Language :: Persian -Classifier: Natural Language :: Polish -Classifier: Natural Language :: Portuguese (Brazilian) -Classifier: Natural Language :: Russian -Classifier: Natural Language :: Slovak -Classifier: Natural Language :: Spanish -Classifier: Natural Language :: Swedish -Classifier: Natural Language :: Ukrainian -Project-URL: Homepage, https://docutils.sourceforge.io - -Docutils is a modular system for processing documentation -into useful formats, such as HTML, XML, and LaTeX. For -input Docutils supports reStructuredText, an easy-to-read, -what-you-see-is-what-you-get plaintext markup syntax. diff --git a/venv/Lib/site-packages/docutils-0.21.2.dist-info/RECORD b/venv/Lib/site-packages/docutils-0.21.2.dist-info/RECORD deleted file mode 100644 index c4ac135..0000000 --- a/venv/Lib/site-packages/docutils-0.21.2.dist-info/RECORD +++ /dev/null @@ -1,347 +0,0 @@ -../../Scripts/docutils.exe,sha256=n6SPmXlvnoXMhoTtt3mBFTGhn_Vuctn4s_GvlbhxMqs,107895 -../../Scripts/rst2html.exe,sha256=7Dao_wECqCodl6Q5UygpUiTi5liZ1lWB1ss5ylf7-KY,107899 -../../Scripts/rst2html4.exe,sha256=wLdBhMEuc7drugGlZIEKTx_-GGfjrz0Bb1wB3Fr1pHQ,107901 -../../Scripts/rst2html5.exe,sha256=G0WdcHdsNBBpn5GkEs8QL7UNx_SxGoW-TvY6H_1PC7I,107901 -../../Scripts/rst2latex.exe,sha256=gmPXM_vm26TqW-tupqiVHa8Kvuzb9-MpAF4I9KFAk5Q,107901 -../../Scripts/rst2man.exe,sha256=KgQWizWiIFrArL-TYFLOXgamsS4k9UiPzmaRUNDh16Y,107897 -../../Scripts/rst2odt.exe,sha256=giyUQtjNnL6DYKY_7_qQg_p7FYrKoc3Y0PXv0_5w0pY,107897 -../../Scripts/rst2pseudoxml.exe,sha256=k-sm2jv_TX9OCSWUDjVfsc_90cXFl1mlkmGm4NYxIhI,107909 -../../Scripts/rst2s5.exe,sha256=Zgw9d5xPDOU4vRho0gHQC7zpZ_ttyWOZrsG3sXkGuFI,107895 -../../Scripts/rst2xetex.exe,sha256=dtoJEKod0Qq51eeJLU8huvUvwhqn48mzqV3OZKkb8Ec,107901 -../../Scripts/rst2xml.exe,sha256=hRXp5cKqCags4iuJxi5itredfoD8RwDOHwum7NjLrCY,107897 -docutils-0.21.2.dist-info/COPYING.txt,sha256=U07fdkGr3mn8UA8ijAl1GBLAWJgV7vDAgrxroxfWRqw,6310 -docutils-0.21.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -docutils-0.21.2.dist-info/METADATA,sha256=3oOygKJQ4otFhgmtONEmLPiLjUgZUQ5Fu1ZFHxTP4C8,2776 -docutils-0.21.2.dist-info/RECORD,, -docutils-0.21.2.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81 -docutils-0.21.2.dist-info/entry_points.txt,sha256=9xC35dFk4tSRrSMOKqq6kYlAZDEERdBM7fmwDLBMifY,379 -docutils/__init__.py,sha256=gmP9fnbribb7oZWoe4PTw8Obh_B_bt3e_CXKi45Xzus,10293 -docutils/__main__.py,sha256=HviLRJb_t90M1fOQ8s8J2A4XZXSvw4cYHkrAtZjR2XA,3625 -docutils/__pycache__/__init__.cpython-310.pyc,, -docutils/__pycache__/__main__.cpython-310.pyc,, -docutils/__pycache__/core.cpython-310.pyc,, -docutils/__pycache__/examples.cpython-310.pyc,, -docutils/__pycache__/frontend.cpython-310.pyc,, -docutils/__pycache__/io.cpython-310.pyc,, -docutils/__pycache__/nodes.cpython-310.pyc,, -docutils/__pycache__/statemachine.cpython-310.pyc,, -docutils/core.py,sha256=Lm2qwSppidgDBjoZQpOLiodDKtEbkT_CsLH93Iq4M6U,33045 -docutils/docutils.conf,sha256=F2yH40kC3N5nnjGIRdT7DHHGXbDKbd5YsbhmQxF2CNY,151 -docutils/examples.py,sha256=nP7S8EnZk4w3PYi2Ymeu9_UUcDIi39lP049Pe6iBECU,3961 -docutils/frontend.py,sha256=2oRkks_lIJHhlk537ejUki5dyHodR0SMuoZLXYRcUtI,44396 -docutils/io.py,sha256=VrAIuTlsf93O3wAYMK_PC0DqINMvRxuZZC5W_-6NEOg,22583 -docutils/languages/__init__.py,sha256=I8j0eJD3Jj3Q1C5ALqhYa-f8kCCQDPxmgn2VdPeTusI,2921 -docutils/languages/__pycache__/__init__.cpython-310.pyc,, -docutils/languages/__pycache__/af.cpython-310.pyc,, -docutils/languages/__pycache__/ar.cpython-310.pyc,, -docutils/languages/__pycache__/ca.cpython-310.pyc,, -docutils/languages/__pycache__/cs.cpython-310.pyc,, -docutils/languages/__pycache__/da.cpython-310.pyc,, -docutils/languages/__pycache__/de.cpython-310.pyc,, -docutils/languages/__pycache__/en.cpython-310.pyc,, -docutils/languages/__pycache__/eo.cpython-310.pyc,, -docutils/languages/__pycache__/es.cpython-310.pyc,, -docutils/languages/__pycache__/fa.cpython-310.pyc,, -docutils/languages/__pycache__/fi.cpython-310.pyc,, -docutils/languages/__pycache__/fr.cpython-310.pyc,, -docutils/languages/__pycache__/gl.cpython-310.pyc,, -docutils/languages/__pycache__/he.cpython-310.pyc,, -docutils/languages/__pycache__/it.cpython-310.pyc,, -docutils/languages/__pycache__/ja.cpython-310.pyc,, -docutils/languages/__pycache__/ka.cpython-310.pyc,, -docutils/languages/__pycache__/ko.cpython-310.pyc,, -docutils/languages/__pycache__/lt.cpython-310.pyc,, -docutils/languages/__pycache__/lv.cpython-310.pyc,, -docutils/languages/__pycache__/nl.cpython-310.pyc,, -docutils/languages/__pycache__/pl.cpython-310.pyc,, -docutils/languages/__pycache__/pt_br.cpython-310.pyc,, -docutils/languages/__pycache__/ru.cpython-310.pyc,, -docutils/languages/__pycache__/sk.cpython-310.pyc,, -docutils/languages/__pycache__/sv.cpython-310.pyc,, -docutils/languages/__pycache__/uk.cpython-310.pyc,, -docutils/languages/__pycache__/zh_cn.cpython-310.pyc,, -docutils/languages/__pycache__/zh_tw.cpython-310.pyc,, -docutils/languages/af.py,sha256=bjIWD_cNZAyZ9XIqqEoQaSljWlvP0vrQi8p8Fu9Nj2o,1831 -docutils/languages/ar.py,sha256=3FRbb0CSpXPHSQru96bqPDGGEdcnWhQIUG_ndpmacfg,1943 -docutils/languages/ca.py,sha256=b98Y79DEl88Jt2IZsKaH1OaJlC9W5khQcOV71Tvwpj0,2085 -docutils/languages/cs.py,sha256=qkEwPMKaPgw3D4qKCJoGXfDczIA3Wju8joBobn5hMvg,1832 -docutils/languages/da.py,sha256=1db0GiWS2YYOIqWru9BGeun7E3c-lwAgCWA6epn6KH4,1856 -docutils/languages/de.py,sha256=oaGzlhKsE4yFKTnCKrZt8nMnwZGqQ-PDT92UgUwRYzs,1728 -docutils/languages/en.py,sha256=MOTXOluYEnUwSHRlkINnBXMI8sbIfGahXF8RLws4NSk,1854 -docutils/languages/eo.py,sha256=p-wQOrAdL9tQ-89OT8A1VS8sO0OjogmPXRBAoihaAc0,1895 -docutils/languages/es.py,sha256=Jf81tKn_FJ7Kieozten6hn8WjVnYpZ9vsu4N6ER4O1s,1854 -docutils/languages/fa.py,sha256=dXhN7qZnzv1ksnR0Yb5LrSgNLwXy387ILj90v5iHHHM,1958 -docutils/languages/fi.py,sha256=34cPWxDFZXBnOw5LWENSIKaFqFLxZOc6vIioLLnS2do,1892 -docutils/languages/fr.py,sha256=zIPQD7UdOx3FPIBgIAT_mWNk4dped04jK8No2kI1Zic,1799 -docutils/languages/gl.py,sha256=Hz30Wfc-CMuGxKoHzPtY2Wdn-A6tFyvirnnFGZdZ_04,1958 -docutils/languages/he.py,sha256=eHyDSLwp6Y55GyHlgr8yMOkR-gxSgk7Ge8gfsm5n_Io,1878 -docutils/languages/it.py,sha256=aqmXdit3DYMhnke5MmyQIAVfCcrFuKzWmv0L5H06AI8,1814 -docutils/languages/ja.py,sha256=8C-hjqB7fa_Asa-uKKKkHRqT6NTjO3IJiiks6JADJNU,1890 -docutils/languages/ka.py,sha256=aqqIgkJyhLg3FOYWuhBhYDgzAj_nos9WwEQqI-eUcwg,2429 -docutils/languages/ko.py,sha256=eqKib7kW6h8DKg6inoXAtJa3f8FygdT37eGqiMifzZU,1832 -docutils/languages/lt.py,sha256=ixPG61Q2xB6J0uk0TXTXDwfKcEQgqIYC9Tc4VrBMQEY,1919 -docutils/languages/lv.py,sha256=pSZ7y94j6YWKLz4U16uBVwZsgKpd4jWkvcAgwmkDjv0,1851 -docutils/languages/nl.py,sha256=LKV2Hkuh0kH17w_ukZoAtTIlvWSo5iC3g7nPFDHoDDY,1871 -docutils/languages/pl.py,sha256=zyW9iwwriTX8YIGbT54DKgvkdyfiPxm49R0e2eIBxKE,1830 -docutils/languages/pt_br.py,sha256=navcDOoMajIE3yqibn7NPEIf-_oF15ECBWk4beMY3Zw,1865 -docutils/languages/ru.py,sha256=BAQA-1TZEeHpK44L_Os9V-WKUBt9lPApRl1nFM1zOhw,2070 -docutils/languages/sk.py,sha256=r-vrXCNGbDqFXAxM9WpRaH-ws1KumaIb1yramTTlmlI,1788 -docutils/languages/sv.py,sha256=bmJkUSdVn_j8s_P_Nu4KGBM2F42Og7sFzMNH238eKtQ,1908 -docutils/languages/uk.py,sha256=abLYoA0w2pJWlGLBglvUvEnGrhAVgbRyDEmlwV5ntxQ,2062 -docutils/languages/zh_cn.py,sha256=7nOmSfLgrb3Zq-xImQEN4-My6NqHZVat7GoMbpijVn4,1852 -docutils/languages/zh_tw.py,sha256=KJS8-gHwJVUdW7NOjgJQPb6iWkXtBWTT0JrRBV7BYTU,2112 -docutils/nodes.py,sha256=psy0zIro734Gsk7PGIqWqx0Ax_5AB0mBHC0J4KYduHo,80628 -docutils/parsers/__init__.py,sha256=NenSsWynQ-HU858BTDg0dMIX7ErS_qrAJot8KdtHyiU,3724 -docutils/parsers/__pycache__/__init__.cpython-310.pyc,, -docutils/parsers/__pycache__/commonmark_wrapper.cpython-310.pyc,, -docutils/parsers/__pycache__/null.cpython-310.pyc,, -docutils/parsers/__pycache__/recommonmark_wrapper.cpython-310.pyc,, -docutils/parsers/commonmark_wrapper.py,sha256=UcBtp5AcOSQRq-0-UsSZcnFMWa14TULD8kayhp4A0eY,1762 -docutils/parsers/null.py,sha256=LtO7n-E6lNOs4mLXZ2SiShB3C630SoJ80ugd9fh1vXI,445 -docutils/parsers/recommonmark_wrapper.py,sha256=SbFSCvBeQRH-fDQczHgK2qF_HwZ3gQsJx_CY2txX43s,5426 -docutils/parsers/rst/__init__.py,sha256=EydGQTcJeAmJQbCwPEFk77kA7Nio-Vqs7R0NMNkcb_s,15954 -docutils/parsers/rst/__pycache__/__init__.cpython-310.pyc,, -docutils/parsers/rst/__pycache__/roles.cpython-310.pyc,, -docutils/parsers/rst/__pycache__/states.cpython-310.pyc,, -docutils/parsers/rst/__pycache__/tableparser.cpython-310.pyc,, -docutils/parsers/rst/directives/__init__.py,sha256=82wwJQW7spmBVtko7E-a62LUXYfATJg3hSl6CZNrUus,14812 -docutils/parsers/rst/directives/__pycache__/__init__.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/admonitions.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/body.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/html.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/images.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/misc.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/parts.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/references.cpython-310.pyc,, -docutils/parsers/rst/directives/__pycache__/tables.cpython-310.pyc,, -docutils/parsers/rst/directives/admonitions.py,sha256=44OwQdPrDKD5VnCd-pPFtEzJs3U1uF-MeS3iWMmCWwU,2526 -docutils/parsers/rst/directives/body.py,sha256=lRClR4ljNiXntJfojN0HcaNpqH1m2GpwsOMS3JVNJK8,9939 -docutils/parsers/rst/directives/html.py,sha256=adxIFdnOHpqH0QSeXT7utBSy7FKWV0x18zbnXtmmuhs,695 -docutils/parsers/rst/directives/images.py,sha256=amQeXFb31hHlyjf15vgF2Sfe3OGCGzLaZAHxfsWSmOw,7265 -docutils/parsers/rst/directives/misc.py,sha256=9mc7erT0KvKHWR4_i5Uz2FhBk2pLd36fMCabyF2ClLA,26700 -docutils/parsers/rst/directives/parts.py,sha256=m5YOwZoPawR6I-Y3Q7CN9wGUzWmXa9v-Hvglh2E5ffQ,4247 -docutils/parsers/rst/directives/references.py,sha256=1Y1yhe_O2PqLtQUSly-ny291nrQKJgQiO4Hu7Xew9Zo,831 -docutils/parsers/rst/directives/tables.py,sha256=PRwO-lA1I93JAXR7qGDQ6n2cT5UYA8JQHdymHOdLFdg,23470 -docutils/parsers/rst/include/README.txt,sha256=R3Y-9wDzYQ0jOhj9FAlwG6hRRhHcEWOZcn2hMF1DeVg,670 -docutils/parsers/rst/include/isoamsa.txt,sha256=ZqGuK-R-yIxa2YDSREt48DFxc8fpF-HX51eiCKXCPp4,10925 -docutils/parsers/rst/include/isoamsb.txt,sha256=3CK8um9WjhPMVgEAbeI16rk91IzWqWXFbRJC44InP3A,7242 -docutils/parsers/rst/include/isoamsc.txt,sha256=XCI2ubAKaO-eOQj87hbBMeYpkqHvc2b2daUCS9ekUzU,1723 -docutils/parsers/rst/include/isoamsn.txt,sha256=Wx54SjZGeYVEB3oNnRi7eGYHEjROZiBUFhQAQDxcVMQ,6721 -docutils/parsers/rst/include/isoamso.txt,sha256=RFxHs5s8DtMgvDaeArmwnSZP_QN20KssvW5f6KMohYA,3825 -docutils/parsers/rst/include/isoamsr.txt,sha256=TLH3gNugqSX3-tH6gDNcgIgbGiKe_GukwZ8U1MIeJCQ,11763 -docutils/parsers/rst/include/isobox.txt,sha256=NORZqqDIewr0-CPoVWqVfTbCVrGZOqY87Crn8O4OUoo,3101 -docutils/parsers/rst/include/isocyr1.txt,sha256=B2DWWIEZ8aJ-scOBP9pbrsKYEmnNF8VZ9e9Mut2MZzU,4241 -docutils/parsers/rst/include/isocyr2.txt,sha256=t52cY0R-9bnkWiQPXW1NYDzO4ueE6ogUF9Ho4ARHg7Q,1882 -docutils/parsers/rst/include/isodia.txt,sha256=VMg8jI2IQogISrpiTS3L88TntxiMfS0cElsrpxZ1FAI,869 -docutils/parsers/rst/include/isogrk1.txt,sha256=DkJc-K_nTh-WDhfOQIRMdQ4aUnsYKb_etyEEJfU8SG4,3010 -docutils/parsers/rst/include/isogrk2.txt,sha256=0x8w_DgroVISgsTLUOuyLZNzDLThcnti27T7T7DxL7g,1705 -docutils/parsers/rst/include/isogrk3.txt,sha256=8b7gQSKtw4yhLEVMZ6vH8VaToiZMM2_kD2snlqfeIQE,2880 -docutils/parsers/rst/include/isogrk4-wide.txt,sha256=RAdw43c5ZAUBWu8MO_lJDmXVV0cGHhVrky0H_bq1eEs,3035 -docutils/parsers/rst/include/isogrk4.txt,sha256=FQxEZAJu2d_RX3G3PfHm6JlC_1osHQoheFA886MLeQk,372 -docutils/parsers/rst/include/isolat1.txt,sha256=d4dBGSPosghudIhZfMPNzsBJKvH1nyVyi6m5p0oW_HY,4397 -docutils/parsers/rst/include/isolat2.txt,sha256=2RMWwHB9djHvsdnKSv2dSNHlBc50P0JYF1DRcK3HW8s,8466 -docutils/parsers/rst/include/isomfrk-wide.txt,sha256=RsYrcq3mX-CMuV6oijCIfUTnUe8Z6w0PG0ephU9isBM,3334 -docutils/parsers/rst/include/isomfrk.txt,sha256=Y40ZXO1GLLzHezKEJJ8w8OBFtHGwtdjErI_062abwC4,519 -docutils/parsers/rst/include/isomopf-wide.txt,sha256=nrhNkzw15HdEA-Gf8T7yatCbs5b7z7q7T6SCTNLByJw,1931 -docutils/parsers/rst/include/isomopf.txt,sha256=l9rTXrdZWf2RchhPr4Oi2M-4yZYLtVH-7kdOmCPzY_M,639 -docutils/parsers/rst/include/isomscr-wide.txt,sha256=VNfKzET1n08k2PUeK9UeDamgP0j8iKpaorregQbaP3w,3231 -docutils/parsers/rst/include/isomscr.txt,sha256=EBWiVvLZYhm9e2c5i7T4Ur6i1WODl_BLiHjcWA_C45g,776 -docutils/parsers/rst/include/isonum.txt,sha256=yg4P9UxBM-72JRGkB4KVdjmRPyBWLvkOlkelh8quDzc,4066 -docutils/parsers/rst/include/isopub.txt,sha256=BFkr5rRRFuYM7a19WPP7lfBpUKftkYKZjnM2SHLtzwY,4613 -docutils/parsers/rst/include/isotech.txt,sha256=2WGt7TSBeRMr2m2DBlY-xiVjxeiNXdTZJb1DJdtgYKg,9726 -docutils/parsers/rst/include/mmlalias.txt,sha256=jQ4IbZwZAJ9rXmb7De77DYgdIlMsWA-s8uZf42EYtFU,45428 -docutils/parsers/rst/include/mmlextra-wide.txt,sha256=Myj4APWltVYohIK7f1v8urJuDVT2_I_U7rasnBCTsYY,9010 -docutils/parsers/rst/include/mmlextra.txt,sha256=DfWtgBA6Bn4TzlZokxTu5vp7zIf1hqUeaeGpYbfHSAg,6800 -docutils/parsers/rst/include/s5defs.txt,sha256=_5JOMpDtaufiZbdxh6QKpICqLvGpB9cypHM-SEt3sKA,1036 -docutils/parsers/rst/include/xhtml1-lat1.txt,sha256=ht_IZrejaCfgG95sfLNfCu1WAzU4LwpkWgzRbZ_6OA4,6112 -docutils/parsers/rst/include/xhtml1-special.txt,sha256=u4YARKjTrICRTtqlMDDOmpYR8xe-DKDRiNjzmXQs7gc,1945 -docutils/parsers/rst/include/xhtml1-symbol.txt,sha256=e6GP5rkmSNcXusRBJkKf2LSbSEyd1oFXJG_WBCYBKE8,7028 -docutils/parsers/rst/languages/__init__.py,sha256=bAE-YQUQ95QwYJVPnWcjz5bw6LOfW5Pgbhwmwp01-OY,1222 -docutils/parsers/rst/languages/__pycache__/__init__.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/af.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/ar.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/ca.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/cs.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/da.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/de.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/en.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/eo.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/es.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/fa.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/fi.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/fr.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/gl.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/he.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/it.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/ja.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/ka.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/ko.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/lt.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/lv.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/nl.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/pl.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/pt_br.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/ru.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/sk.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/sv.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/uk.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/zh_cn.cpython-310.pyc,, -docutils/parsers/rst/languages/__pycache__/zh_tw.cpython-310.pyc,, -docutils/parsers/rst/languages/af.py,sha256=MYGuM5yX_bx83imYLMJreUelpx3c1fcMmLhEu5tyQQI,3760 -docutils/parsers/rst/languages/ar.py,sha256=XpIY3SM10ccvFrO_j__REi_ITvLxSmGuf_y0Dc-Z_-g,3051 -docutils/parsers/rst/languages/ca.py,sha256=atmy4uqx3eVNvnKJwD0HuY0JSRG7uJfo7-AXrRgWg9g,4318 -docutils/parsers/rst/languages/cs.py,sha256=UXKr7zpl6UY31mBtCaNF-FBSsGVvWC59dx7KkwnIbTk,4760 -docutils/parsers/rst/languages/da.py,sha256=tQfxUwhlJohtnfKscjY0PUnwDYF2M-6Tu08EcXy7c6Q,3752 -docutils/parsers/rst/languages/de.py,sha256=nTIYDpKgOf28OJkcJbnuRvTOeLG6nDkfXDwW-MJV3Ls,3564 -docutils/parsers/rst/languages/en.py,sha256=9dmxPb_sYYsY4vEg8B_IBGQhEytcRvXtp5iOrzwmaHI,3516 -docutils/parsers/rst/languages/eo.py,sha256=ozUCNH5zKhnmYXxd5nZRu3TmF_aVeCAVzSLleRJWDf8,3751 -docutils/parsers/rst/languages/es.py,sha256=gFFm2EwAtAZOJUQLk03QUQdV0E7DKnct0amy6gpaNs4,4034 -docutils/parsers/rst/languages/fa.py,sha256=fap5ifAVKvqHGo3S2_G4mMrA8fvOiQ3BPi4z8Zlf94M,3171 -docutils/parsers/rst/languages/fi.py,sha256=xsxxUTOqVj1P1XkCQsPPkI-p1-ELE0QwMA9Oy-QPDHg,3536 -docutils/parsers/rst/languages/fr.py,sha256=V9_k_lbLkBSWuAbNeW2l4_Bv4EzaK4Dbwih0fJYIi0U,3816 -docutils/parsers/rst/languages/gl.py,sha256=v-zXIwcRYxgu8mZJmlexv73pMtwWlSB4yGVcYeENQP4,3389 -docutils/parsers/rst/languages/he.py,sha256=_UHQHJQx7EAGvMlURHJ8kDk_tcG1uv-7eTl7a4XEGgU,3293 -docutils/parsers/rst/languages/it.py,sha256=ZR4TsyM3611ASRQelyA7rx0zjUgMVM6gzrym6Bqrj40,3353 -docutils/parsers/rst/languages/ja.py,sha256=_PlI9H5u300_VlYvW52UvSy_MJ5OLlMmoNo1Pc6Pib8,3776 -docutils/parsers/rst/languages/ka.py,sha256=Xxv37fZnLqIbo1vmT1--Kj7etRxlKPgHcgfgiBvn9Xk,4141 -docutils/parsers/rst/languages/ko.py,sha256=IpSyXjTkoij0C7859i1p0iSgz9BQYpdF3fNTS6qcQ1A,3377 -docutils/parsers/rst/languages/lt.py,sha256=PHzrQAP-ZAcboCyc1jvHI5l0CMQnrbBEZ285MWJVy9w,3519 -docutils/parsers/rst/languages/lv.py,sha256=pfTCSDtQkOWYVTnTFjWhUZpnJJW7yuNzVW9xvBgP_u4,3376 -docutils/parsers/rst/languages/nl.py,sha256=dQ2Hex8oQS8f075B6nWZjeSQ0Rzjnl87oS8LauqBe1Y,3794 -docutils/parsers/rst/languages/pl.py,sha256=TRNum6wVR2XQY_Y_uhKqXNHdTBeaYgXwWaqokBaO-N0,3240 -docutils/parsers/rst/languages/pt_br.py,sha256=-cFMXIp8_6cryE7Q7smlElf4QegPqjmDRya8VxM1CQQ,3870 -docutils/parsers/rst/languages/ru.py,sha256=t5K4rlNKIcoOchVeC68sjJ8mr0Cox_BeyCvb1MDm9tQ,3398 -docutils/parsers/rst/languages/sk.py,sha256=HSdFwU6j9rZShkXyGPBc749TrUUB7tBSz-aw0f4UAzs,3943 -docutils/parsers/rst/languages/sv.py,sha256=HxyE3k93qgJw-aD6Ea3Tmfqz3QX1Q7AJIaU65MrkJxc,3261 -docutils/parsers/rst/languages/uk.py,sha256=LBUHWeKwFdEjfif4CG7LtMhBidl4ln6u4oStJ2omVsQ,3441 -docutils/parsers/rst/languages/zh_cn.py,sha256=YEC3UmY43NaI7s_6DatL_VQugiHvSUbBrHubgnMfYbI,3925 -docutils/parsers/rst/languages/zh_tw.py,sha256=icmm58W9wO69L6p5dwTQwjj45uxer2ZrJCqvBbERnkQ,5160 -docutils/parsers/rst/roles.py,sha256=GLJVffa-S_Fn3u6RTxdXJm1MXd1AQ7IxbCq99MmxIzQ,16119 -docutils/parsers/rst/states.py,sha256=ziKtByqhX2TAjRg4cOgGyQ6729W6gmVuaUUMKwKtf1k,133123 -docutils/parsers/rst/tableparser.py,sha256=D2jtx00mTdHsn20TKk9GJmCilwISeKHe9VoSy8PYELs,20912 -docutils/readers/__init__.py,sha256=rgBQZvedeYA8UZb2pYKoKqYWAjvUi8ZrzG1kANjnwC4,3520 -docutils/readers/__pycache__/__init__.cpython-310.pyc,, -docutils/readers/__pycache__/doctree.cpython-310.pyc,, -docutils/readers/__pycache__/pep.cpython-310.pyc,, -docutils/readers/__pycache__/standalone.cpython-310.pyc,, -docutils/readers/doctree.py,sha256=9QNTk_8x46sDkcSjzQiyFZxN-m9CBO3XA5bLar7OA0Q,1607 -docutils/readers/pep.py,sha256=m5RnOjKfMnmwHXU8vsr0HfZlqcqH2Yn4MXspjLO0GYE,1523 -docutils/readers/standalone.py,sha256=qwVRPiBto5CvE3m-2sZ2a2btlVl8aSbT4J_z7uIr3yM,2334 -docutils/statemachine.py,sha256=fKzVodfw6BEZQf4HquXfpBfNR8N5E8uzVeDoJA5eFRw,56956 -docutils/transforms/__init__.py,sha256=LTftDJ01XJReLdKMyuJrB_ImFr0fHOaZGqzE1VnXg9c,6968 -docutils/transforms/__pycache__/__init__.cpython-310.pyc,, -docutils/transforms/__pycache__/components.cpython-310.pyc,, -docutils/transforms/__pycache__/frontmatter.cpython-310.pyc,, -docutils/transforms/__pycache__/misc.cpython-310.pyc,, -docutils/transforms/__pycache__/parts.cpython-310.pyc,, -docutils/transforms/__pycache__/peps.cpython-310.pyc,, -docutils/transforms/__pycache__/references.cpython-310.pyc,, -docutils/transforms/__pycache__/universal.cpython-310.pyc,, -docutils/transforms/__pycache__/writer_aux.cpython-310.pyc,, -docutils/transforms/components.py,sha256=4qO1txFE98PJa4tqKCpnlnQi_UIEQDU4mMVuzwgqizY,2151 -docutils/transforms/frontmatter.py,sha256=zgWHDRBnv1Flv1Ddq5xEK6KmmGSgRyBwOzOHT8TfOAk,20809 -docutils/transforms/misc.py,sha256=BhyjLyE8j5QRELg7CcT0hEwdvnUJugUqQYyckzXDlh0,4873 -docutils/transforms/parts.py,sha256=Z_72Wf2oqchCcTIPTOgBVS1auAtA7POwJww1EaoeQPk,6912 -docutils/transforms/peps.py,sha256=7TMhgwqyopkuUetITpsByN-t0ZT8bXJOqaClUwliF0U,11111 -docutils/transforms/references.py,sha256=fhgJ6KDifnAFtPZHw6srdH76A5cepjfejzSKNF_2McA,36821 -docutils/transforms/universal.py,sha256=mhJkmCIhYQFqBAzitGyskSjGTYCwAyvSQzld6p5aLEE,12381 -docutils/transforms/writer_aux.py,sha256=G_XXqiAcSqWnFJKWRhQ8oE0jWcZPjLjyW2QBThE1Xes,3057 -docutils/utils/__init__.py,sha256=8G-da95eq3Ka72X1U0vAgNR4UZJYzS2t4o_MpfnN5c0,30381 -docutils/utils/__pycache__/__init__.cpython-310.pyc,, -docutils/utils/__pycache__/code_analyzer.cpython-310.pyc,, -docutils/utils/__pycache__/error_reporting.cpython-310.pyc,, -docutils/utils/__pycache__/punctuation_chars.cpython-310.pyc,, -docutils/utils/__pycache__/roman.cpython-310.pyc,, -docutils/utils/__pycache__/smartquotes.cpython-310.pyc,, -docutils/utils/__pycache__/urischemes.cpython-310.pyc,, -docutils/utils/code_analyzer.py,sha256=O6eUnWPYyZFXtTtk-NuNVv4k7L9sb5BJGIjacSZT4Tw,4920 -docutils/utils/error_reporting.py,sha256=vjHvpHu0BSoE2Ltm4FyYfLUsV5VWAjBbRoniWrJ7CR8,8105 -docutils/utils/math/__init__.py,sha256=DgTt07qT_uN2-9Tz8HNKkRqw5P3KIj81VurrJ2J_Omw,2553 -docutils/utils/math/__pycache__/__init__.cpython-310.pyc,, -docutils/utils/math/__pycache__/latex2mathml.cpython-310.pyc,, -docutils/utils/math/__pycache__/math2html.cpython-310.pyc,, -docutils/utils/math/__pycache__/mathalphabet2unichar.cpython-310.pyc,, -docutils/utils/math/__pycache__/mathml_elements.cpython-310.pyc,, -docutils/utils/math/__pycache__/tex2mathml_extern.cpython-310.pyc,, -docutils/utils/math/__pycache__/tex2unichar.cpython-310.pyc,, -docutils/utils/math/__pycache__/unichar2tex.cpython-310.pyc,, -docutils/utils/math/latex2mathml.py,sha256=ELwAGaYg4kx2E7_AE_rSSSZFID4QMIV8sPAIQ2PsdVE,46961 -docutils/utils/math/math2html.py,sha256=VfZ1ceFmNKu4yvF72j4xsgH_cjtOkeCevPC3UYw4enQ,107808 -docutils/utils/math/mathalphabet2unichar.py,sha256=bsgWbE09bIyXfME-TyCms-0fesWVoxXMErQVVeYOoSo,56217 -docutils/utils/math/mathml_elements.py,sha256=zMoCC2KnjAxmSGu4ZUtCZAEuyWme80pCPTn66E44gcY,14564 -docutils/utils/math/tex2mathml_extern.py,sha256=lo4n8GFXWcpe-yw8TPPahzHfhXU9_jv2oo-Sm_TasE4,9436 -docutils/utils/math/tex2unichar.py,sha256=_A2K7ap6o6cb1LY9qCYtsfP-zk5eeu_Hu6LIl6j7LnA,37497 -docutils/utils/math/unichar2tex.py,sha256=Q1gvqUGWprAjMfpGfujAu4ldjJevoFG2moM46SWy6WU,18393 -docutils/utils/punctuation_chars.py,sha256=OMY7gEwy_TIo1MnjZ9cnT3wA9LmSApldJ3lSJZbEtuE,5747 -docutils/utils/roman.py,sha256=JCF_zBcbauEuVvDPuNTR1ZBxFgyNEUr6jZ2JwZwnQ9A,4280 -docutils/utils/smartquotes.py,sha256=KW27gHCkAhgDCdKisPbAu85yJjc0j2FcssSwzvPlCCI,39136 -docutils/utils/urischemes.py,sha256=5dcLKn-Xo5ldDCcdTtO7l8UM_Y3KZrcjyR3A8RWp91U,6260 -docutils/writers/__init__.py,sha256=sJuZewwKkiJHl0VkAtx-geKluXhd_34H9o3sg4Yp4AU,4945 -docutils/writers/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/__pycache__/_html_base.cpython-310.pyc,, -docutils/writers/__pycache__/docutils_xml.cpython-310.pyc,, -docutils/writers/__pycache__/manpage.cpython-310.pyc,, -docutils/writers/__pycache__/null.cpython-310.pyc,, -docutils/writers/__pycache__/pseudoxml.cpython-310.pyc,, -docutils/writers/_html_base.py,sha256=pQqROc1bBMw_ozqT7T8jNtkHh7F7EWcxZUAbLDIvMrY,75401 -docutils/writers/docutils_xml.py,sha256=wi786IvTZqbojdiIxx-vZWS76BE0cUYJQ5RSqfJnkXc,6851 -docutils/writers/html4css1/__init__.py,sha256=KkCwD339fBkAsvUpO448_i2YcSyZ04bloCTr932wTJ8,38125 -docutils/writers/html4css1/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/html4css1/html4css1.css,sha256=-Uk0s5gu8-k8f4f34R-bSIpcSzqkVGa5JN6FGSh7QbY,7300 -docutils/writers/html4css1/template.txt,sha256=HDzUUyAv7gT4ewGQTqfOE2_9HOVyGu9-wCRgsmoCmjQ,114 -docutils/writers/html5_polyglot/__init__.py,sha256=9wqpd5R89Ewug52mD3g_9tGhyIr5dSEv0vLC0oA8ZOw,15635 -docutils/writers/html5_polyglot/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/html5_polyglot/italic-field-names.css,sha256=R9vxBFOn5NiQXWOLpghskCrn0RzMQEXy6w4EDDSNPXs,1145 -docutils/writers/html5_polyglot/math.css,sha256=eKRtxtJvYDzuQybRk6Ln_k9tr6TCoFhNqek40C9ErdM,6219 -docutils/writers/html5_polyglot/minimal.css,sha256=w78WllgDmLFNc-PwZRiD5_fhYB0zxAq7mGSh3c94TNM,8213 -docutils/writers/html5_polyglot/plain.css,sha256=-UeuH9qUxiAlETSiNjEm4Q1vAtpxD0QWwtN81pVo31Y,7552 -docutils/writers/html5_polyglot/responsive.css,sha256=PYhXgdnYR9hfGobvUMxi8OSPGr-KQUd2ucubuBRm5qg,11739 -docutils/writers/html5_polyglot/template.txt,sha256=HDzUUyAv7gT4ewGQTqfOE2_9HOVyGu9-wCRgsmoCmjQ,114 -docutils/writers/html5_polyglot/tuftig.css,sha256=ACotB-KbCWzGsanW1GncNwgMxa21vapRaAtv-NKdh8M,12023 -docutils/writers/latex2e/__init__.py,sha256=xs566hs7lq1MEteKh3PhCVj7jGdW3ivB_WNlrQ5pHVY,138165 -docutils/writers/latex2e/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/latex2e/default.tex,sha256=JcaJnrdmKE9vqwATl9dSHOsnGnjF2dLX4vsiu7kvWEI,422 -docutils/writers/latex2e/docutils.sty,sha256=dgnu97-E5w_rOrdaKBYAw_PwnMKASOFLXV08k17DABQ,5472 -docutils/writers/latex2e/titlepage.tex,sha256=ampRiXY22vtJ22UPMv61mmPubJPItdrSkl9MSAOftpQ,480 -docutils/writers/latex2e/titlingpage.tex,sha256=Pa9ixIf9Yy6RLljbTPUEgmrQwRzYsyzrxl4KSrHA37E,424 -docutils/writers/latex2e/xelatex.tex,sha256=NbrtTphygnEaTmyJEz5HwkNuWCbV1ijlh_1M7_TXLu0,672 -docutils/writers/manpage.py,sha256=REpVzDREXjLJ8ChcBpzbk3Wv8MJ45QWJuPRLB7s5nt8,38128 -docutils/writers/null.py,sha256=Ue7kizk6_1GGrCmYiltg9MrYNetMyHM-yvQvNRrclN8,568 -docutils/writers/odf_odt/__init__.py,sha256=uW_W6F_zMdbcqEmo4swfou2elk4XG-ShZusngP1acS4,132081 -docutils/writers/odf_odt/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/odf_odt/__pycache__/prepstyles.cpython-310.pyc,, -docutils/writers/odf_odt/__pycache__/pygmentsformatter.cpython-310.pyc,, -docutils/writers/odf_odt/prepstyles.py,sha256=XwC29yEYGKpNATr5yuGJH_WYkPBBUAkVr8fLaMEo6Yo,2142 -docutils/writers/odf_odt/pygmentsformatter.py,sha256=j1fMQPdv5fdczPkSKbyYjoh66G8Z_MZhTN52_XfRhHc,4681 -docutils/writers/odf_odt/styles.odt,sha256=xKv9z2sd1qNxAH28X-5st5JuDZeTw6jyDOxXohsFrKY,16500 -docutils/writers/pep_html/__init__.py,sha256=mrApLw1JROL32XM-eXrDjYnQq_DTS3_KqTNOEoiD55k,3503 -docutils/writers/pep_html/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/pep_html/pep.css,sha256=AyHZfudmKKTu-ZmyoLaihM_e5bD3_gCO51hG_NPEDA8,6367 -docutils/writers/pep_html/template.txt,sha256=SPc44ICSNgps08fDtVaRlu6glPPwcCcx9mqybx5u6W4,1001 -docutils/writers/pseudoxml.py,sha256=gjnBxBIXYNdnQYt_XTXljV3fcp9dW1Ek0LE5VkGIvJk,1032 -docutils/writers/s5_html/__init__.py,sha256=UahNZB0U6WSRb3jR6x1MXy4A4ud2bd8lduqG9Nn5Vao,14712 -docutils/writers/s5_html/__pycache__/__init__.cpython-310.pyc,, -docutils/writers/s5_html/themes/README.txt,sha256=wYnu3iomgGD6odpZOtWTzOynI1dfIGE6AVF1MDR0FVY,278 -docutils/writers/s5_html/themes/big-black/__base__,sha256=WeKnChXCPkrXDs7Xr-Qnf1i-bgFjkeaKJ-ilXV0R5lM,38 -docutils/writers/s5_html/themes/big-black/framing.css,sha256=DtEo7Fti9JARMLmcCx0NIfir7QRR24_WN3UbG-EyH64,910 -docutils/writers/s5_html/themes/big-black/pretty.css,sha256=UP9r7eGX0qEFCIDyKcT5bcazMxCw43O2KSrs2ebBPwI,3605 -docutils/writers/s5_html/themes/big-white/framing.css,sha256=meBByeaKIduudfFCDxVw4uzSOj8q_ZJArnwp8oZ1S8g,905 -docutils/writers/s5_html/themes/big-white/pretty.css,sha256=RlQ7CZuN-WMrR8CmCeQ-U8WVmZj769z2zx2FfLwTS48,3565 -docutils/writers/s5_html/themes/default/framing.css,sha256=Sbh5wryeioxDMZ-kJFwzKNziO-3CRvLBMG7rcJjTLmU,1002 -docutils/writers/s5_html/themes/default/opera.css,sha256=guPZOg_BINv-LjV9_IAM7ILFQ-fKALNjlP1i06e5dmA,261 -docutils/writers/s5_html/themes/default/outline.css,sha256=z3ACJiW3_gnG8XFvX602PMTYvKhbRybqCeoWl3O_pA0,648 -docutils/writers/s5_html/themes/default/pretty.css,sha256=iT_51bIPLTk1hFFs3hCarnyJqtbB4I86BNrxlT1r3eo,4383 -docutils/writers/s5_html/themes/default/print.css,sha256=INhYRMsY7y2wd9p7tqjcDWBREXHUMO-2ApAWvITyetI,818 -docutils/writers/s5_html/themes/default/s5-core.css,sha256=D4WDPb581O-_G5jhzpAIwI88B1Zi8y3nWBB8rCxgzlg,450 -docutils/writers/s5_html/themes/default/slides.css,sha256=VKYQ1Oe8lZ8LHxzPqJiU79J0z295nkmIbzsXL-N_dfQ,283 -docutils/writers/s5_html/themes/default/slides.js,sha256=5BXUM5jSWu9hUQSVhGZhMTEvkdCYgqrOJO3ljwDgxWI,15801 -docutils/writers/s5_html/themes/medium-black/__base__,sha256=822LJG-LrdBZY6CA7wsLFCFzsYfxbyz2mr1j6rpb1UA,41 -docutils/writers/s5_html/themes/medium-black/pretty.css,sha256=OdL1xJ9f_FE1pmS7X0s0yxyIl1n2vUBQaGOcJrT2svg,4029 -docutils/writers/s5_html/themes/medium-white/framing.css,sha256=BF5YnRLGRhobO06xDet-0KZYpR10IgRjRbULPVm3PMM,943 -docutils/writers/s5_html/themes/medium-white/pretty.css,sha256=Zm-Pgk3SLAGmGTRF27nrqvpBb_LH2yQ5FIpDPM3p0Y0,3989 -docutils/writers/s5_html/themes/small-black/__base__,sha256=WmiB80z49RfMsy_7tFI042AfUgyztL5OXI3tap9EfQM,40 -docutils/writers/s5_html/themes/small-black/pretty.css,sha256=fmc73kx-zOp0jbiy4GAmpw2Xdz9Q_-WzebsgDJWUJos,4028 -docutils/writers/s5_html/themes/small-white/framing.css,sha256=qwNUgzqnrXgoX47SddbVIKEZwQDjGnTGA468jHHIXqc,940 -docutils/writers/s5_html/themes/small-white/pretty.css,sha256=qU8WOhY8TT6ZY6cXKXABb7T7JgpJQORzTZJhuAm0gGg,3999 -docutils/writers/xetex/__init__.py,sha256=o25hpaSPL9erEUe18GIzaVbP2QuYtjZ0SwSkDeXfZ6k,5736 -docutils/writers/xetex/__pycache__/__init__.cpython-310.pyc,, diff --git a/venv/Lib/site-packages/docutils-0.21.2.dist-info/WHEEL b/venv/Lib/site-packages/docutils-0.21.2.dist-info/WHEEL deleted file mode 100644 index 3b5e64b..0000000 --- a/venv/Lib/site-packages/docutils-0.21.2.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: flit 3.9.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/Lib/site-packages/docutils-0.21.2.dist-info/entry_points.txt b/venv/Lib/site-packages/docutils-0.21.2.dist-info/entry_points.txt deleted file mode 100644 index 3e32d4e..0000000 --- a/venv/Lib/site-packages/docutils-0.21.2.dist-info/entry_points.txt +++ /dev/null @@ -1,13 +0,0 @@ -[console_scripts] -docutils=docutils.__main__:main -rst2html=docutils.core:rst2html -rst2html4=docutils.core:rst2html4 -rst2html5=docutils.core:rst2html5 -rst2latex=docutils.core:rst2latex -rst2man=docutils.core:rst2man -rst2odt=docutils.core:rst2odt -rst2pseudoxml=docutils.core:rst2pseudoxml -rst2s5=docutils.core:rst2s5 -rst2xetex=docutils.core:rst2xetex -rst2xml=docutils.core:rst2xml - diff --git a/venv/Lib/site-packages/docutils/__init__.py b/venv/Lib/site-packages/docutils/__init__.py deleted file mode 100644 index 16af410..0000000 --- a/venv/Lib/site-packages/docutils/__init__.py +++ /dev/null @@ -1,291 +0,0 @@ -# $Id: __init__.py 9649 2024-04-23 18:54:26Z grubert $ -# Author: David Goodger -# Copyright: This module has been placed in the public domain. - -""" -This is the Docutils (Python Documentation Utilities) package. - -Package Structure -================= - -Modules: - -- __init__.py: Contains component base classes, exception classes, and - Docutils version information. - -- core.py: Contains the ``Publisher`` class and ``publish_*()`` convenience - functions. - -- frontend.py: Runtime settings (command-line interface, configuration files) - processing, for Docutils front-ends. - -- io.py: Provides a uniform API for low-level input and output. - -- nodes.py: Docutils document tree (doctree) node class library. - -- statemachine.py: A finite state machine specialized for - regular-expression-based text filters. - -Subpackages: - -- languages: Language-specific mappings of terms. - -- parsers: Syntax-specific input parser modules or packages. - -- readers: Context-specific input handlers which understand the data - source and manage a parser. - -- transforms: Modules used by readers and writers to modify - the Docutils document tree. - -- utils: Contains the ``Reporter`` system warning class and miscellaneous - utilities used by readers, writers, and transforms. - - utils/urischemes.py: Contains a complete mapping of known URI addressing - scheme names to descriptions. - -- utils/math: Contains functions for conversion of mathematical notation - between different formats (LaTeX, MathML, text, ...). - -- writers: Format-specific output translators. -""" - -from collections import namedtuple - -__docformat__ = 'reStructuredText' - -__version__ = '0.21.2' -"""Docutils version identifier (complies with PEP 440):: - - major.minor[.micro][releaselevel[serial]][.dev] - -For version comparison operations, use `__version_info__` (see, below) -rather than parsing the text of `__version__`. - -https://docutils.sourceforge.io/docs/dev/policies.html#version-identification -""" - -__version_details__ = '' -"""Optional extra version details (e.g. 'snapshot 2005-05-29, r3410'). - -For development and release status, use `__version__ and `__version_info__`. -""" - - -class VersionInfo(namedtuple('VersionInfo', - 'major minor micro releaselevel serial release')): - - def __new__(cls, major=0, minor=0, micro=0, - releaselevel='final', serial=0, release=True): - releaselevels = ('alpha', 'beta', 'candidate', 'final') - if releaselevel not in releaselevels: - raise ValueError('releaselevel must be one of %r.' - % (releaselevels, )) - if releaselevel == 'final': - if not release: - raise ValueError('releaselevel "final" must not be used ' - 'with development versions (leads to wrong ' - 'version ordering of the related __version__') - # cf. https://peps.python.org/pep-0440/#summary-of-permitted-suffixes-and-relative-ordering # noqa - if serial != 0: - raise ValueError('"serial" must be 0 for final releases') - - return super().__new__(cls, major, minor, micro, - releaselevel, serial, release) - - def __lt__(self, other): - if isinstance(other, tuple): - other = VersionInfo(*other) - return tuple.__lt__(self, other) - - def __gt__(self, other): - if isinstance(other, tuple): - other = VersionInfo(*other) - return tuple.__gt__(self, other) - - def __le__(self, other): - if isinstance(other, tuple): - other = VersionInfo(*other) - return tuple.__le__(self, other) - - def __ge__(self, other): - if isinstance(other, tuple): - other = VersionInfo(*other) - return tuple.__ge__(self, other) - - -__version_info__ = VersionInfo( - major=0, - minor=21, - micro=2, - releaselevel='final', # one of 'alpha', 'beta', 'candidate', 'final' - serial=0, # pre-release number (0 for final releases and snapshots) - release=True # True for official releases and pre-releases - ) -"""Comprehensive version information tuple. - -https://docutils.sourceforge.io/docs/dev/policies.html#version-identification -""" - - -class ApplicationError(Exception): pass -class DataError(ApplicationError): pass - - -class SettingsSpec: - - """ - Runtime setting specification base class. - - SettingsSpec subclass objects used by `docutils.frontend.OptionParser`. - """ - - # TODO: replace settings_specs with a new data structure - # Backwards compatiblity: - # Drop-in components: - # Sphinx supplies settings_spec in the current format in some places - # Myst parser provides a settings_spec tuple - # - # Sphinx reads a settings_spec in order to set a default value - # in writers/html.py:59 - # https://github.com/sphinx-doc/sphinx/blob/4.x/sphinx/writers/html.py - # This should be changed (before retiring the old format) - # to use `settings_default_overrides` instead. - settings_spec = () - """Runtime settings specification. Override in subclasses. - - Defines runtime settings and associated command-line options, as used by - `docutils.frontend.OptionParser`. This is a tuple of: - - - Option group title (string or `None` which implies no group, just a list - of single options). - - - Description (string or `None`). - - - A sequence of option tuples. Each consists of: - - - Help text (string) - - - List of option strings (e.g. ``['-Q', '--quux']``). - - - Dictionary of keyword arguments sent to the OptionParser/OptionGroup - ``add_option`` method. - - Runtime setting names are derived implicitly from long option names - ('--a-setting' becomes ``settings.a_setting``) or explicitly from the - 'dest' keyword argument. - - Most settings will also have a 'validator' keyword & function. The - validator function validates setting values (from configuration files - and command-line option arguments) and converts them to appropriate - types. For example, the ``docutils.frontend.validate_boolean`` - function, **required by all boolean settings**, converts true values - ('1', 'on', 'yes', and 'true') to 1 and false values ('0', 'off', - 'no', 'false', and '') to 0. Validators need only be set once per - setting. See the `docutils.frontend.validate_*` functions. - - See the optparse docs for more details. - - - More triples of group title, description, options, as many times as - needed. Thus, `settings_spec` tuples can be simply concatenated. - """ - - settings_defaults = None - """A dictionary of defaults for settings not in `settings_spec` (internal - settings, intended to be inaccessible by command-line and config file). - Override in subclasses.""" - - settings_default_overrides = None - """A dictionary of auxiliary defaults, to override defaults for settings - defined in other components' `setting_specs`. Override in subclasses.""" - - relative_path_settings = () - """Settings containing filesystem paths. Override in subclasses. - Settings listed here are to be interpreted relative to the current working - directory.""" - - config_section = None - """The name of the config file section specific to this component - (lowercase, no brackets). Override in subclasses.""" - - config_section_dependencies = None - """A list of names of config file sections that are to be applied before - `config_section`, in order (from general to specific). In other words, - the settings in `config_section` are to be overlaid on top of the settings - from these sections. The "general" section is assumed implicitly. - Override in subclasses.""" - - -class TransformSpec: - """ - Runtime transform specification base class. - - Provides the interface to register "transforms" and helper functions - to resolve references with a `docutils.transforms.Transformer`. - - https://docutils.sourceforge.io/docs/ref/transforms.html - """ - - def get_transforms(self): - """Transforms required by this class. Override in subclasses.""" - if self.default_transforms != (): - import warnings - warnings.warn('TransformSpec: the "default_transforms" attribute ' - 'will be removed in Docutils 2.0.\n' - 'Use get_transforms() method instead.', - DeprecationWarning) - return list(self.default_transforms) - return [] - - # Deprecated; for compatibility. - default_transforms = () - - unknown_reference_resolvers = () - """List of functions to try to resolve unknown references. - - Unknown references have a 'refname' attribute which doesn't correspond - to any target in the document. Called when the transforms in - `docutils.transforms.references` are unable to find a correct target. - - The list should contain functions which will try to resolve unknown - references, with the following signature:: - - def reference_resolver(node): - '''Returns boolean: true if resolved, false if not.''' - - If the function is able to resolve the reference, it should also remove - the 'refname' attribute and mark the node as resolved:: - - del node['refname'] - node.resolved = 1 - - Each function must have a "priority" attribute which will affect the order - the unknown_reference_resolvers are run:: - - reference_resolver.priority = 100 - - This hook is provided for 3rd party extensions. - Example use case: the `MoinMoin - ReStructured Text Parser` - in ``sandbox/mmgilbe/rst.py``. - """ - - -class Component(SettingsSpec, TransformSpec): - - """Base class for Docutils components.""" - - component_type = None - """Name of the component type ('reader', 'parser', 'writer'). Override in - subclasses.""" - - supported = () - """Name and aliases for this component. Override in subclasses.""" - - def supports(self, format): - """ - Is `format` supported by this component? - - To be used by transforms to ask the dependent component if it supports - a certain input context or output format. - """ - return format in self.supported diff --git a/venv/Lib/site-packages/docutils/__main__.py b/venv/Lib/site-packages/docutils/__main__.py deleted file mode 100644 index ce61489..0000000 --- a/venv/Lib/site-packages/docutils/__main__.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python3 -# :Copyright: © 2020, 2022 Günter Milde. -# :License: Released under the terms of the `2-Clause BSD license`_, in short: -# -# Copying and distribution of this file, with or without modification, -# are permitted in any medium without royalty provided the copyright -# notice and this notice are preserved. -# This file is offered as-is, without any warranty. -# -# .. _2-Clause BSD license: https://opensource.org/licenses/BSD-2-Clause -# -# Revision: $Revision: 9107 $ -# Date: $Date: 2022-07-06 15:59:57 +0200 (Mi, 06. Jul 2022) $ - -"""Generic command line interface for the `docutils` package. - -See also -https://docs.python.org/3/library/__main__.html#main-py-in-python-packages -""" - -import argparse -import locale -import sys - -import docutils -from docutils.core import Publisher, publish_cmdline, default_description - - -class CliSettingsSpec(docutils.SettingsSpec): - """Runtime settings & command-line options for the generic CLI. - - Configurable reader, parser, and writer components. - - The "--writer" default will change to 'html' in Docutils 2.0 - when 'html' becomes an alias for the current value 'html5'. - """ - - settings_spec = ( - 'Docutils Application Options', - 'Reader, writer, and parser settings influence the available options. ' - ' Example: use `--help --writer=latex` to see LaTeX writer options. ', - # options: ('help text', [

    "). - """ - overrides = {'input_encoding': input_encoding, - 'doctitle_xform': doctitle, - 'initial_header_level': initial_header_level} - parts = core.publish_parts( - source=input_string, source_path=source_path, - destination_path=destination_path, - writer_name='html', settings_overrides=overrides) - return parts - - -def html_body(input_string, source_path=None, destination_path=None, - input_encoding='unicode', output_encoding='unicode', - doctitle=True, initial_header_level=1): - """ - Given an input string, returns an HTML fragment as a string. - - The return value is the contents of the element. - - Parameters (see `html_parts()` for the remainder): - - - `output_encoding`: The desired encoding of the output. If a Unicode - string is desired, use the default value of "unicode" . - """ - parts = html_parts( - input_string=input_string, source_path=source_path, - destination_path=destination_path, - input_encoding=input_encoding, doctitle=doctitle, - initial_header_level=initial_header_level) - fragment = parts['html_body'] - if output_encoding != 'unicode': - fragment = fragment.encode(output_encoding) - return fragment - - -def internals(input_string, source_path=None, destination_path=None, - input_encoding='unicode', settings_overrides=None): - """ - Return the document tree and publisher, for exploring Docutils internals. - - Parameters: see `html_parts()`. - """ - if settings_overrides: - overrides = settings_overrides.copy() - else: - overrides = {} - overrides['input_encoding'] = input_encoding - output, pub = core.publish_programmatically( - source_class=io.StringInput, source=input_string, - source_path=source_path, - destination_class=io.NullOutput, destination=None, - destination_path=destination_path, - reader=None, reader_name='standalone', - parser=None, parser_name='restructuredtext', - writer=None, writer_name='null', - settings=None, settings_spec=None, settings_overrides=overrides, - config_section=None, enable_exit_status=None) - return pub.writer.document, pub diff --git a/venv/Lib/site-packages/docutils/frontend.py b/venv/Lib/site-packages/docutils/frontend.py deleted file mode 100644 index 2499c62..0000000 --- a/venv/Lib/site-packages/docutils/frontend.py +++ /dev/null @@ -1,1065 +0,0 @@ -# $Id: frontend.py 9540 2024-02-17 10:36:59Z milde $ -# Author: David Goodger -# Copyright: This module has been placed in the public domain. - -""" -Command-line and common processing for Docutils front-end tools. - -This module is provisional. -Major changes will happen with the switch from the deprecated -"optparse" module to "arparse". - -Applications should use the high-level API provided by `docutils.core`. -See https://docutils.sourceforge.io/docs/api/runtime-settings.html. - -Exports the following classes: - -* `OptionParser`: Standard Docutils command-line processing. - Deprecated. Will be replaced by an ArgumentParser. -* `Option`: Customized version of `optparse.Option`; validation support. - Deprecated. Will be removed. -* `Values`: Runtime settings; objects are simple structs - (``object.attribute``). Supports cumulative list settings (attributes). - Deprecated. Will be removed. -* `ConfigParser`: Standard Docutils config file processing. - Provisional. Details will change. - -Also exports the following functions: - -Interface function: - `get_default_settings()`. New in 0.19. - -Option callbacks: - `store_multiple()`, `read_config_file()`. Deprecated. - -Setting validators: - `validate_encoding()`, `validate_encoding_error_handler()`, - `validate_encoding_and_error_handler()`, - `validate_boolean()`, `validate_ternary()`, - `validate_nonnegative_int()`, `validate_threshold()`, - `validate_colon_separated_string_list()`, - `validate_comma_separated_list()`, - `validate_url_trailing_slash()`, - `validate_dependency_file()`, - `validate_strip_class()` - `validate_smartquotes_locales()`. - - Provisional. - -Misc: - `make_paths_absolute()`, `filter_settings_spec()`. Provisional. -""" - -__docformat__ = 'reStructuredText' - - -import codecs -import configparser -import optparse -from optparse import SUPPRESS_HELP -import os -import os.path -from pathlib import Path -import sys -import warnings - -import docutils -from docutils import io, utils - - -def store_multiple(option, opt, value, parser, *args, **kwargs): - """ - Store multiple values in `parser.values`. (Option callback.) - - Store `None` for each attribute named in `args`, and store the value for - each key (attribute name) in `kwargs`. - """ - for attribute in args: - setattr(parser.values, attribute, None) - for key, value in kwargs.items(): - setattr(parser.values, key, value) - - -def read_config_file(option, opt, value, parser): - """ - Read a configuration file during option processing. (Option callback.) - """ - try: - new_settings = parser.get_config_file_settings(value) - except ValueError as err: - parser.error(err) - parser.values.update(new_settings, parser) - - -def validate_encoding(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - if value == '': - return None # allow overwriting a config file value - try: - codecs.lookup(value) - except LookupError: - raise LookupError('setting "%s": unknown encoding: "%s"' - % (setting, value)) - return value - - -def validate_encoding_error_handler(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - try: - codecs.lookup_error(value) - except LookupError: - raise LookupError( - 'unknown encoding error handler: "%s" (choices: ' - '"strict", "ignore", "replace", "backslashreplace", ' - '"xmlcharrefreplace", and possibly others; see documentation for ' - 'the Python ``codecs`` module)' % value) - return value - - -def validate_encoding_and_error_handler( - setting, value, option_parser, config_parser=None, config_section=None): - """ - Side-effect: if an error handler is included in the value, it is inserted - into the appropriate place as if it were a separate setting/option. - """ - if ':' in value: - encoding, handler = value.split(':') - validate_encoding_error_handler(handler) - if config_parser: - config_parser.set(config_section, setting + '_error_handler', - handler) - else: - setattr(option_parser.values, setting + '_error_handler', handler) - else: - encoding = value - return validate_encoding(encoding) - - -def validate_boolean(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - """Check/normalize boolean settings: - True: '1', 'on', 'yes', 'true' - False: '0', 'off', 'no','false', '' - - All arguments except `value` are ignored - (kept for compatibility with "optparse" module). - If there is only one positional argument, it is interpreted as `value`. - """ - if value is None: - value = setting - if isinstance(value, bool): - return value - try: - return OptionParser.booleans[value.strip().lower()] - except KeyError: - raise LookupError('unknown boolean value: "%s"' % value) - - -def validate_ternary(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - """Check/normalize three-value settings: - True: '1', 'on', 'yes', 'true' - False: '0', 'off', 'no','false', '' - any other value: returned as-is. - - All arguments except `value` are ignored - (kept for compatibility with "optparse" module). - If there is only one positional argument, it is interpreted as `value`. - """ - if value is None: - value = setting - if isinstance(value, bool) or value is None: - return value - try: - return OptionParser.booleans[value.strip().lower()] - except KeyError: - return value - - -def validate_nonnegative_int(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - value = int(value) - if value < 0: - raise ValueError('negative value; must be positive or zero') - return value - - -def validate_threshold(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - try: - return int(value) - except ValueError: - try: - return OptionParser.thresholds[value.lower()] - except (KeyError, AttributeError): - raise LookupError('unknown threshold: %r.' % value) - - -def validate_colon_separated_string_list( - setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - if not isinstance(value, list): - value = value.split(':') - else: - last = value.pop() - value.extend(last.split(':')) - return value - - -def validate_comma_separated_list(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - """Check/normalize list arguments (split at "," and strip whitespace). - - All arguments except `value` are ignored - (kept for compatibility with "optparse" module). - If there is only one positional argument, it is interpreted as `value`. - """ - if value is None: - value = setting - # `value` may be ``bytes``, ``str``, or a ``list`` (when given as - # command line option and "action" is "append"). - if not isinstance(value, list): - value = [value] - # this function is called for every option added to `value` - # -> split the last item and append the result: - last = value.pop() - items = [i.strip(' \t\n') for i in last.split(',') if i.strip(' \t\n')] - value.extend(items) - return value - - -def validate_math_output(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - """Check "math-output" setting, return list with "format" and "options". - - See also https://docutils.sourceforge.io/docs/user/config.html#math-output - - Argument list for compatibility with "optparse" module. - All arguments except `value` are ignored. - If there is only one positional argument, it is interpreted as `value`. - """ - if value is None: - value = setting - - formats = ('html', 'latex', 'mathml', 'mathjax') - tex2mathml_converters = ('', 'latexml', 'ttm', 'blahtexml', 'pandoc') - - if not value: - return [] - values = value.split(maxsplit=1) - format = values[0].lower() - try: - options = values[1] - except IndexError: - options = '' - if format not in formats: - raise LookupError(f'Unknown math output format: "{value}",\n' - f' choose from {formats}.') - if format == 'mathml': - converter = options.lower() - if converter not in tex2mathml_converters: - raise LookupError(f'MathML converter "{options}" not supported,\n' - f' choose from {tex2mathml_converters}.') - options = converter - return [format, options] - - -def validate_url_trailing_slash(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - if not value: - return './' - elif value.endswith('/'): - return value - else: - return value + '/' - - -def validate_dependency_file(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - try: - return utils.DependencyList(value) - except OSError: - # TODO: warn/info? - return utils.DependencyList(None) - - -def validate_strip_class(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - # All arguments except `value` are ignored - # (kept for compatibility with "optparse" module). - # If there is only one positional argument, it is interpreted as `value`. - if value is None: - value = setting - # value is a comma separated string list: - value = validate_comma_separated_list(value) - # validate list elements: - for cls in value: - normalized = docutils.nodes.make_id(cls) - if cls != normalized: - raise ValueError('Invalid class value %r (perhaps %r?)' - % (cls, normalized)) - return value - - -def validate_smartquotes_locales(setting, value=None, option_parser=None, - config_parser=None, config_section=None): - """Check/normalize a comma separated list of smart quote definitions. - - Return a list of (language-tag, quotes) string tuples. - - All arguments except `value` are ignored - (kept for compatibility with "optparse" module). - If there is only one positional argument, it is interpreted as `value`. - """ - if value is None: - value = setting - # value is a comma separated string list: - value = validate_comma_separated_list(value) - # validate list elements - lc_quotes = [] - for item in value: - try: - lang, quotes = item.split(':', 1) - except AttributeError: - # this function is called for every option added to `value` - # -> ignore if already a tuple: - lc_quotes.append(item) - continue - except ValueError: - raise ValueError('Invalid value "%s".' - ' Format is ":".' - % item.encode('ascii', 'backslashreplace')) - # parse colon separated string list: - quotes = quotes.strip() - multichar_quotes = quotes.split(':') - if len(multichar_quotes) == 4: - quotes = multichar_quotes - elif len(quotes) != 4: - raise ValueError('Invalid value "%s". Please specify 4 quotes\n' - ' (primary open/close; secondary open/close).' - % item.encode('ascii', 'backslashreplace')) - lc_quotes.append((lang, quotes)) - return lc_quotes - - -def make_paths_absolute(pathdict, keys, base_path=None): - """ - Interpret filesystem path settings relative to the `base_path` given. - - Paths are values in `pathdict` whose keys are in `keys`. Get `keys` from - `OptionParser.relative_path_settings`. - """ - if base_path is None: - base_path = Path.cwd() - else: - base_path = Path(base_path) - for key in keys: - if key in pathdict: - value = pathdict[key] - if isinstance(value, list): - value = [str((base_path/path).resolve()) for path in value] - elif value: - value = str((base_path/value).resolve()) - pathdict[key] = value - - -def make_one_path_absolute(base_path, path): - # deprecated, will be removed - warnings.warn('frontend.make_one_path_absolute() will be removed ' - 'in Docutils 0.23.', DeprecationWarning, stacklevel=2) - return os.path.abspath(os.path.join(base_path, path)) - - -def filter_settings_spec(settings_spec, *exclude, **replace): - """Return a copy of `settings_spec` excluding/replacing some settings. - - `settings_spec` is a tuple of configuration settings - (cf. `docutils.SettingsSpec.settings_spec`). - - Optional positional arguments are names of to-be-excluded settings. - Keyword arguments are option specification replacements. - (See the html4strict writer for an example.) - """ - settings = list(settings_spec) - # every third item is a sequence of option tuples - for i in range(2, len(settings), 3): - newopts = [] - for opt_spec in settings[i]: - # opt_spec is ("", [more' - self.assertEqual(smartyPants(text), text) - - suite = unittest.TestLoader().loadTestsFromTestCase( - TestSmartypantsAllAttributes) - unittest.TextTestRunner().run(suite) - - else: - if args.alternative_quotes: - if '-x-altquot' in args.language: - args.language = args.language.replace('-x-altquot', '') - else: - args.language += '-x-altquot' - text = sys.stdin.read() - print(smartyPants(text, attr=args.action, language=args.language)) diff --git a/venv/Lib/site-packages/docutils/utils/urischemes.py b/venv/Lib/site-packages/docutils/utils/urischemes.py deleted file mode 100644 index a0435c0..0000000 --- a/venv/Lib/site-packages/docutils/utils/urischemes.py +++ /dev/null @@ -1,138 +0,0 @@ -# $Id: urischemes.py 9315 2023-01-15 19:27:55Z milde $ -# Author: David Goodger -# Copyright: This module has been placed in the public domain. - -""" -`schemes` is a dictionary with lowercase URI addressing schemes as -keys and descriptions as values. It was compiled from the index at -http://www.iana.org/assignments/uri-schemes (revised 2005-11-28) -and an older list at https://www.w3.org/Addressing/schemes.html. -""" - -# Many values are blank and should be filled in with useful descriptions. - -schemes = { - 'about': 'provides information on Navigator', - 'acap': 'Application Configuration Access Protocol; RFC 2244', - 'addbook': "To add vCard entries to Communicator's Address Book", - 'afp': 'Apple Filing Protocol', - 'afs': 'Andrew File System global file names', - 'aim': 'AOL Instant Messenger', - 'callto': 'for NetMeeting links', - 'castanet': 'Castanet Tuner URLs for Netcaster', - 'chttp': 'cached HTTP supported by RealPlayer', - 'cid': 'content identifier; RFC 2392', - 'crid': 'TV-Anytime Content Reference Identifier; RFC 4078', - 'data': 'allows inclusion of small data items as "immediate" data; ' - 'RFC 2397', - 'dav': 'Distributed Authoring and Versioning Protocol; RFC 2518', - 'dict': 'dictionary service protocol; RFC 2229', - 'dns': 'Domain Name System resources', - 'eid': 'External ID; non-URL data; general escape mechanism to allow ' - 'access to information for applications that are too ' - 'specialized to justify their own schemes', - 'fax': 'a connection to a terminal that can handle telefaxes ' - '(facsimiles); RFC 2806', - 'feed': 'NetNewsWire feed', - 'file': 'Host-specific file names; RFC 1738', - 'finger': '', - 'freenet': '', - 'ftp': 'File Transfer Protocol; RFC 1738', - 'go': 'go; RFC 3368', - 'gopher': 'The Gopher Protocol', - 'gsm-sms': 'Global System for Mobile Communications Short Message ' - 'Service', - 'h323': 'video (audiovisual) communication on local area networks; ' - 'RFC 3508', - 'h324': 'video and audio communications over low bitrate connections ' - 'such as POTS modem connections', - 'hdl': 'CNRI handle system', - 'hnews': 'an HTTP-tunneling variant of the NNTP news protocol', - 'http': 'Hypertext Transfer Protocol; RFC 2616', - 'https': 'HTTP over SSL; RFC 2818', - 'hydra': 'SubEthaEdit URI. ' - 'See http://www.codingmonkeys.de/subethaedit.', - 'iioploc': 'Internet Inter-ORB Protocol Location?', - 'ilu': 'Inter-Language Unification', - 'im': 'Instant Messaging; RFC 3860', - 'imap': 'Internet Message Access Protocol; RFC 2192', - 'info': 'Information Assets with Identifiers in Public Namespaces', - 'ior': 'CORBA interoperable object reference', - 'ipp': 'Internet Printing Protocol; RFC 3510', - 'irc': 'Internet Relay Chat', - 'iris.beep': 'iris.beep; RFC 3983', - 'iseek': 'See www.ambrosiasw.com; a little util for OS X.', - 'jar': 'Java archive', - 'javascript': 'JavaScript code; ' - 'evaluates the expression after the colon', - 'jdbc': 'JDBC connection URI.', - 'ldap': 'Lightweight Directory Access Protocol', - 'lifn': '', - 'livescript': '', - 'lrq': '', - 'mailbox': 'Mail folder access', - 'mailserver': 'Access to data available from mail servers', - 'mailto': 'Electronic mail address; RFC 2368', - 'md5': '', - 'mid': 'message identifier; RFC 2392', - 'mocha': '', - 'modem': 'a connection to a terminal that can handle incoming data ' - 'calls; RFC 2806', - 'mtqp': 'Message Tracking Query Protocol; RFC 3887', - 'mupdate': 'Mailbox Update (MUPDATE) Protocol; RFC 3656', - 'news': 'USENET news; RFC 1738', - 'nfs': 'Network File System protocol; RFC 2224', - 'nntp': 'USENET news using NNTP access; RFC 1738', - 'opaquelocktoken': 'RFC 2518', - 'phone': '', - 'pop': 'Post Office Protocol; RFC 2384', - 'pop3': 'Post Office Protocol v3', - 'pres': 'Presence; RFC 3859', - 'printer': '', - 'prospero': 'Prospero Directory Service; RFC 4157', - 'rdar': 'URLs found in Darwin source ' - '(http://www.opensource.apple.com/darwinsource/).', - 'res': '', - 'rtsp': 'real time streaming protocol; RFC 2326', - 'rvp': '', - 'rwhois': '', - 'rx': 'Remote Execution', - 'sdp': '', - 'service': 'service location; RFC 2609', - 'shttp': 'secure hypertext transfer protocol', - 'sip': 'Session Initiation Protocol; RFC 3261', - 'sips': 'secure session intitiaion protocol; RFC 3261', - 'smb': 'SAMBA filesystems.', - 'snews': 'For NNTP postings via SSL', - 'snmp': 'Simple Network Management Protocol; RFC 4088', - 'soap.beep': 'RFC 3288', - 'soap.beeps': 'RFC 3288', - 'ssh': 'Reference to interactive sessions via ssh.', - 't120': 'real time data conferencing (audiographics)', - 'tag': 'RFC 4151', - 'tcp': '', - 'tel': 'a connection to a terminal that handles normal voice ' - 'telephone calls, a voice mailbox or another voice messaging ' - 'system or a service that can be operated using DTMF tones; ' - 'RFC 3966.', - 'telephone': 'telephone', - 'telnet': 'Reference to interactive sessions; RFC 4248', - 'tftp': 'Trivial File Transfer Protocol; RFC 3617', - 'tip': 'Transaction Internet Protocol; RFC 2371', - 'tn3270': 'Interactive 3270 emulation sessions', - 'tv': '', - 'urn': 'Uniform Resource Name; RFC 2141', - 'uuid': '', - 'vemmi': 'versatile multimedia interface; RFC 2122', - 'videotex': '', - 'view-source': 'displays HTML code that was generated with JavaScript', - 'wais': 'Wide Area Information Servers; RFC 4156', - 'whodp': '', - 'whois++': 'Distributed directory service.', - 'x-man-page': 'Opens man page in Terminal.app on OS X ' - '(see macosxhints.com)', - 'xmlrpc.beep': 'RFC 3529', - 'xmlrpc.beeps': 'RFC 3529', - 'z39.50r': 'Z39.50 Retrieval; RFC 2056', - 'z39.50s': 'Z39.50 Session; RFC 2056', - } diff --git a/venv/Lib/site-packages/docutils/writers/__init__.py b/venv/Lib/site-packages/docutils/writers/__init__.py deleted file mode 100644 index eb6d3d2..0000000 --- a/venv/Lib/site-packages/docutils/writers/__init__.py +++ /dev/null @@ -1,159 +0,0 @@ -# $Id: __init__.py 9368 2023-04-28 21:26:36Z milde $ -# Author: David Goodger -# Copyright: This module has been placed in the public domain. - -""" -This package contains Docutils Writer modules. -""" - -__docformat__ = 'reStructuredText' - -from importlib import import_module - -import docutils -from docutils import languages, Component -from docutils.transforms import universal - - -class Writer(Component): - - """ - Abstract base class for docutils Writers. - - Each writer module or package must export a subclass also called 'Writer'. - Each writer must support all standard node types listed in - `docutils.nodes.node_class_names`. - - The `write()` method is the main entry point. - """ - - component_type = 'writer' - config_section = 'writers' - - def get_transforms(self): - return super().get_transforms() + [universal.Messages, - universal.FilterMessages, - universal.StripClassesAndElements] - - document = None - """The document to write (Docutils doctree); set by `write()`.""" - - output = None - """Final translated form of `document` - - (`str` for text, `bytes` for binary formats); set by `translate()`. - """ - - language = None - """Language module for the document; set by `write()`.""" - - destination = None - """`docutils.io` Output object; where to write the document. - - Set by `write()`. - """ - - def __init__(self): - - self.parts = {} - """Mapping of document part names to fragments of `self.output`. - - See `Writer.assemble_parts()` below and - . - """ - - def write(self, document, destination): - """ - Process a document into its final form. - - Translate `document` (a Docutils document tree) into the Writer's - native format, and write it out to its `destination` (a - `docutils.io.Output` subclass object). - - Normally not overridden or extended in subclasses. - """ - self.document = document - self.language = languages.get_language( - document.settings.language_code, - document.reporter) - self.destination = destination - self.translate() - return self.destination.write(self.output) - - def translate(self): - """ - Do final translation of `self.document` into `self.output`. Called - from `write`. Override in subclasses. - - Usually done with a `docutils.nodes.NodeVisitor` subclass, in - combination with a call to `docutils.nodes.Node.walk()` or - `docutils.nodes.Node.walkabout()`. The ``NodeVisitor`` subclass must - support all standard elements (listed in - `docutils.nodes.node_class_names`) and possibly non-standard elements - used by the current Reader as well. - """ - raise NotImplementedError('subclass must override this method') - - def assemble_parts(self): - """Assemble the `self.parts` dictionary. Extend in subclasses. - - See . - """ - self.parts['whole'] = self.output - self.parts['encoding'] = self.document.settings.output_encoding - self.parts['errors'] = ( - self.document.settings.output_encoding_error_handler) - self.parts['version'] = docutils.__version__ - - -class UnfilteredWriter(Writer): - - """ - A writer that passes the document tree on unchanged (e.g. a - serializer.) - - Documents written by UnfilteredWriters are typically reused at a - later date using a subclass of `readers.ReReader`. - """ - - def get_transforms(self): - # Do not add any transforms. When the document is reused - # later, the then-used writer will add the appropriate - # transforms. - return Component.get_transforms(self) - - -_writer_aliases = { - 'html': 'html4css1', # may change to html5 some day - 'html4': 'html4css1', - 'xhtml10': 'html4css1', - 'html5': 'html5_polyglot', - 'xhtml': 'html5_polyglot', - 's5': 's5_html', - 'latex': 'latex2e', - 'xelatex': 'xetex', - 'luatex': 'xetex', - 'lualatex': 'xetex', - 'odf': 'odf_odt', - 'odt': 'odf_odt', - 'ooffice': 'odf_odt', - 'openoffice': 'odf_odt', - 'libreoffice': 'odf_odt', - 'pprint': 'pseudoxml', - 'pformat': 'pseudoxml', - 'pdf': 'rlpdf', - 'xml': 'docutils_xml'} - - -def get_writer_class(writer_name): - """Return the Writer class from the `writer_name` module.""" - name = writer_name.lower() - name = _writer_aliases.get(name, name) - try: - module = import_module('docutils.writers.'+name) - except ImportError: - try: - module = import_module(name) - except ImportError as err: - raise ImportError(f'Writer "{writer_name}" not found. {err}') - return module.Writer diff --git a/venv/Lib/site-packages/docutils/writers/__pycache__/__init__.cpython-310.pyc b/venv/Lib/site-packages/docutils/writers/__pycache__/__init__.cpython-310.pyc deleted file mode 100644 index f8c895b74d4c4e3125a508dbd7779c4d9a69026d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4529 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 Xu>b0I?7z6j>_6MbZOi{t>xKUVJyz@H diff --git a/venv/Lib/site-packages/docutils/writers/__pycache__/_html_base.cpython-310.pyc b/venv/Lib/site-packages/docutils/writers/__pycache__/_html_base.cpython-310.pyc deleted file mode 100644 index 1dd8b88c17040f9cc74077b6957707dee5119ebb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63532 zcmc${37lL0J8%xHfEz|0m>Y3@$O!v4> zkCsCZ7|Q{(IIIBzHq3wtn2>}7LP#JRBqSjO5|W#xZx%>+H*sFJdwp|Xu7a)i|9^GP z={~(k=J9*)&HVaQopb8c@>SJW-&S9hy1P>${QdmjY@2)Au5jq@cvJru#m%kw*+0NV zg)$)(R@Oo|6PD1*SQ17u5ecIbMiyd=@k~5y(k3zqd6CG5y_NSIpev_j#~Vppcy zP1%#_!JFtp&th+;cd;+ix7eTQUmVB`EUwF}lQgk~!Nv8N^%9RS3@vWRY>;?jVdLVa z%qEE^7d9_$$!uBNn%TOzEwgQLduIFMC7DYW)0uQQbVo>asMM1omCCQ1-*GmQ*?}jW zstZrL^8NF}cycM8bgLdb>A{oB@MNd5j)X>foxRhg#l=!Ft@1O4Vxe3p747s)Nv98$ zrkBfw1v`D`(R=SnpVEbLUfVAKUZKg6a5Z{=t~@sqt0rf3saVbzRkdRwSDanW&F1ZD ztXNVEB0#;a=2DV$)P}d zZdZr#><&MVJJnsdH!Z%KU(F26L@;Gut?ns=Gbwd%rc+I3y3~D{ZgqdA=dGccuzHPp z;K^jBR~=DDpA2RC)Pw4^2>aDT>S2Tf>UAoEaNS!&(NJa(L-~{oBUUxa!I6ob zX5g%o5p3S2?^}`~KIt4jvXq}L%$!M==kn=tesPIIEIm_L$ftKdc=Yh-jp=-mLq?5^ zrFUa;HNt;Y1vMXj@G5h6;8eld^o}FfNA}{fcWi9z(TQqrEvqcQ9Es?481L1Nl2>lE<7953pmODs zcK-eqRGYb=-Vfvfx5CMMTJF<1oloaaFQK+*Y+)vyOJnX$&!LV6v;`uUWwfPG6u{Tl zdQ=rOa(t+OhK-Ic6pAP60I*k*OQVs8&J#TV?;z%uUoJ_C(sFrexonUY`{2Tz*B>aK zxjX&Rb&u@j$1d=)zNTdBCCel`U|QhL5Emv;mr_Gc9@( zpA}u`5nz7Pq}4e+yS#`I2MAqgI0joph+;4xcw{dwradE;^t~R!0B}y;zBq;Ya1zw& zyW1Y|I;a_*>7#+P(yw-UaTx=9Dxc0xPXmt^rZA1vvSu@ubV(i+XKOVdaRx?5^DMcp zi;q?T=#tK7%X&FK5~(KKSyzqcra5U%g|E2>10(JB_A9Ki1E@5Nr)r-RpRMIk?KGv& zzc zYWQj=F)q(12)pUIQUPGsn^1r0Zs&D}OB$0=7WbJ_sf^0zF~(*vREtQtKV2&3iJFG( zWh~D2v@R@_htr@0hNpCH`b55L57#y(CgV5XX@H9wNRQqk$!BMP05v!+Z1RHP%yQ| zsGL1FoZg*Z9A%8ib*6B7WN&&H7#ZC&m$&ow@IG^A5AT)s76FN1TP2qfr+aj?u9WAa z7$e9u(^;2SH7+-HHOgG{4%T?~f&3!yET(o@=h8s9<-#-u(5X4lRMJvRobstWCO;l5 z+NKi>8a&~1uPO=H-JTeIP*n}tJ-2xhYm)Z-qBG|bAVkL!yO+u*BmO?InG7* zaoUz_yQ>N>C1^3bjO)3+%uPQV~`834#>#0`uVayCW-<}yiPBr&*Qe|oBYB^iPOq?luaT2t7?cM3Z>>OTAmljSH6xPbo+;X{8e?N=$evD&EiZ_T*275K+ zEZ&Q?DD5I&GhNcVy$Q;9_uhlSI!wxjA)nlxJME6&dvZtf4-b#Xa48AB1B4!!yFw8y z;-j%?+a8vI&AU-kpwk_AkM%;PpsW{L@7F^6AoKLYU<_1#dV#bJX5Cntc=q(-!f4&Y z!_KDr77IXwSTq{bJA=}54PR7y@gQ55g>&YkW zqcLX##^pjOcLIwQ3Lf$m?o9+Czo}s0XlH zAZ80!lOECN^pQwSPvy`A!}B2T1kpy9yfDw~k#*HhBLA$xV4!euqcp$@1l z$|^0CW~&`?!!N2SiJIKHCGKZwQnBo5FjoE_;}(7q{Okc-%AvEN)$m%VY|Tez!y7_J zLeGaMN21l3tRmH(*?bw4L9S?XI@p>Vex~y_1>V(gtK^;pWTg1CA5m)e0VJ! zMVPf#!n|9JRPZFsH_=0(M>|)na;y@nSmk&nT(QntXCvXzV*~gWydl0yDga84BfF7~ zOrO991TjXR0HB&=JEZ3lCktp{Nmn~gkZgy+zfZH5VxXOeHfQ&lqofvW-f>Lu*0iP{=>Mn*<%CYu5ceJ;rS zL;+|~M3cnNhgMl&HIKnTLCe$DySf0c@M?4|v|>F3Ax;$kgiSGdRmk3W3J~P~>+l1t zVn`LKSe3{SpfwViJO|mt%;=36DoJnBLdp;=fveNEqg2cYm$T9%yp3uO@__>J`%;M< zN2!=qh3PVAlv|m=nptvFV%*yefY7f-k~RDU1cLy;*7Hd#SsOJ$05`!Qj!%6!6hbmi zFj7`5j1dcCq;~}{S&fvV7$=dl)>?Qqrf|i0iHwIH>!?`s7&{8_a$-J-Sadv82?GwX zNxh4e52y5N7$!iP*l5{EhX6qz!9#r~-$dt2g`(!5t;RK|;=)q3w*l#yp~fjw?aXG~ zoU&OLK>8u(B^ln!Sa7812l4Dv_}M+UM8ipf2)|S~8g@3hFQ=sfynK;V3#>O4To6q5Ab3AkSZwyDz`xqmb{mA-iGMg>t7W3I`HI>aSmeewe z&Q`m!*~gZ13+|f^;KZephD1R}kZER{%e&_x<$}N=>$9gq^JMz`*C1aO^0^|A>e51? zTpjdZaQV-gF3og%gCBHwemc|d-?|K$of-0YQxPVhI3tG0^l&jQ%;JG?Y?&>=d#vh4 zZZZun*+7zrR8R84Ng@M5A4ja(?c(t1{K7&uTL;tIn2z{G`iBG9{w^-bP}H)*Rs_Fr z)QX3#m#k>iiedys&m$g-#@zThD;Y&9dHw?{9!P_cXT5Aiq7j7rPTn()yO)tmJQ|5# z_{;hdz1*Ux&42RSx>A`7OL!Tz^wL==*7~#2my)kXt(cS5l}JXCiDbO5Ls~nHh6etK zQ*Xu3eme$Nz0guwnP@(miK$2?uA-1u$MVVfj*o;?{MiTuZV3u7pRpizOF`_`ndyd* zvkQ{y?o4mKZ?#|btc5cJ66-~5o$AXB=GUwKvtc!Wa2-P4uSYn9a09}P2sa_zT!>|c zklU8b23#T1gph8d+O94^xJhzMuZ3qI+*HF)hBKQf+{BwL3c^i!rkhiI)rdUL1c;W3J5LlM7T%YrS3+!mm*4pqv~EYiEvEn zai6*$dGDi$68}fk(PyHWD_sHQRjz>YYGnkJ*QiI-F?@NgdQ`n0;dLsjjw8HY<{|F{KgSqHI-0c&l1g zClTJJPN~xfU!~3{2jM~W230|LNUf+hBD`I_Nj;A6u=K^7*TVC6pf{dSXVIcN)syPS z@a``47WGzycdMt=+Yr85yS=`csvlSHLO7}3t=@z1KJ{MpK7{wH_p6^k z_!{*A^+ALWs1K>1M0iAfSbYTHQT2>^7U6^Hqv~S_U#nKt8p4Ov$JHkgKCGTopG5dN z^;7Co2s7%_>Uo5ZsL!aMMtDqpR{adZN7c`&pF{Y1^u{l#pI5(tx@R#yzJO=PF&@5% zFo!o^LO7*UR;&tKU=KKzKs^zWOG@1@#B&TL>4`x78maEUG_J-$7VXf2{rl;gb3<>Q50qrv6O* zIYO=eLRAsk>c6VLL|9gTrT!Y>vickKU4$pq_tf7aJf;3leIMaz^?#`UhVYE~d-V?p z9rc3xM}%)s|EKyVgcbGA>R%A9sDD-ehVYH*zpMX&@J;GP^*<3luKr#9FNAMa|Cjm? zgiomdtp}c!guVFnA^zhC`|%q<{9Opw;Wvo*yAiIJT%iz| zVW}JN+lb#L_ujnq?l!B$Y)I0r_tGKUG7EJA!mZE5GVejS4ZrQk{k;f@HPVQ`4xL!cqLj5dSd3efV98 z_(u?4h2PbPKZEcZ{H{g(S%lZ&cRk`CMR)^#HzNKqgg4>0AMsU$H{&;s_!`0k_)Q@G zafG+vcPrwbKzJK|uR{Dega`3Eg!m^B-j3g4#D5Cm9r)de_@@xwh2PzXe;VPd@w*4{ z=MmnE-z4InL3kg2_apw(2w#KW1BibX;Sv0fBK|W7AH?sqi2p3YhwytC@t;HZI{Y$- ze-7az_#H$1=Mg@N-|G?o1%z4rjwAkgggN}C5dQ+gY5Wx8zlbo8-wfhkL^zAz9OA!( zuz=q@;$K2|0>1^se;MH-enrH81z`!lCB(ms@G<-};$J~%<5x!fR}n7bcM|bmLwE|m z(}@2%!ZY|ei2nw{H{e%6{5KJ<;P*zvzl!ip_&tvJ*ATuLzb6p?Ere(BdlK>AM)+g+ zy#?{FBYZ1z$HdPf zUPZ`p@Hxc)D?;}DFChMxYV=5G_m{xlS9>T%I!cyZSkhbp>~AWKzdP~}jTWYBI%bG* zMC9c0f+ancl9WgCP|iVgbe!DxwGdWabzH<+a(`VGyx5u9g;M#rr=T{{ZOBa1Gx=P3 zS?85xBbmFLyqojbSo*Ge@4xSXqqj{S-M?Q_rPEYx92cfIdxcvNNLJAFyoD%auB0eE zg0R{BU@i}iur!PIP-6#K()5YF>EjebjDhrp2D*HF%uV_bwL9Prg)xVeXfIS_Cm^Ll zB`L<5qL8*|Lu^Z}0n}p!2z*i04g-jE`u5W~iiC}JUYDk*aDjpnIqmn7%SEB&Z5L|k^wbDyLXE#Efg)t2DHWASVUW)m zKewh#0Owi>X__3Q4Y2d3ZBUIY%XJ%}z{_J-1 zS0~N;|DyN*A9UUS%gwyNuyf(1{1HRFg8^lFw}&a*K?6-1RBkR70mjMeQw5+$qR0R` z38F-UC|iu7_O)u7_w9SIeI|_~;R4-qX<9U86rGB+ZKbd!K1Ic|8_xj6DjARablq~)DcDd!0=qTytIGczEh`8jh(t?tfXi6U3Jq< zH|-OfnPDc{Pm8Vt!#j5~9I=Pf4fhkNamxOY@z6Nc1gxHhCABnEN+Y<{dz+9!EdBfx7So`i}% z0sAp#UX2~R=e8q9oU6x;+B#i6vxE}4{O+5FL5`=)w)M1BZeo0&d4xKS($Hi7zGYkQ zvr+$i-3R+96r0bT-ghrTsMp5kZRgr?s*q@#abUP+J20G{gLcO>ysm62*8~td$0coj zz4&e-mD*{iP#IbSp)TEzygq%b_~@QWdQat8(dixAbL^pG4~^}qJTiLAqhoujQTD*O z@Gd8|3$(z^=fdMobk{-|kzpski)wI0C-7{Rkz3Ejc3pb?wKtDMoQ{()Eh_C>T)Ngt zndqtf)S~yeG&?&@@u~Mm*?SB>iWcpE03~NcsZT*_ykbZX}Rt|uEX-prE-6nTzATK7v5bi?{^@23uGWF{9vm zQ#r17z%$m^l@#rl=kzW3+{mIu!<7Oyu*v(nYhNj!V4tGk14z~o|7DV(U8F6tbK z7-)Q3?e=2E-Zcr0GxY?zn)F^&BhaK&2VIMztWo%81<<0>&?i}J@>EV2K_J4Ag|TY) z;bpQ@51FUhVVV?bRiyrWI$!OqQy^3$P!Wk@LeDW>mw9I_FZDh=(tCLs<>g9V#(24w zm+N`i!^;)CT*J%FxKz8`MI%f6s&C};8+h5z%S}wt;jb|IIzD7)WY!TnHAF4?5K)`! ztC)t0B7He7FftR?K_BByY@u`tFpHyku-1V!mEq;8(2NK>WWZHT!nlKUfnDwJEKQcG z(1C~vPS#kwWCpzZnh{DSRe<`?Rm(GO13gdWU@Bmqi^eunYuCXX~hR%M4`$QwWL}F=#bISq8OeRNjoVX%6IfBhnM@ zf({}Xj-N+p^+Bf+4MUS*#b1UNScr5s}cNYyi8`?~%z-;I2;k=-R(dKAUVWVcJvUCHL$Pu|l zk4|$v_WsyJU)@RdzgQDks}SXK zm0rWj%LePMZ18*(VT4*?6g@(+`0ZB^@4VOuMxzERvb5E?{ywCzv$c7 z<v5AE z@WS$x{xB*lgR;6_Olz`YT9frnYpMy)O2*Z#M_Cd!1o-B1)r84U)oBG?SeMJF+-bs^ znz4Zh$8Z-Q-V9qw86bN|0uih-a=06y5?+(#&uz|MW~d{{q+ zSH6~+uxf03XB{w~AOP5uu4q@-+1xO!>JqkZe;2;4wI6McI9JrSnTFj&O8aTQUe`vq zi8emhALHeDT)c`$U=iF{?=DjvliS-^arQ%3%-Pbi+9q97y*V|c-v$wZsYv*2So(|_ zeoO|`KkSU&4mlONOE@{$Uy@ycsU*6D4ApUV-f)HVY+(2QPu#6c^~7y}So@Ppcu7-;A)fn}O?y=;yepsS*Xh(EV&=7S=o;53h6}^*Wk)%n#15pC3{^s~ajEw0%*%Ps?}3 zb>)q!?<^?uM|)OMumMVK3N3wJ^;Z&%4Z*Uil7a!qr^}o0O=J`3cQvpjw9@H+mG-{U ze^=hTx<#!sc>pPNsliGozUx}us@AVz$PI=h-UkJ@<>&l0^h0iV)!3{qEiY9&eADrfUVSUS zhmAV;jo(Bx)5qS%c%W@38U_PP4x4I+-!!ldi?f*oF4C+BY+S36MSHdyF2Gt8c(kPT z?=z=+x=2Lr`~ zYY*aE&qp60v^Iy6k6Y)H5mJ$~{DJMvdCQ8v+=C~n^Ieh6;XbVV%xQq%pSKN3s6)B7V*_7U@wsHK9gTt%L-fM#K_3K2$>NS92x+{bVqGxtsk zPppcy8d32zpuCkB5aTEiBaA!GfMZ<2eo`XZ`Pgb4SD5F`cc=sqQF2oV)4Zb+|48WB zDDG1RnRz)q1lmtfXZ(%vBSfJH1$9RB5|QMSAt28bHY9>xS?#1X4+Rq|32aW}yM(zz znl7a2TkQri6q{SrQ3O1ye^baltp;SF`IzLj&g2C{%47vbgvh;r7Hz%(_inlmRFbQ4 zphO^0*8W+8wpqqHwH{?)X<_baNOJu$a_vzYu)ttpTMp?j15&+e17OsF9EPw^b!7XH zreAFYLKoQ14^(1mliK_=X|OGm&gNzj=G9kTdF4L)@@Er zuKx@V^nJKE8(riDwFpGGM_zk}L15`&nG)w>!<0qqFCb}v@$kq;@>@2^5D_!P4e7WR z3JMuwVnhk7RYAfkG}pm-q2Gwde}|#=B6A%KIgL6hSbCwWFIT34VeM%$2KvHSH|3m|1uK0Vi}l0(sW)|@u*eBzt5RWOU@)jA(*4! zb1+X|a;%%vV5QA2i)u{vPgG-a@5Ie+3PIAqcME01o+G1>eiJYE;{qFa>-MA70iBz6rnrz0rp4K69D4_V*Q%-e*?|VRKEphS@awQ=3@8jp>nnUZiwoEjEDagP zqSyeUs)^fy2qC97G~RppB3Uk(QbtmOLiM-!)L=>Moy=AH8nIs{jy}p3ZRCD(R{s%_ z!{DyAX~Ncj!$%!VBn*E8K&zc~UHwf0b{y%g4lv5+`yzc|3kb3gXmJ3s{>muzsDh752x17{xYQcuXLRDCop+z&87`20C#V=rAtGFa~5e1aulB@&KJF2yqoi zkhG49RpLV-7x4j+zA*;GC!tF-hUZhOoxbfn=tSCjS1dhU?q2PYTK1AN#!wH<_kp(U zXIilbk2^O$V0c{N55U&>JJGlwOhlVdxcEDENeZNobG<)4DJVlmC+HhP^fad5pLV*( zM@L7~JGrNKbRsn}P{m%1(t;7<5mo3dypU?pM|t@gFaA2O|ADu^&CAzusjia}U@urF z*b-@1wL4&!3!`D~VJs9ygB1{L3f@~oX0Ua>l^L%v4iT=vo%q>9WR0v<7}T#=Ag$vth)+~v+&KagKLzqSi4~*+D_W9iK-zaz z5@3X|K^~o-!WS4MSdZmi-iT0y8woZrhwUp}AmSk&SqtllN+;IkE)`SpAG5HcljI)7 z+r%2ol`CD96xgm;S5i#lzU$NvRytJzt5*WUEIA%h$+v}|5($@6^PNy&%!tZ>-WrmX zl&r$3N=lbh=PGgo+mcWgzCn$_*e%~3dV+EXI2Mq)cY_hYN{zP2Jxi=~>(5oXO?j$| ztb*z>bwx|Ifz628Yi{X1s6j7lF@r4v`uR#6Yjtm>2g(Gt>b;eSxx;!MdF;LAK9mE9 zVuJTptl98NU!@m0-snMB#h1hOZ?k^Ly`$WZ9RE)B(IT+YA+74K^dbL#(+8Mr1Jc5N zPyoUjNts`6OjBN0=^$fB=E+SF)&E-!tPB*L$^TUFyZ#NO0@PxE7nmqymr$Oye)61rRS;F6+zrkbjaDQqp4-OIAsiW`hY^DV+yGsrjs z^h>;8N{2MIK7mEV_flj|GMChLCWf7Xh0_LNFY^QTH#R+Sa-c&~?DXS!l$1>qq%SB$ zO#`2k+5oHdcr@Gtr9c-b3&il&#JcddD;~wO_{)9K9!MYKdoTTMy|FHJz!7jav} z3~es^9NzO`ZhgcrI)ie2Cop=RC1rUOg*G`ewJ_CPBW;39Q90@_dh}C@)ICm=SL0IA$B>HdnG4>G% zr_4%lT!QRzxJD2mKP>|>)gd`9h#+eWf@76GO_Bd`ic)-A&ooS1Dd-Z%C$KW&OXvV# zyP1bx(R>g4N?Hs-@+_IuecOZ)IRV%eFK)#}Po`00RgI{QC$hoeOK!Xa^KmvjsbD0PlRDu$q03#?dHo%M|K}iE($r{Rj*c(SZF^k9rW63%{U^zQ3TI;|RBy+=` zjG|RUh*ajoOEHB>#)$}#IVT(#88~>du!ycN$5rHP7&MPHpMYpQG7mxX3Zy@fg+xIu zUIW7w=FtVJDOM3FkfFu4gjT!B3RR*d= z6SfKbRJr8mWmu)!2hhXt#_U6^tNv|Mc4+~06c|=W{&?nI=g|@~qZ$w6OkD*W=Hbu{2zgxSnt5*@tP2 zvAOYD6o8oD_BzOU&U5@KxCKowqhDc#&3dzEP2ZIut@msL)9L$li4(j8(rv$#?3rv| zZl`H!LTUA0G#c^}NNMvz4Nv9ga`Z8!{mLxnV74vRg|OU#egHO|Idzhj9k4tULy$U( zmb@OY2?I(>7V^#(u)aW&u>BULfmpbhF#vVv=aEhbz{!#IhUNXA{4&0*VS+qWUbs3vnZHU`*mZ(x;R zyF}FltZQ)L*KmhWfZ_sKa2e4r@Eag4vUC!6_C`=A{Wt9*7WiE6MXj5yzJve zaJSLHiz08|ecGm~Mm#9> z`Bf!x2wDaZ8?h$g32GlRm;lUb)oWF=buL8ei+i^RKy;mWn5k{y8EcWesdgS9^^IsA z!Ij8O!%O6uMI&gxi2!O>jUS zrtlB4@ChV#wlz%BV7jK#eY%uP9|w^cJ}UBbgpMfY#UsJIsOce9fn>u@gQxLQ_%jex$4j+~1D8ECZ(5UA~X=GA4-_Hzsh7x<-b{O}0K=VA) zd;;|qgtR^ET+%R{8q>Cgu?%Ox@>~aoGwU>wYCoF$y;17d`ltK>E%se4X0)Gl#9C&@ z{_W%Mmw`88oeS?i7anmJd^3mBND!zhyTc#*N4^Z)pd1G;X00v^P9yZ1J_X(&yXoT0m zx6;*=eQmEm)oVft@R;40 z)Ku^o4Y3hO82*`SPGk~>j$)naM8=mUKuuBFpuu>%Lb8Nwv8r$9qYE!eT`p85zh7c6 zkXEAv2`f^gSy+AArsntfFC;A_oA}0W4w@SG@E5%WMcFZ; zmq5d6bq_XCzn(3-lb2R~)$KuFTJ;sSiW7!XG04oCslh<}f4Kx76c;><>h%;-T&L9Tj=lGPgy&gG|1$QJ9I=Sh;XWw4#t_%;m|P&RxN z!EM8PqHFfPaAxfAQFsdPKO!6I?m>FV2Fmx_Q4wx0SU6z>=^c|0lO3je;Ccb0I2dcf z)?g8*Pq-%bV$}a_z(&N2DHsDmS{?0qiGrb~E^GQQ04QWq!`P>BLnBLyT46Goq@)n) zY45&IK?Ute;UI~Nh}iZL02XM)zNGGL9B&iyc1+$T?J>Sp@I3{4ACvnH%pFrGMX3{| zJ)j0%5DLL@RMf+Vx#vJO&)FlLH8CITALv)pczf!Falh>DfV56T|3}acy_3N1^-aJ` zT6hB#|Dq<{WlSe1d#N23>nYfDF+~@nRC;`uKo?fm0{sXYasYyTTDA{}R4!^kNf1t1 zO+;ESmp~5?vw2h6p27|EyEHPOajQo^bMOM%X6=L%JiIZ|I>h-dq<2&z_6|c?Kr71C zig}0|v>B@a{V~-A-r73?dLwRjYv}Kx#EiAP07U;mf}=)He1Nwn37FQDMGszO21@7! zZ^MV1C6QAzp-~5TB0igloN{p^AfVU)>XFvuM%||Y&~fm3_{JW_4M9OQ?lCkz%O63A z9eY7$F+RR;8GEK6rmayM(spTaZMkc;jQB{ZHjG|kYuJkeT&~+8s#^M{CU}VIMGh>} z1YBJboi_M&lp3^oa`~u5Aso40^Q{^-Na!)Oy7$S+Au$EvZh*kfEL8A zA7+UcO%qPfI8>|ByEXW`Ax?gf-UVS6l?P}>;!#8<#GaWXdz zuyb~cp9FaG#BN!l3T(}#dDem9>4LlMS)O8}*LW^%%;;t3eXLGE_LUiG#3m0-M^%ln1|P z>ME*F4&wLXjkuTrRZj(y`2b+Bm(>O2=K3_G9)yC3O`d~TghmSsQi3kuLe^n;w zw$pw-)<7IqJBkpAi7~T&Ge=0PDFk#avMaB_{b=xuq^C$4LQQ(U4_2*BTC#?Z0&PYH zHM=beH>uK)T>>H94XvpxU@-KsiaqXLf-QIoTrtnZ4yv_>yvn~N5P|CK-jdYq4R2aUxxY_%&@zmHf=v?s*Z;wv?Gwjj$Upq zG8i%?(;IFKKz&^pNxD*uTKdabHNlguWf--TO*O)oX8zS!U=K-AzUnQ*lx|>#v9@qw zU+eR#C*6e#W3lBF^5h-0I$VJ=MTRUEkB!Ty2TbBR0Y+1mJ(MAKZ3Z2fiUN~TH;9Si zEu>!cA!`Jv%ga+(NPmLkk@9mPr)Z5!udrf6@D)C7g$KN4$!sYdLjznP7mNy8b7k)C z(?I39@Y1g6Ab$3*;9{6~%CI3~5yd7r-fqEanAadx#aR7h$i5WhD3*))I8>cGX@u^- z<2~j&-cs!ug1rF@)D3S{PMM>J@UD}FU#>+c;*V~m^^xj?DV&A4^hg$5@XK zg`6wfOjEZLYkR%D&-F*q9vEGf7Mz5X4eQXz*i}16!uqdJxYISh&ubS*vTj4-zm+iH zkj#K3kR8W{OebMq?G#Gfn1a?OjVL3y;d0Ro#z7*3IzbpdE0uE#S*e3msu78L9J*WL zHEcII1d{aBUx^*i`5ta!jSK>jQpZJwPYMfG(+cg)I8%EkKDzss1EV7WYh(7BFP%-} z2IE2GH53n$M_mh@bqxc_pFR-=N4oQN>@ZrwQ6r^ga3gZWgK>`n5}cOXW|Jy_y2CTS zg|`4}G>rwOwxozEjL@wnkDMqhkqHf~FdxUOM&S69Rf;*}jfu^Xc>BpJNduFWtB2QQ zvF$KT#+8e-nX>ibXraP5@E4cJC0_)EdxVsm`qikUh*-8Z3(ej2(oNY^M|RCYLV-FJ zplSUi2V`4v*QaRQ{3h|eS=Aa%fBj)$8q`#<2ORw=8NQQ-3>^RsVa_HaFPy_!4HsL@ zdc6j^$zOvSxk5!DC>!h5ki4m00f6YwTo4+4ek0w&AN0Y|xRN%eY%14VmR_XMI0s8@ zn7BAI3U!-6Wx9M=zls$jdc5$0gL+MuA4aWYcnpTyE;o{}sZt!p2RSbr+Enz<2YD-(Lx@$^d!yU~g@|-d6CPv;yRZRl(89`pSp&h^^0NR`>RDWSFY>B` z3inl!M)P~ry^ng(;TaQt?+V!_08KxQ#B<9YBmbCsV&=llQ zlP%xlHpQKAA$=Jo%@m0EPX=*^Cn7#OhHx0f)@BKPk(rQv} zY26Rfo~OMoq|Ou5^NNO+T;S8Drg#(8vog|OW{rsd+Dm?2SE( zvqqv4#_>xQ{$5?p%;2iq3?i z5In=-P!!r!&|=)h>r>zjeF;Ed3z&4&X-!g-V2Q1*`Oi75n#pPiT$p?4!EHVv{0Lb4-(i(C?UUR&qHpy4@!ooLZ)JxZM)wzfCh|GQ|>Kwi*KKv0AN zd}W!@;e3N-%JjX(FH=hAXckL`&!S*6Ux(XZuKLo5aJ@gqIZ&8iooWs}4`jxO3(Jn&;lVT#F3EHZ>*7?BTH(4uDdf z3{a{xHmSuYfhk$Po)`e$;RCSM!Z28y3$;po-iPR=Z6R7q9Vj1P))sRz3z#UNP1eFo zJ=_)}R5K<8@3DE5n30-K7@c9eF7P0y&a*z~tFG9_ zEA5NyCJr4qErDts1HBQ)_#Gv+3&4nd#4ctLHWwN|L8w>^JFEhrr z6F58^+Y{hzShh;YuD5g6_&(Vb>R1!07tZ6)>BZW+TP#3Mmq*eE(j!|mE%kH)eQR(6 zTp3jd=@8Q06XT!TXN)ADVCoxqkr62 zk5OAgJ+_{cUb?2D@m-B{g!syV>1TfN0xClfPF{|G%92}(u3RkZB@7fzio-_--^UHT zAQZUY4agI=y0QTk>LIu|Q(^3ojJgD)yu*7CjJU#yoW9IYAt=<`!L4(2C4#;BF{pcx zG75_u6~7^5g|cw%EM9+ZBRvAwX7speDf&l%G6_iJAw0)qcAvu`oA>X#_?k)Z z3hkqLM7@WrZ*kS9WL>dsJmpzliIhbY2Qh5w)PhgSp&$=dVWAD%*xHRjiq9=c+G58}$Y1YO;#?aE&o?Cbsw4HU~R_`L-ROJch`cSWV! z$zd8k55TI4-Xh+>h%CJ#VM;^J=TI?&KiY^<8qx=9Ld5AaE}z4VnCJ=hC5}oWWlT@; zcDNU&|50v+g=7H~g}%}0EJv{YI$~C26+H_-Kkhc|=$R`#i&Ibvy{BA{Kj_go&;dNw za?>nR6vJ@o62X3W*Lx*s1@`@&@(eVIto?9BMub50(W2i|rr(`zF`FFaUgTnV^o4Hr zDV65VI-F=vi%R#^e)#UW*(hj@rKOxtUSpC+Qt(%vFMD2<|A6`YH7_LGWFw=Fa?rFG zO`sfaWukBKBIrOyYyW{5N+34a#wz4bUuv>H_%2Kh?zKvM`rWN!$7SD@7BEm#4d(gyAmBI&ZBhh#*y7Ea3=*oxf?3`_!f8$m|ugDV#J z%?k}Yrf-57hk$em^5RI=>2Qs6cG`mW^>>lNNu*sj zg(q+aWFjnogSMs>ao}!fGWm~rJ;WW-M9>?FhFfoIGGAPzcRq8$Y2fWUGFe^k_e`Vg z)khyV+oO5z;j>0!F(7Ql@D_#b^U*qsdExp5JgtU}2Nbw($m^R}uYW;9+5tjR1pvV+ zdG-+Y3~tPPqgyz{T(KJWb3!j?eBK*dR#!YMbOQb0dm`01Bu0jr5nDCL1>p2eR6h{3 zl3qDrW-#=3?0$1x#e=N!(D)pDx){T095#pM7zrx3y^6iC@$r?cv#*z_%~hvP*>^2- zy%HCUtXmlul7OVCDXU>Q@;g>a90xeWvX%5D&#oTCLT@&gHHq21u5N}YC!mk%9>5J@ z%9G}4WKPb&w~^j}H!=DoGJ_#M^LTmI`3)CcGfm)`{RVyn|W!NnB=nR*Z54Q z2%lZUxd!06jJ{XOVM4cuz=;l!{{n6mo8i`MzxP#OxN_C^hO0iyra;wlA41Q@@hz-# ztBK+QB3~Y! zc*L^-jv0|v1fXl^%)ks`b|&|RPIS${J#f^9%0uien z*xrgP0U~O|!I20b!nnv%1zeFyr+vF&H7>T#+-~|x%*UH+_IkF99W6U$+nA6ye->yE zQGmY&li2abiLl;bZt+BufG7=`UF8^|k`awGGM6&6QLeZ&hCOUNF$a9LbkM&OT3=mt z(t*BrQw&eQKdRUD38N``1nKL#evP-BMEaBH^ZLoGQye4>{qNd)xyJ(K)ilAwSq!`g z2?|fPiASR6nx>H<+-sk)*4`iEDEk!?@1FISpW6Z|(b`VQMazE5K)0}5_N+AVJV*RE z?lfd;t&xVix|)-LN-XmNtE)*BD34`%=t{QXnQ`5`x(d>WVD02Sk;b((>du1N+DZ|g zx6b-sxGO6VqO7dfuw}BcZo?6S{?ck{2~oMXtU|pgQZ-?%Tdk;jnGtgf;0sw%rHqF0 z;;pErAPo?h4W&R4#=KdkRU5*o1q^#pvX63~Lr;<2f@3;E&T`K!=#nxGOE7uJfUUrh z{7MYclsJ$sWnDYCMU>9uLGD7{L2870Elj>dC877i$!wfLR5-i?ERp^i)lnq%6N8iX zFbLxmoUX$mZY8NYp^dp+bs{~4tHmOobm7V8<&+Q6hplv!6O|6teb#zc7f!rLttQde zo!AkKVHd^eeUQ5(uL{}I4c?nC$8O<{a%#rHdD@{B>~L^4p?tb$g{Eh|XTDeAtPAMc zdMjP7EBij<%HBQuqw9@b#mnKq9--^Uxo^IIb%1Ah0DneRKWh0LTD=Y;-_A;6EwU0T z_VN_K3N%QoL#Sgn+|Tn&kad-AmH=9111OJ;K89E`yoswJp$@m<&Bh8&IpO&n@I)D> zu1amjQ}i|JwM9-i+{zO?o`u+3ZIc*|qC!h65ENyGnuDf%8?aL0mP#-*BY&+yCOh)U;-KE-F2o^l2Q zKCz9_T(Tw7 zjhAP5c{eY&^KzD#f8gZ^FTc&p*LnFjT&i)?XqzTgVfqiq>ZO;?<;^wGD4TAK%m3UkbO;6NZJa_x{2uTpjSK zY40oBST2ibhysuRl}c~gjZ~^TTcm#9;A|O0#&m6!#5~~qfVtfH=u2=I*jm6W9|n3B znbb)53T`}`oXZ<`D$Yle9=eT;qhkzGW%Xq?t ziV3`kf;>qMR z@emwBop<)NHd>M{Y2_o=xirvpZxjws?A~dQc#S?6-s_4v^rajxg8KdORL2g9nu+r$ zK;9DAJVnb4V!NRkRS#WB9sh*w*@_&@erS$5{>vGjz^6PnDf&_qN^u#L=7EQjeY4cS zmaR;DArHRhVmsDclxEU?4|UVew?}CvRbb$=e2x<7G(l;vOg3t=`aTQ15K3!PqAxI` z4U9odxcUM}PpbmOC$`7hoMuFNLWKE~1Zn|ceTeeq2DEvKpm$k!LSy)lA2DaY%!?ZsV9KEeS%;=wdC^n)iZ`iad&0hdNMU;sxA%upL zVuqt)t$2~Wj;^+e>5X;czxt!6weF*q@<(d9r~9a7_dophw^1_Hk~Wp>L&5W$X)P2k zLIt=o4!Y?O8`pnl@j?h}Z@^7Ps^KSWDm*Z8T-$<$!i6?!c(M&Y&;Rh--UxKR@7-z! zN+(U=Pa^ULhIbO56&ASKZ9MM9vtQ?m#OXze18v)BjkqRj7AKSU#`ReN;iczd6Z~)t z++qY&1e`IIanKrErrbCZdmV}-ohIM6ZA2|{fAxVWCoJw2cdJ1x7$77 zW)>J=P3r=NH(gE8qWS_xcb>Jso8=(Jsm-j~?{9BcxIelnP{mlm0>BZ&anAAUEfJLZ zP<1JyR*Rw&zJaoAN+?wy_Z;(n!j{ z1yvi%^1wI3aAgwoC%U|lgK;3Xeqbt9qcqBunaYFMN^mlO2Zd><=?72%&ep(Y*VFp1 zm^99$iwk-JRS$rKB0&C#VC~o9t>-fi#!uE$FixYjY2piqHD6Ep_H8hy&+w z)|1#|_TlLu-@t&}t%*Kat3@#mkt2n3UC%~VqIKmjqWo@@|F5bCU$4i2e;>jjl)fI} z280_C!cBR3Q+YFEXj7~hDQ}tIx)OuSLKuUA1;G)&JYcQ}^;~&dc{_xV5OS}?A%wgU z$MVKi-z)@|D+zpm$!Z!`X;TGGj4FwbhaU*xe5!E4^#dn$lU^XqkaoxXuo}PtD^<15 zvuQ=Y#mn0vM*Myyf*M9#5hl*wEXHbQaN^rbdHx7@2qqZ7*^|XDp?XDw|>08 zOlq?eBF$ulaFz5tHB${4MX99Og*JA$X8HVbxA_uhW+nkqoQg?tC#Mh0pDxGZvT0HV zRmx!&Eq@nEKJp zg?0SAGuo15;k;_aOzB-{oxX(^PC)0j$x`}Wq`f(4SqU1nzBkh?+Uew=HL-Ca1?JkyDjnU@xF zXBM&2Y3d_nrLK0eH0(9VVkbhKX!3WEpxWcTGn*v!cTwMJ4+JALjm`4q;zDMf>_I4& z<+Nn?q5g5^e>X4PymaD{NukbHn~ya6yiqPnW?pY%5gkm0=3!fb5HP+%C(}i@EC=0# zV(Jgx%p~DRQUH%5h{Y9j#^fSfrQi~xcoN4o!#fB?ma-4I8bJYdLQ5H*LW{V36DzTg z1N3oxLX%0@QSr#CFeHmFC8H@h;?PKCxQ!8Kn^HRYaw;ZUTFE_23d%Goxq$~aq~ICE zlvHv94`rD+suNO75;0LoDdX1Q_e0jcXZa^@|*wAcjG*dkeWJCV@Tf=Gbp#&*1WE%-3|DgDQyWI1VRm zWE>3FQcK&^Zm%Yqhj4jiQ|R5YY>!{7Ww^rjPvYCA9l$QnQcK!YHZd!qAkGegWS!WV ziOGz&bxDL_uv+An8}RcCjB0?g`pi%f-dbJz;o2#4cFRV1Llv8`pFr(})}g~y7*)0z zFi6={d6a4dCD#&I2G)?`5Q>Uh@V1hg52Ep|)y_F(e(?x(R%6 zGsjxEySCfve7qw%>N9`VhhQUb=+6K8#7#Bvz~_sHe-nUlI?Xp`SB1zv+On;#4+pmp zik?;p9nz;}sIm+kEgN)xzD-?gG{v$^J8b4H^e#01PJak5sxR zb_f*zIluTe0*65Art*m(W&NEp7%tOQ(zCf@!I9&l+PnDj&_!M1&$A|?$Y>moE+FdC zHq`?QmZ?Xc7)!{48OB=Sdmla2W%xxFE-u{~d%+tAb%~ow_tAqZ0oO-ZwlGg^F@h@s z$5up;_PM3G-(?LhAOiOjHkI!6fqf5v;9_y1YYlxsx&Xhpc=F!>B`9bHqdc`QtH=4E zhhcu@(ZfRbVFftOmWUGcVdM@CUjxywf$vdu7+m<1N^j&t(e<lz9Ca#&| zAlM1+`2tb#QWI(I_J{vn6F5AY&3-Mx5r#b(8U;@>##4|id7kba&mx}ppdxqP@lJ#j zCN-{<)x-Y+cH<}Ntid7Cr0uZNGw#{&7GDTFZ6To`bYL;`!Sc?eJ)0N;lS zwm*K&T{7zAci$n1L@p=R++7xqW@=Q|n7LB-Q4@Up;WAA47}=(DyNTlpT>)LU7zwAb zuV}lQ)>~NWO02S)ETt=qUA2vq+3UZWSTayUE^6L%vT3G7Ni6!1`V#m8TBDSCe{Enx ztThNbIIGC*+w5Cz^WKFv7=IAla!v9$VSEL-&%>)7rhRVu{pL9x&bY?F(fJfaQ?LP` zyj0&2>{U^DQd*6ZVp1Fh*apvYxjT)$)hs^|g4&-OdLwhF%^V>`MO4yc5xl^!1*6L4 z5N@j-rc-t9)L#>{w6vf#KlyOl4Vk^v;JY_AEMfj<0SL2aNOv%Q`=4+jtvw5oBHf6s z&@h@doL2%iIBpow<8~#C5?EpE<{dWJV{a>F)NUXQ`eDKo9BD7%o*@k!B%ys>RwHq$eAFMSu&Q_}_XL^10zA}iIiiFzpLz4S3ZWv`?p zDof#ACv;+Y)hD{JF6_944JW>XWnpluy`Z!KSC_TP>r+~w&EODAvF~@_&Z4kTF6}>x zebqP<9cOMXn3;af1D?s6otA@7aTaMlJ#4-m#$l}zFR0rEH zOI7nNZv<`JgfP-$4D3F^4`d(i&oK63Uc?$tFsh6!3q;drWz2uQiE4O z0C`(;yv$N8REVEO?YoPty@XAr`j|S6;!U>!D+Jg|?x@N}+zy0_%CP6gFs;cxpURH8?S z_`)NfD$K<7@{}%2U&K7b6&{(igRH^@ghwV-QzZh;zQ}C<%w2}9AU?YVdr{jUNwWKVhvzg-k~f=lsSly$;W6!@&-HsiXiY|X=$kls%I z3s&vqT;kw;uu}?HFHubSsbEN=chgh1Y+sGzESu0gj$EXjAb6snWWwolar!7ADvloY z)$F)0;evN&WvspPi4x;7*FB!G#=1JdKt|av?1!M!naW}v#CKTNL!X*m;R&(V}NC;C5!E29lS_n38 zEp4hx+P162*Q%=mL;4F~Hcz5dm+Ns>prvTo2Y_GMKn*w(eV<={i5m`ypcSJp8LHX! zL6StXcgm8^(nFWTV1tVtz?hv0NGA3`Rs?%m$`Lu6RbmBBo3T?d0vp`km3Sov_BB21*91{CA`k<$U2mI886vq8n#XmaqrvFVS@d~}q! zV-GG)$6i1f#$6@5glg1Ed zYZaG(tU!>Jpt20xJHwi+A%<<)xAMWaaLIJB&Oq>RLwdSwV8R_X`f{YsB;1$MfJT%z z=%OxZO4jXxX-;Tj18(x8hcil7U{V94nrMWw7CP92c?~2iDN4P$MG)H!t@Ejuo9sYa z=8tOme~fzw(s($YBp}*qOV@jIC{X1Uf66tgzFQ^_%sMhL9?fiP+(3qlu`HhYjT{&9 zWsx@;S)=D0k*76^)X^Q&80nBiUM}XGn2X{(iTlQ}a|`L}JmiVwFOFGN<0f5SdB)m~ z*68}Xy!5fVe-1Gx<-1BUF7h-CFga4hv}=tJdyXH>@={yni1nMLYj-i%hPBV#ASZ@z zkF)=2bF>kCJcJ)Mijv7|v|TcNE1v`a8tBrWU_A|OEGgmHvz{Yrt8wwRP{~JcWA}a- zIknp+)w&WsW%B?UL&-c$Yj=p(ONPLiybs`5^l43Zf;aHtZ{)&USlxSnQxPTZCkRV% z%<@ilg6L6pp|olouI*>@Wg|2BAc4>%J`#mWD{j?gPD~C@vp4#XB~9Jns}~z{H)ESF z?BiQAE9R@F4&f-5KL01yQ&f&^wIm*oVzT-Gfe)MC=EHm4xz(mbd}c~4u=UntCRV01 zvi1y$HwKyN!z}a!3vDy%n*5ptMx7@$qw{d4ypZ6`A8AbZEX$R(yAirxV_O#NuiBLM za-{iZ423*h9!C%G05lfx)a1{6Jgv!?;?!oCgHa@;6W`?1f${b$>^*98APZSuT+Hb+ zW+5za9E$x5mTyXQM1;cxg4(Tst@LPK&E(yX)3&Yq$@ayn)wWZe#7n^i5;T z$D)T(E?YpKk!JVB(-GatIV3HNzzhs}7+_2K@8j-c|Eyd0-rtcilJw7~^qbB@QryPl zq(Po$gi{e*Z`EjyJ5DT_ zqvk9OT*Fy$W^QaHEpt5NGwu4oo9|+W^b4#HXDdx#+s$!vCMS#b{uoF8X2!h&YeRpI zOIBY*p~kwUjr675x3-6{dVeGn@&( z!g4P-!R3(72MQdUAw)a*fE*jVu<5#&AH$S3*)#p@~Gd zGEN#+yz*uebMU~++EA}t?SN!Z!}>ipi<1WzN_L*nM#5#l6%k~GFA&rAUq|EYG;-j4 zHcqIheIeyaT4p=LNb-ELS=-;7S6~2gR{Au>ooJ?_9E6z8lbBp#@E5M+dqij8`Q^j2 z1UDMd+t9o?Xb1iqG3i|zqXXQT_Vc3-`Ie^qQeJ+=NBxv3q&(V`veQp_r=JqKXI=18 z3UAis@9gYG>DTxvyO8oNUP@^VPWVv0UY^ijTjg%PKMQI(+fy9!zwCv6`(1a3p1^bL z)P$`DoCo-4gSg%wu}uh?@0!oH{z)w&3tzkgAJ(O%!nEP`3=u_9hAe%~72w}oSCGC~ zD~+9!BLDL}N+5$_IX;9V6Ks~#?Ma$ss5pH&wOA?^DEV`Xc>{+s78e|M%cm2msx^0& zc*fx>Gj|nMnSlmd32wSXJ?rEv!m*Jo&vauVWxZ)*Yl@~asoVTQg@mt@Rn^2)pFm3S zx)q?^KhCFXytJX+d6dd`IQB{1@z|a?xH9hSH16Yx(ycdNA)?>$jGu9`C6CxVg+hG7n?e#X}RQvTvX-)0xi#` zyP+m8u_m%?Hrl^>#L-2n;zQ+ATpwT^A%;nxqY}M#KP$TBZ^bLxB+?A`HT2!gP|2yEE(U*+>wHU=Vy159Q$ltU@S^Mu_+b z`hk)v%ko`i`N7gD{h;V4%aZb03W)#T>7L2X?u0O1_t&@YJ$)bDJ>948<23*5lOCCl z(!l?W!B(lgiuo#9c03Sz<)d(lF9~v3pd$TlM)pCRx?Hk_+muJYKb4*qOX@BI6<%U#K(|jNa><`IG0|(VAQ~ z(!^b(qMWKDGV83>v@(XIgk*1HOy;YmX}vSC1(oLBWH-uJF~p?P{hFn zKA}B5gTb@&h};Nr+M(^q{DFHCvG0LffsH;qg6}A>k!FwJ`xST|*bG{G_}YKU8kW{k zfMF;Jx5lFac_y4)%imU<%BD1K>t*5Znwt3~mE= zf_uQd;6Cs<@Gy7`e2J1ij_(LK3cd!O0LQ>n;G5uE;5c|1dVcKLkGl zKL$SqKL@`6TfuhlYw#QJTkstCBlr{eGx!VmD|jCK9sC3Q3;Y}W2mBYj0A2(yf&YO; zoasT}+c^gXPy``Z42HoHum+5R2&@I`!0W&`I2&vL=YR@$JvbM<0bB^)3@!q10o#C0 zqP!H}JHfla<>1}mO7I?VHMj;;!L{Ih;5u+Um;k##4eSQonOq&jU@zDQ_Je8A05jkN z00S7V1!lnka3eSfJ_K$Cw}3<7R&X2mC^!u60G|M#1fK$TfxE#y;9l@)@ELGFcmO;I zJ_|l?KF-@0@I3?`244h^g2%y^!4dEk@KtaWJOQ2r$H3PC_o_Kstlg$B=HlNk9G6Re zsT_j=f6#xEuMP(65UP8@SN8)0JBRsfnOQef*F(DaFAnC3lRd2~f=l(!~!~hJKhE9^%VYB{kLuFN8t3-C}c!K`L)+{ONXQ-?BmqlJ>)49jCm> zb|iAjqqBcU-j{SKESlUIVo`hIh%a`1UN{ntYOAxCt(SUsetClR{B$u4Y?4bJ65@fX zTF$C!HmurQ(Zd5(8SJg+w6>;st!0k4Uevk}7c}moet6$-i3RYve}dBDuA4WA%~-bq%>`U6-{{ zp%m$NMQt*Pqg_0`lgbWpTXVKi-xW>n(G$IKPGW;R)MJ>mA}QU|(PR=~bX1?c)EMS^ zrDTb0mp>XyWyhlFSPEZMo3j&E0BRbSBBepr-uJQADt1w8U#%fY%q~pDmQ;6|$p#BY zfv|)&Fygxwb)%y_&8ey82le62-3NOmvoh`6r=n(Bj=sl{G$Va$@rL&&+R-UPOV~bw zW67($jd~=tV6w5NS+SCE)9e25>yV}D*zMZtG>ckOP*YL;G@7=WDEHK6r&_6^GKOwL zO0r5cdZiWNG9B10lq+_X9@(DUJ?(?rBA4~=)dvq-`?T3slx1jF(bu%pTBEW1vWcmd zk91oz3eqtz$=Md4Zs*j#F?TzUyewxG9#JJ*nw6nm_neHHTtIub_Ag5H%kNlVF@(BX z@7*fuPvP8Z`7*N}?yPR8McLi)774BIsCa<}zL#FU>HLLI$8ZPg}8Cit74r=p}UGiNT$vMY7+ z%(_>v`xw`8zs!av_crvkL(A@bvb$4~H?3Zn-5j|c<7drNwB0vI|J#5==#GP@fvK{l zPnfQ0s+j3=rlOj5YWnOkj*F>^rX`v#Vj6=zhfOy$wa}jM_aSVWqbYQz%bD_Kx}52x zrcao?M6cI!hYfiBo?}Dj6)Y z`|kMq^q{QZC_KYeS5Yq2LNlq%$j(K(0H-E*JH@B(7;Zh)x%L3h!guJ zU3L8_q$)NgCUNv0R!6$R_UetPmBi66H7CZ#l2kC3VTNDKBu#1uW|*Qa0kmJaW#A(K zjjCFHN8E@tf}cm!RhsD0(%U3wsNbn;2XB=jo7t(Dc8`H%li)AKOeqUvL0HOCv{q@0 TC0bPW2M(2&4IJvfteE~kpL~H1 diff --git a/venv/Lib/site-packages/docutils/writers/__pycache__/docutils_xml.cpython-310.pyc b/venv/Lib/site-packages/docutils/writers/__pycache__/docutils_xml.cpython-310.pyc deleted file mode 100644 index 4122dfe58c354450b81c775a77eb7c07c5c1a6f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5547 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 diff --git a/venv/Lib/site-packages/docutils/writers/__pycache__/pseudoxml.cpython-310.pyc b/venv/Lib/site-packages/docutils/writers/__pycache__/pseudoxml.cpython-310.pyc deleted file mode 100644 index 18efc1c98456c6b31e31c9d3e251c323703535b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1183 zcmY*YO>fgc5Z$#M$8nQ3T)0$7R*R4w7{Dk()CsrkdLLzJx2Os=Tf zS}6BkRw^wEc|6~IB|xd0NqgJd-Bze`&nrp}ayoY>6Amg$GvJLYRVjdBK>$l&N3njO z8C*qK$|DTT$9H79vI?IH6V=BQVQG4A;5xu1#|R(E1^Gh1;+Gkmpgwwx!klHhgf3)b zm$j;D<w~A^8wo;&)vU}RJOp{E$|^iMe1^2bD=4nQqx3A4*yKqS z#h1|xWT>CkW!YJDap#Wrw7O{qN<@XsA_d!;qUJiL^Kn=5>0L0^fu-ra7S@W=gUcxj zG3HNB&r`W5h9~Q)Dut3>lx1Gmqlv5_PLnkDAOk&|a(db-^9?b?XBxZ9YkeK8Yqzs} z>k*z>ik30oSWsNX{9)rTRzx{4*0_x2C9gBRA2Rm7j'}), - ('Comma separated list of stylesheet URLs. ' - 'Overrides previous --stylesheet and --stylesheet-path settings.', - ['--stylesheet'], - {'metavar': '', 'overrides': 'stylesheet_path', - 'validator': frontend.validate_comma_separated_list}), - ('Comma separated list of stylesheet paths. ' - 'Relative paths are expanded if a matching file is found in ' - 'the --stylesheet-dirs. With --link-stylesheet, ' - 'the path is rewritten relative to the output HTML file. ' - '(default: writer dependent)', - ['--stylesheet-path'], - {'metavar': '', 'overrides': 'stylesheet', - 'validator': frontend.validate_comma_separated_list}), - ('Comma-separated list of directories where stylesheets are found. ' - 'Used by --stylesheet-path when expanding relative path arguments. ' - '(default: writer dependent)', - ['--stylesheet-dirs'], - {'metavar': '', - 'validator': frontend.validate_comma_separated_list}), - ('Embed the stylesheet(s) in the output HTML file. The stylesheet ' - 'files must be accessible during processing. (default)', - ['--embed-stylesheet'], - {'default': True, 'action': 'store_true', - 'validator': frontend.validate_boolean}), - ('Link to the stylesheet(s) in the output HTML file. ', - ['--link-stylesheet'], - {'dest': 'embed_stylesheet', 'action': 'store_false'}), - ('Specify the initial header level. ' - 'Does not affect document title & subtitle (see --no-doc-title).' - '(default: writer dependent).', - ['--initial-header-level'], - {'choices': '1 2 3 4 5 6'.split(), 'default': '2', - 'metavar': ''}), - ('Format for footnote references: one of "superscript" or ' - '"brackets". (default: "brackets")', - ['--footnote-references'], - {'choices': ['superscript', 'brackets'], 'default': 'brackets', - 'metavar': '', - 'overrides': 'trim_footnote_reference_space'}), - ('Format for block quote attributions: ' - 'one of "dash" (em-dash prefix), "parentheses"/"parens", or "none". ' - '(default: "dash")', - ['--attribution'], - {'choices': ['dash', 'parentheses', 'parens', 'none'], - 'default': 'dash', 'metavar': ''}), - ('Remove extra vertical whitespace between items of "simple" bullet ' - 'lists and enumerated lists. (default)', - ['--compact-lists'], - {'default': True, 'action': 'store_true', - 'validator': frontend.validate_boolean}), - ('Disable compact simple bullet and enumerated lists.', - ['--no-compact-lists'], - {'dest': 'compact_lists', 'action': 'store_false'}), - ('Remove extra vertical whitespace between items of simple field ' - 'lists. (default)', - ['--compact-field-lists'], - {'default': True, 'action': 'store_true', - 'validator': frontend.validate_boolean}), - ('Disable compact simple field lists.', - ['--no-compact-field-lists'], - {'dest': 'compact_field_lists', 'action': 'store_false'}), - ('Added to standard table classes. ' - 'Defined styles: borderless, booktabs, ' - 'align-left, align-center, align-right, ' - 'colwidths-auto, colwidths-grid.', - ['--table-style'], - {'default': ''}), - ('Math output format (one of "MathML", "HTML", "MathJax", ' - 'or "LaTeX") and option(s). ' - '(default: "HTML math.css")', - ['--math-output'], - {'default': 'HTML math.css', - 'validator': frontend.validate_math_output}), - ('Prepend an XML declaration. ', - ['--xml-declaration'], - {'default': False, 'action': 'store_true', - 'validator': frontend.validate_boolean}), - ('Omit the XML declaration.', - ['--no-xml-declaration'], - {'dest': 'xml_declaration', 'action': 'store_false'}), - ('Obfuscate email addresses to confuse harvesters while still ' - 'keeping email links usable with standards-compliant browsers.', - ['--cloak-email-addresses'], - {'action': 'store_true', 'validator': frontend.validate_boolean}), - ) - ) - - settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'} - - relative_path_settings = ('template',) - - config_section = 'html base writer' # overwrite in subclass - config_section_dependencies = ('writers', 'html writers') - - visitor_attributes = ( - 'head_prefix', 'head', 'stylesheet', 'body_prefix', - 'body_pre_docinfo', 'docinfo', 'body', 'body_suffix', - 'title', 'subtitle', 'header', 'footer', 'meta', 'fragment', - 'html_prolog', 'html_head', 'html_title', 'html_subtitle', - 'html_body') - - def get_transforms(self): - return super().get_transforms() + [writer_aux.Admonitions] - - def translate(self): - self.visitor = visitor = self.translator_class(self.document) - self.document.walkabout(visitor) - for attr in self.visitor_attributes: - setattr(self, attr, getattr(visitor, attr)) - self.output = self.apply_template() - - def apply_template(self): - with open(self.document.settings.template, encoding='utf-8') as fp: - template = fp.read() - subs = self.interpolation_dict() - return template % subs - - def interpolation_dict(self): - subs = {} - settings = self.document.settings - for attr in self.visitor_attributes: - subs[attr] = ''.join(getattr(self, attr)).rstrip('\n') - subs['encoding'] = settings.output_encoding - subs['version'] = docutils.__version__ - return subs - - def assemble_parts(self): - writers.Writer.assemble_parts(self) - for part in self.visitor_attributes: - self.parts[part] = ''.join(getattr(self, part)) - - -class HTMLTranslator(nodes.NodeVisitor): - - """ - Generic Docutils to HTML translator. - - See the `html4css1` and `html5_polyglot` writers for full featured - HTML writers. - - .. IMPORTANT:: - The `visit_*` and `depart_*` methods use a - heterogeneous stack, `self.context`. - When subclassing, make sure to be consistent in its use! - - Examples for robust coding: - - a) Override both `visit_*` and `depart_*` methods, don't call the - parent functions. - - b) Extend both and unconditionally call the parent functions:: - - def visit_example(self, node): - if foo: - self.body.append('

    ') - html4css1.HTMLTranslator.visit_example(self, node) - - def depart_example(self, node): - html4css1.HTMLTranslator.depart_example(self, node) - if foo: - self.body.append('
    ') - - c) Extend both, calling the parent functions under the same - conditions:: - - def visit_example(self, node): - if foo: - self.body.append('
    \n') - else: # call the parent method - _html_base.HTMLTranslator.visit_example(self, node) - - def depart_example(self, node): - if foo: - self.body.append('
    \n') - else: # call the parent method - _html_base.HTMLTranslator.depart_example(self, node) - - d) Extend one method (call the parent), but don't otherwise use the - `self.context` stack:: - - def depart_example(self, node): - _html_base.HTMLTranslator.depart_example(self, node) - if foo: - # implementation-specific code - # that does not use `self.context` - self.body.append('\n') - - This way, changes in stack use will not bite you. - """ - - doctype = '\n' - doctype_mathml = doctype - - head_prefix_template = ('\n\n') - content_type = '\n' - generator = ( - f'\n') - # `starttag()` arguments for the main document (HTML5 uses
    ) - documenttag_args = {'tagname': 'div', 'CLASS': 'document'} - - # Template for the MathJax script in the header: - mathjax_script = '\n' - - mathjax_url = 'file:/usr/share/javascript/mathjax/MathJax.js' - """ - URL of the MathJax javascript library. - - The MathJax library ought to be installed on the same - server as the rest of the deployed site files and specified - in the `math-output` setting appended to "mathjax". - See `Docutils Configuration`__. - - __ https://docutils.sourceforge.io/docs/user/config.html#math-output - - The fallback tries a local MathJax installation at - ``/usr/share/javascript/mathjax/MathJax.js``. - """ - - stylesheet_link = '\n' - embedded_stylesheet = '\n' - words_and_spaces = re.compile(r'[^ \n]+| +|\n') - # wrap point inside word: - in_word_wrap_point = re.compile(r'.+\W\W.+|[-?].+') - lang_attribute = 'lang' # name changes to 'xml:lang' in XHTML 1.1 - - special_characters = {ord('&'): '&', - ord('<'): '<', - ord('"'): '"', - ord('>'): '>', - ord('@'): '@', # may thwart address harvesters - } - """Character references for characters with a special meaning in HTML.""" - - videotypes = ('video/mp4', 'video/webm', 'video/ogg') - """MIME types supported by the HTML5