From d603d6f41c81ee3f5bed2982dcbba14b2f3c99ad Mon Sep 17 00:00:00 2001 From: Ladebeze66 Date: Wed, 2 Apr 2025 11:51:53 +0200 Subject: [PATCH] new --- README.md | 199 - __pycache__/post_process.cpython-312.pyc | Bin 30944 -> 0 bytes agents/__init__.py | 14 - agents/__pycache__/__init__.cpython-312.pyc | Bin 425 -> 0 bytes .../agent_analyse_image.cpython-312.pyc | Bin 3751 -> 0 bytes agents/__pycache__/agent_base.cpython-312.pyc | Bin 7583 -> 0 bytes .../agent_filtre_images.cpython-312.pyc | Bin 6801 -> 0 bytes .../agent_question_reponse.cpython-312.pyc | Bin 16286 -> 0 bytes agents/agent_analyse_image.py | 91 - agents/agent_base.py | 174 - agents/agent_filtre_images.py | 169 - agents/agent_question_reponse.py | 474 - config.json | 12 - config.json.example | 12 - extract_ticket.log | 4 - filter_images.log | 1 - llm-ticket3.code-workspace | 14 - llm/__init__.py | 8 - llm/__pycache__/__init__.cpython-312.pyc | Bin 299 -> 0 bytes llm/__pycache__/llm_base.cpython-312.pyc | Bin 2124 -> 0 bytes llm/__pycache__/mistral.cpython-312.pyc | Bin 10720 -> 0 bytes llm/__pycache__/pixtral.cpython-312.pyc | Bin 10941 -> 0 bytes llm/llm_base.py | 52 - llm/mistral.py | 243 - llm/pixtral.py | 245 - main.py | 400 - .../31975_ecran - 2020-04-07T120505.164.png | Bin 99024 -> 0 bytes output/ticket_T0140/attachments_info.json | 9 - output/ticket_T0140/messages.json | 25 - output/ticket_T0140/messages.json.backup | 59 - output/ticket_T0140/questions_reponses.md | 15 - .../ticket_T0140/rapport/ticket_analysis.json | 90 - .../ticket_T0140/rapport/ticket_analysis.md | 76 - output/ticket_T0140/ticket_info.json | 140 - output/ticket_T0150/attachments_info.json | 1 - output/ticket_T0150/messages.json | 168 - output/ticket_T0150/messages.json.backup | 293 - output/ticket_T0150/messages.json.original | 155 - output/ticket_T0150/questions_reponses.md | 20 - .../ticket_T0150/rapport/ticket_analysis.json | 191 - .../ticket_T0150/rapport/ticket_analysis.md | 69 - output/ticket_T0150/ticket_info.json | 164 - .../attachments/32380_image001.png | Bin 25085 -> 0 bytes .../attachments/32382_Problème partie.png | Bin 255246 -> 0 bytes output/ticket_T0167/attachments_info.json | 16 - output/ticket_T0167/messages.json | 25 - output/ticket_T0167/messages.json.backup | 125 - output/ticket_T0167/questions_reponses.md | 15 - .../ticket_T0167/rapport/ticket_analysis.json | 151 - .../ticket_T0167/rapport/ticket_analysis.md | 116 - output/ticket_T0167/ticket_info.json | 145 - .../attachments/144792_image003.png | Bin 5417 -> 0 bytes .../attachments/144794_image004.jpg | Bin 63295 -> 0 bytes .../attachments/144796_image.png | Bin 45686 -> 0 bytes output/ticket_T11067/attachments_info.json | 23 - output/ticket_T11067/messages.json | 38 - output/ticket_T11067/messages.json.backup | 35 - output/ticket_T11067/questions_reponses.md | 16 - .../rapport/ticket_analysis.json | 238 - .../ticket_T11067/rapport/ticket_analysis.md | 157 - output/ticket_T11067/ticket_info.json | 145 - .../attachments/144918_image.png | Bin 115046 -> 0 bytes output/ticket_T11094/attachments_info.json | 9 - output/ticket_T11094/messages.json | 25 - output/ticket_T11094/messages.json.backup | 83 - output/ticket_T11094/questions_reponses.md | 15 - .../rapport/ticket_analysis.json | 112 - .../ticket_T11094/rapport/ticket_analysis.md | 104 - output/ticket_T11094/ticket_info.json | 143 - output_processed/ticket_T0167/messages.json | 38 - .../ticket_T0167/pretraitement_rapport.json | 8 - .../ticket_T0167/ticket_info.json | 145 - post_process.py | 982 -- requirements.txt | 2 - scripts/analyze_image_contexte.py | 384 - scripts/analyze_ticket.py | 444 - scripts/extract_question_reponse.py | 534 - scripts/extract_ticket.py | 504 - scripts/filter_images.py | 380 - scripts/processus_complet.py | 383 - utils/__init__.py | 7 - utils/__pycache__/__init__.cpython-312.pyc | Bin 302 -> 0 bytes .../ticket_analyzer.cpython-312.pyc | Bin 16623 -> 0 bytes .../ticket_manager.cpython-312.pyc | Bin 14635 -> 0 bytes utils/ticket_analyzer.py | 358 - utils/ticket_manager.py | 408 - venv/bin/Activate.ps1 | 247 - venv/bin/activate | 70 - venv/bin/activate.csh | 27 - venv/bin/activate.fish | 69 - venv/bin/httpx | 8 - venv/bin/normalizer | 8 - venv/bin/pip | 8 - venv/bin/pip3 | 8 - venv/bin/pip3.12 | 8 - venv/bin/python | 1 - venv/bin/python3 | 1 - venv/bin/python3.12 | 1 - .../OdooRPC-0.10.1.dist-info/AUTHORS | 3 - .../OdooRPC-0.10.1.dist-info/INSTALLER | 1 - .../OdooRPC-0.10.1.dist-info/LICENSE | 165 - .../OdooRPC-0.10.1.dist-info/METADATA | 163 - .../OdooRPC-0.10.1.dist-info/RECORD | 34 - .../OdooRPC-0.10.1.dist-info/REQUESTED | 0 .../OdooRPC-0.10.1.dist-info/WHEEL | 6 - .../OdooRPC-0.10.1.dist-info/top_level.txt | 1 - venv/lib/python3.12/site-packages/README.rst | 1 - .../__pycache__/six.cpython-312.pyc | Bin 41400 -> 0 bytes .../typing_extensions.cpython-312.pyc | Bin 172877 -> 0 bytes .../annotated_types-0.7.0.dist-info/INSTALLER | 1 - .../annotated_types-0.7.0.dist-info/METADATA | 295 - .../annotated_types-0.7.0.dist-info/RECORD | 10 - .../annotated_types-0.7.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 21 - .../site-packages/annotated_types/__init__.py | 432 - .../__pycache__/__init__.cpython-312.pyc | Bin 18616 -> 0 bytes .../__pycache__/test_cases.cpython-312.pyc | Bin 13235 -> 0 bytes .../site-packages/annotated_types/py.typed | 0 .../annotated_types/test_cases.py | 151 - .../anyio-4.9.0.dist-info/INSTALLER | 1 - .../anyio-4.9.0.dist-info/LICENSE | 20 - .../anyio-4.9.0.dist-info/METADATA | 105 - .../anyio-4.9.0.dist-info/RECORD | 88 - .../site-packages/anyio-4.9.0.dist-info/WHEEL | 5 - .../anyio-4.9.0.dist-info/entry_points.txt | 2 - .../anyio-4.9.0.dist-info/top_level.txt | 1 - .../site-packages/anyio/__init__.py | 85 - .../__pycache__/__init__.cpython-312.pyc | Bin 3578 -> 0 bytes .../__pycache__/from_thread.cpython-312.pyc | Bin 24086 -> 0 bytes .../__pycache__/lowlevel.cpython-312.pyc | Bin 6961 -> 0 bytes .../__pycache__/pytest_plugin.cpython-312.pyc | Bin 13394 -> 0 bytes .../to_interpreter.cpython-312.pyc | Bin 9116 -> 0 bytes .../__pycache__/to_process.cpython-312.pyc | Bin 11869 -> 0 bytes .../__pycache__/to_thread.cpython-312.pyc | Bin 2934 -> 0 bytes .../site-packages/anyio/_backends/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 185 -> 0 bytes .../__pycache__/_asyncio.cpython-312.pyc | Bin 132756 -> 0 bytes .../__pycache__/_trio.cpython-312.pyc | Bin 70477 -> 0 bytes .../site-packages/anyio/_backends/_asyncio.py | 2816 ------ .../site-packages/anyio/_backends/_trio.py | 1334 --- .../site-packages/anyio/_core/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 181 -> 0 bytes .../_asyncio_selector_thread.cpython-312.pyc | Bin 8412 -> 0 bytes .../__pycache__/_eventloop.cpython-312.pyc | Bin 6339 -> 0 bytes .../__pycache__/_exceptions.cpython-312.pyc | Bin 6053 -> 0 bytes .../_core/__pycache__/_fileio.cpython-312.pyc | Bin 41612 -> 0 bytes .../__pycache__/_resources.cpython-312.pyc | Bin 934 -> 0 bytes .../__pycache__/_signals.cpython-312.pyc | Bin 1266 -> 0 bytes .../__pycache__/_sockets.cpython-312.pyc | Bin 31540 -> 0 bytes .../__pycache__/_streams.cpython-312.pyc | Bin 2329 -> 0 bytes .../__pycache__/_subprocesses.cpython-312.pyc | Bin 9641 -> 0 bytes .../_synchronization.cpython-312.pyc | Bin 32180 -> 0 bytes .../_core/__pycache__/_tasks.cpython-312.pyc | Bin 6986 -> 0 bytes .../__pycache__/_tempfile.cpython-312.pyc | Bin 28133 -> 0 bytes .../__pycache__/_testing.cpython-312.pyc | Bin 3561 -> 0 bytes .../__pycache__/_typedattr.cpython-312.pyc | Bin 3831 -> 0 bytes .../anyio/_core/_asyncio_selector_thread.py | 167 - .../site-packages/anyio/_core/_eventloop.py | 166 - .../site-packages/anyio/_core/_exceptions.py | 126 - .../site-packages/anyio/_core/_fileio.py | 742 -- .../site-packages/anyio/_core/_resources.py | 18 - .../site-packages/anyio/_core/_signals.py | 27 - .../site-packages/anyio/_core/_sockets.py | 792 -- .../site-packages/anyio/_core/_streams.py | 52 - .../anyio/_core/_subprocesses.py | 202 - .../anyio/_core/_synchronization.py | 732 -- .../site-packages/anyio/_core/_tasks.py | 158 - .../site-packages/anyio/_core/_tempfile.py | 616 -- .../site-packages/anyio/_core/_testing.py | 78 - .../site-packages/anyio/_core/_typedattr.py | 81 - .../site-packages/anyio/abc/__init__.py | 55 - .../abc/__pycache__/__init__.cpython-312.pyc | Bin 2221 -> 0 bytes .../__pycache__/_eventloop.cpython-312.pyc | Bin 14970 -> 0 bytes .../__pycache__/_resources.cpython-312.pyc | Bin 1628 -> 0 bytes .../abc/__pycache__/_sockets.cpython-312.pyc | Bin 9876 -> 0 bytes .../abc/__pycache__/_streams.cpython-312.pyc | Bin 8432 -> 0 bytes .../__pycache__/_subprocesses.cpython-312.pyc | Bin 3236 -> 0 bytes .../abc/__pycache__/_tasks.cpython-312.pyc | Bin 4512 -> 0 bytes .../abc/__pycache__/_testing.cpython-312.pyc | Bin 2831 -> 0 bytes .../site-packages/anyio/abc/_eventloop.py | 376 - .../site-packages/anyio/abc/_resources.py | 33 - .../site-packages/anyio/abc/_sockets.py | 194 - .../site-packages/anyio/abc/_streams.py | 203 - .../site-packages/anyio/abc/_subprocesses.py | 79 - .../site-packages/anyio/abc/_tasks.py | 101 - .../site-packages/anyio/abc/_testing.py | 65 - .../site-packages/anyio/from_thread.py | 527 - .../site-packages/anyio/lowlevel.py | 161 - .../python3.12/site-packages/anyio/py.typed | 0 .../site-packages/anyio/pytest_plugin.py | 272 - .../site-packages/anyio/streams/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 183 -> 0 bytes .../__pycache__/buffered.cpython-312.pyc | Bin 6112 -> 0 bytes .../streams/__pycache__/file.cpython-312.pyc | Bin 7524 -> 0 bytes .../__pycache__/memory.cpython-312.pyc | Bin 14944 -> 0 bytes .../__pycache__/stapled.cpython-312.pyc | Bin 7544 -> 0 bytes .../streams/__pycache__/text.cpython-312.pyc | Bin 8288 -> 0 bytes .../streams/__pycache__/tls.cpython-312.pyc | Bin 17567 -> 0 bytes .../site-packages/anyio/streams/buffered.py | 119 - .../site-packages/anyio/streams/file.py | 148 - .../site-packages/anyio/streams/memory.py | 317 - .../site-packages/anyio/streams/stapled.py | 141 - .../site-packages/anyio/streams/text.py | 147 - .../site-packages/anyio/streams/tls.py | 352 - .../site-packages/anyio/to_interpreter.py | 218 - .../site-packages/anyio/to_process.py | 258 - .../site-packages/anyio/to_thread.py | 69 - .../beautifulsoup4-4.13.3.dist-info/INSTALLER | 1 - .../beautifulsoup4-4.13.3.dist-info/METADATA | 123 - .../beautifulsoup4-4.13.3.dist-info/RECORD | 89 - .../beautifulsoup4-4.13.3.dist-info/WHEEL | 4 - .../licenses/AUTHORS | 49 - .../licenses/LICENSE | 31 - .../bs4-0.0.2.dist-info/INSTALLER | 1 - .../bs4-0.0.2.dist-info/METADATA | 10 - .../site-packages/bs4-0.0.2.dist-info/RECORD | 6 - .../bs4-0.0.2.dist-info/REQUESTED | 0 .../site-packages/bs4-0.0.2.dist-info/WHEEL | 5 - .../python3.12/site-packages/bs4/__init__.py | 1170 --- .../bs4/__pycache__/__init__.cpython-312.pyc | Bin 39625 -> 0 bytes .../__pycache__/_deprecation.cpython-312.pyc | Bin 3741 -> 0 bytes .../bs4/__pycache__/_typing.cpython-312.pyc | Bin 3543 -> 0 bytes .../bs4/__pycache__/_warnings.cpython-312.pyc | Bin 5594 -> 0 bytes .../bs4/__pycache__/css.cpython-312.pyc | Bin 14420 -> 0 bytes .../bs4/__pycache__/dammit.cpython-312.pyc | Bin 46475 -> 0 bytes .../bs4/__pycache__/diagnose.cpython-312.pyc | Bin 12649 -> 0 bytes .../bs4/__pycache__/element.cpython-312.pyc | Bin 107375 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 1757 -> 0 bytes .../bs4/__pycache__/filter.cpython-312.pyc | Bin 28612 -> 0 bytes .../bs4/__pycache__/formatter.cpython-312.pyc | Bin 10525 -> 0 bytes .../site-packages/bs4/_deprecation.py | 80 - .../python3.12/site-packages/bs4/_typing.py | 196 - .../python3.12/site-packages/bs4/_warnings.py | 98 - .../site-packages/bs4/builder/__init__.py | 848 -- .../__pycache__/__init__.cpython-312.pyc | Bin 27459 -> 0 bytes .../__pycache__/_html5lib.cpython-312.pyc | Bin 23134 -> 0 bytes .../__pycache__/_htmlparser.cpython-312.pyc | Bin 14630 -> 0 bytes .../builder/__pycache__/_lxml.cpython-312.pyc | Bin 18434 -> 0 bytes .../site-packages/bs4/builder/_html5lib.py | 594 -- .../site-packages/bs4/builder/_htmlparser.py | 474 - .../site-packages/bs4/builder/_lxml.py | 490 - venv/lib/python3.12/site-packages/bs4/css.py | 338 - .../python3.12/site-packages/bs4/dammit.py | 1408 --- .../python3.12/site-packages/bs4/diagnose.py | 268 - .../python3.12/site-packages/bs4/element.py | 2886 ------ .../site-packages/bs4/exceptions.py | 28 - .../python3.12/site-packages/bs4/filter.py | 755 -- .../python3.12/site-packages/bs4/formatter.py | 276 - .../lib/python3.12/site-packages/bs4/py.typed | 0 .../site-packages/bs4/tests/__init__.py | 1305 --- .../__pycache__/__init__.cpython-312.pyc | Bin 67411 -> 0 bytes .../__pycache__/test_builder.cpython-312.pyc | Bin 1571 -> 0 bytes .../test_builder_registry.cpython-312.pyc | Bin 7595 -> 0 bytes .../__pycache__/test_css.cpython-312.pyc | Bin 28906 -> 0 bytes .../__pycache__/test_dammit.cpython-312.pyc | Bin 19783 -> 0 bytes .../__pycache__/test_element.cpython-312.pyc | Bin 6028 -> 0 bytes .../__pycache__/test_filter.cpython-312.pyc | Bin 31904 -> 0 bytes .../test_formatter.cpython-312.pyc | Bin 7797 -> 0 bytes .../__pycache__/test_fuzz.cpython-312.pyc | Bin 7036 -> 0 bytes .../__pycache__/test_html5lib.cpython-312.pyc | Bin 11959 -> 0 bytes .../test_htmlparser.cpython-312.pyc | Bin 7282 -> 0 bytes .../__pycache__/test_lxml.cpython-312.pyc | Bin 8094 -> 0 bytes .../test_navigablestring.cpython-312.pyc | Bin 7760 -> 0 bytes .../test_pageelement.cpython-312.pyc | Bin 22905 -> 0 bytes .../__pycache__/test_soup.cpython-312.pyc | Bin 31496 -> 0 bytes .../__pycache__/test_tag.cpython-312.pyc | Bin 14116 -> 0 bytes .../__pycache__/test_tree.cpython-312.pyc | Bin 93179 -> 0 bytes ...mized-bs4_fuzzer-4670634698080256.testcase | 1 - ...mized-bs4_fuzzer-4818336571064320.testcase | 1 - ...mized-bs4_fuzzer-4999465949331456.testcase | 1 - ...mized-bs4_fuzzer-5000587759190016.testcase | Bin 15347 -> 0 bytes ...mized-bs4_fuzzer-5167584867909632.testcase | Bin 19469 -> 0 bytes ...mized-bs4_fuzzer-5270998950477824.testcase | Bin 12 -> 0 bytes ...mized-bs4_fuzzer-5375146639360000.testcase | 1 - ...mized-bs4_fuzzer-5492400320282624.testcase | Bin 11502 -> 0 bytes ...mized-bs4_fuzzer-5703933063462912.testcase | 2 - ...mized-bs4_fuzzer-5843991618256896.testcase | 1 - ...mized-bs4_fuzzer-5984173902397440.testcase | Bin 51495 -> 0 bytes ...mized-bs4_fuzzer-6124268085182464.testcase | 1 - ...mized-bs4_fuzzer-6241471367348224.testcase | 1 - ...mized-bs4_fuzzer-6306874195312640.testcase | 1 - ...mized-bs4_fuzzer-6450958476902400.testcase | Bin 3546 -> 0 bytes ...mized-bs4_fuzzer-6600557255327744.testcase | Bin 124 -> 0 bytes ...0c8ed8bcd0785b67000fcd5dea1d33f08.testcase | Bin 2607 -> 0 bytes ...a2b26f13537b68d3794b0478a4090ee4a.testcase | Bin 103 -> 0 bytes .../site-packages/bs4/tests/test_builder.py | 28 - .../bs4/tests/test_builder_registry.py | 139 - .../site-packages/bs4/tests/test_css.py | 536 - .../site-packages/bs4/tests/test_dammit.py | 433 - .../site-packages/bs4/tests/test_element.py | 138 - .../site-packages/bs4/tests/test_filter.py | 674 -- .../site-packages/bs4/tests/test_formatter.py | 170 - .../site-packages/bs4/tests/test_fuzz.py | 181 - .../site-packages/bs4/tests/test_html5lib.py | 264 - .../bs4/tests/test_htmlparser.py | 161 - .../site-packages/bs4/tests/test_lxml.py | 196 - .../bs4/tests/test_navigablestring.py | 144 - .../bs4/tests/test_pageelement.py | 437 - .../site-packages/bs4/tests/test_soup.py | 602 -- .../site-packages/bs4/tests/test_tag.py | 241 - .../site-packages/bs4/tests/test_tree.py | 1452 --- .../certifi-2025.1.31.dist-info/INSTALLER | 1 - .../certifi-2025.1.31.dist-info/LICENSE | 20 - .../certifi-2025.1.31.dist-info/METADATA | 77 - .../certifi-2025.1.31.dist-info/RECORD | 14 - .../certifi-2025.1.31.dist-info/WHEEL | 5 - .../certifi-2025.1.31.dist-info/top_level.txt | 1 - .../site-packages/certifi/__init__.py | 4 - .../site-packages/certifi/__main__.py | 12 - .../__pycache__/__init__.cpython-312.pyc | Bin 304 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 619 -> 0 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 3189 -> 0 bytes .../site-packages/certifi/cacert.pem | 4897 ---------- .../python3.12/site-packages/certifi/core.py | 114 - .../python3.12/site-packages/certifi/py.typed | 0 .../INSTALLER | 1 - .../LICENSE | 21 - .../METADATA | 721 -- .../charset_normalizer-3.4.1.dist-info/RECORD | 35 - .../charset_normalizer-3.4.1.dist-info/WHEEL | 6 - .../entry_points.txt | 2 - .../top_level.txt | 1 - .../charset_normalizer/__init__.py | 48 - .../charset_normalizer/__main__.py | 6 - .../__pycache__/__init__.cpython-312.pyc | Bin 1770 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 345 -> 0 bytes .../__pycache__/api.cpython-312.pyc | Bin 18159 -> 0 bytes .../__pycache__/cd.cpython-312.pyc | Bin 13286 -> 0 bytes .../__pycache__/constant.cpython-312.pyc | Bin 38669 -> 0 bytes .../__pycache__/legacy.cpython-312.pyc | Bin 2810 -> 0 bytes .../__pycache__/md.cpython-312.pyc | Bin 24398 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 17117 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 13524 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 372 -> 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 | 321 - .../cli/__pycache__/__init__.cpython-312.pyc | Bin 333 -> 0 bytes .../cli/__pycache__/__main__.cpython-312.pyc | Bin 10968 -> 0 bytes .../charset_normalizer/constant.py | 1998 ---- .../charset_normalizer/legacy.py | 66 - .../md.cpython-312-x86_64-linux-gnu.so | Bin 16064 -> 0 bytes .../site-packages/charset_normalizer/md.py | 630 -- .../md__mypyc.cpython-312-x86_64-linux-gnu.so | Bin 280904 -> 0 bytes .../charset_normalizer/models.py | 360 - .../site-packages/charset_normalizer/py.typed | 0 .../site-packages/charset_normalizer/utils.py | 408 - .../charset_normalizer/version.py | 8 - .../site-packages/dateutil/__init__.py | 24 - .../__pycache__/__init__.cpython-312.pyc | Bin 1124 -> 0 bytes .../__pycache__/_common.cpython-312.pyc | Bin 1921 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 300 -> 0 bytes .../__pycache__/easter.cpython-312.pyc | Bin 2844 -> 0 bytes .../__pycache__/relativedelta.cpython-312.pyc | Bin 28357 -> 0 bytes .../__pycache__/rrule.cpython-312.pyc | Bin 69217 -> 0 bytes .../__pycache__/tzwin.cpython-312.pyc | Bin 203 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 2556 -> 0 bytes .../site-packages/dateutil/_common.py | 43 - .../site-packages/dateutil/_version.py | 4 - .../site-packages/dateutil/easter.py | 89 - .../site-packages/dateutil/parser/__init__.py | 61 - .../__pycache__/__init__.cpython-312.pyc | Bin 2650 -> 0 bytes .../__pycache__/_parser.cpython-312.pyc | Bin 61843 -> 0 bytes .../__pycache__/isoparser.cpython-312.pyc | Bin 15576 -> 0 bytes .../site-packages/dateutil/parser/_parser.py | 1613 --- .../dateutil/parser/isoparser.py | 416 - .../site-packages/dateutil/relativedelta.py | 599 -- .../site-packages/dateutil/rrule.py | 1737 ---- .../site-packages/dateutil/tz/__init__.py | 12 - .../tz/__pycache__/__init__.cpython-312.pyc | Bin 703 -> 0 bytes .../tz/__pycache__/_common.cpython-312.pyc | Bin 14156 -> 0 bytes .../tz/__pycache__/_factories.cpython-312.pyc | Bin 4589 -> 0 bytes .../tz/__pycache__/tz.cpython-312.pyc | Bin 66003 -> 0 bytes .../tz/__pycache__/win.cpython-312.pyc | Bin 17259 -> 0 bytes .../site-packages/dateutil/tz/_common.py | 419 - .../site-packages/dateutil/tz/_factories.py | 80 - .../site-packages/dateutil/tz/tz.py | 1849 ---- .../site-packages/dateutil/tz/win.py | 370 - .../site-packages/dateutil/tzwin.py | 2 - .../site-packages/dateutil/utils.py | 71 - .../dateutil/zoneinfo/__init__.py | 167 - .../__pycache__/__init__.cpython-312.pyc | Bin 7426 -> 0 bytes .../__pycache__/rebuild.cpython-312.pyc | Bin 3952 -> 0 bytes .../zoneinfo/dateutil-zoneinfo.tar.gz | Bin 156400 -> 0 bytes .../dateutil/zoneinfo/rebuild.py | 75 - .../INSTALLER | 1 - .../LICENSE.txt | 21 - .../METADATA | 48 - .../eval_type_backport-0.2.2.dist-info/RECORD | 13 - .../eval_type_backport-0.2.2.dist-info/WHEEL | 5 - .../top_level.txt | 1 - .../eval_type_backport/__init__.py | 9 - .../__pycache__/__init__.cpython-312.pyc | Bin 423 -> 0 bytes .../eval_type_backport.cpython-312.pyc | Bin 11050 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 213 -> 0 bytes .../eval_type_backport/eval_type_backport.py | 230 - .../site-packages/eval_type_backport/py.typed | 0 .../eval_type_backport/version.py | 1 - .../h11-0.14.0.dist-info/INSTALLER | 1 - .../h11-0.14.0.dist-info/LICENSE.txt | 22 - .../h11-0.14.0.dist-info/METADATA | 193 - .../site-packages/h11-0.14.0.dist-info/RECORD | 52 - .../site-packages/h11-0.14.0.dist-info/WHEEL | 5 - .../h11-0.14.0.dist-info/top_level.txt | 1 - .../python3.12/site-packages/h11/__init__.py | 62 - .../h11/__pycache__/__init__.cpython-312.pyc | Bin 1064 -> 0 bytes .../h11/__pycache__/_abnf.cpython-312.pyc | Bin 1770 -> 0 bytes .../__pycache__/_connection.cpython-312.pyc | Bin 22591 -> 0 bytes .../h11/__pycache__/_events.cpython-312.pyc | Bin 13275 -> 0 bytes .../h11/__pycache__/_headers.cpython-312.pyc | Bin 7856 -> 0 bytes .../h11/__pycache__/_readers.cpython-312.pyc | Bin 9409 -> 0 bytes .../_receivebuffer.cpython-312.pyc | Bin 4693 -> 0 bytes .../h11/__pycache__/_state.cpython-312.pyc | Bin 8528 -> 0 bytes .../h11/__pycache__/_util.cpython-312.pyc | Bin 4708 -> 0 bytes .../h11/__pycache__/_version.cpython-312.pyc | Bin 202 -> 0 bytes .../h11/__pycache__/_writers.cpython-312.pyc | Bin 6284 -> 0 bytes .../lib/python3.12/site-packages/h11/_abnf.py | 132 - .../site-packages/h11/_connection.py | 633 -- .../python3.12/site-packages/h11/_events.py | 369 - .../python3.12/site-packages/h11/_headers.py | 278 - .../python3.12/site-packages/h11/_readers.py | 247 - .../site-packages/h11/_receivebuffer.py | 153 - .../python3.12/site-packages/h11/_state.py | 367 - .../lib/python3.12/site-packages/h11/_util.py | 135 - .../python3.12/site-packages/h11/_version.py | 16 - .../python3.12/site-packages/h11/_writers.py | 145 - .../lib/python3.12/site-packages/h11/py.typed | 1 - .../site-packages/h11/tests/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 179 -> 0 bytes .../tests/__pycache__/helpers.cpython-312.pyc | Bin 4380 -> 0 bytes .../test_against_stdlib_http.cpython-312.pyc | Bin 6945 -> 0 bytes .../test_connection.cpython-312.pyc | Bin 58345 -> 0 bytes .../__pycache__/test_events.cpython-312.pyc | Bin 5534 -> 0 bytes .../__pycache__/test_headers.cpython-312.pyc | Bin 7121 -> 0 bytes .../__pycache__/test_helpers.cpython-312.pyc | Bin 1187 -> 0 bytes .../tests/__pycache__/test_io.cpython-312.pyc | Bin 20016 -> 0 bytes .../test_receivebuffer.cpython-312.pyc | Bin 3967 -> 0 bytes .../__pycache__/test_state.cpython-312.pyc | Bin 12617 -> 0 bytes .../__pycache__/test_util.cpython-312.pyc | Bin 6169 -> 0 bytes .../site-packages/h11/tests/data/test-file | 1 - .../site-packages/h11/tests/helpers.py | 101 - .../h11/tests/test_against_stdlib_http.py | 115 - .../h11/tests/test_connection.py | 1122 --- .../site-packages/h11/tests/test_events.py | 150 - .../site-packages/h11/tests/test_headers.py | 157 - .../site-packages/h11/tests/test_helpers.py | 32 - .../site-packages/h11/tests/test_io.py | 572 -- .../h11/tests/test_receivebuffer.py | 135 - .../site-packages/h11/tests/test_state.py | 271 - .../site-packages/h11/tests/test_util.py | 112 - .../httpcore-1.0.7.dist-info/INSTALLER | 1 - .../httpcore-1.0.7.dist-info/METADATA | 616 -- .../httpcore-1.0.7.dist-info/RECORD | 68 - .../httpcore-1.0.7.dist-info/WHEEL | 4 - .../licenses/LICENSE.md | 27 - .../site-packages/httpcore/__init__.py | 140 - .../__pycache__/__init__.cpython-312.pyc | Bin 3152 -> 0 bytes .../httpcore/__pycache__/_api.cpython-312.pyc | Bin 3764 -> 0 bytes .../__pycache__/_exceptions.cpython-312.pyc | Bin 3179 -> 0 bytes .../__pycache__/_models.cpython-312.pyc | Bin 23110 -> 0 bytes .../httpcore/__pycache__/_ssl.cpython-312.pyc | Bin 599 -> 0 bytes .../_synchronization.cpython-312.pyc | Bin 14174 -> 0 bytes .../__pycache__/_trace.cpython-312.pyc | Bin 5591 -> 0 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 1279 -> 0 bytes .../python3.12/site-packages/httpcore/_api.py | 94 - .../site-packages/httpcore/_async/__init__.py | 39 - .../__pycache__/__init__.cpython-312.pyc | Bin 1612 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 11789 -> 0 bytes .../connection_pool.cpython-312.pyc | Bin 19669 -> 0 bytes .../_async/__pycache__/http11.cpython-312.pyc | Bin 20231 -> 0 bytes .../_async/__pycache__/http2.cpython-312.pyc | Bin 31236 -> 0 bytes .../__pycache__/http_proxy.cpython-312.pyc | Bin 17989 -> 0 bytes .../__pycache__/interfaces.cpython-312.pyc | Bin 5743 -> 0 bytes .../__pycache__/socks_proxy.cpython-312.pyc | Bin 16886 -> 0 bytes .../httpcore/_async/connection.py | 222 - .../httpcore/_async/connection_pool.py | 420 - .../site-packages/httpcore/_async/http11.py | 379 - .../site-packages/httpcore/_async/http2.py | 583 -- .../httpcore/_async/http_proxy.py | 367 - .../httpcore/_async/interfaces.py | 137 - .../httpcore/_async/socks_proxy.py | 341 - .../httpcore/_backends/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 188 -> 0 bytes .../__pycache__/anyio.cpython-312.pyc | Bin 8618 -> 0 bytes .../__pycache__/auto.cpython-312.pyc | Bin 2680 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 4882 -> 0 bytes .../__pycache__/mock.cpython-312.pyc | Bin 7146 -> 0 bytes .../__pycache__/sync.cpython-312.pyc | Bin 11419 -> 0 bytes .../__pycache__/trio.cpython-312.pyc | Bin 8955 -> 0 bytes .../site-packages/httpcore/_backends/anyio.py | 146 - .../site-packages/httpcore/_backends/auto.py | 52 - .../site-packages/httpcore/_backends/base.py | 101 - .../site-packages/httpcore/_backends/mock.py | 143 - .../site-packages/httpcore/_backends/sync.py | 241 - .../site-packages/httpcore/_backends/trio.py | 159 - .../site-packages/httpcore/_exceptions.py | 81 - .../site-packages/httpcore/_models.py | 516 - .../python3.12/site-packages/httpcore/_ssl.py | 9 - .../site-packages/httpcore/_sync/__init__.py | 39 - .../__pycache__/__init__.cpython-312.pyc | Bin 1566 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 10409 -> 0 bytes .../connection_pool.cpython-312.pyc | Bin 18748 -> 0 bytes .../_sync/__pycache__/http11.cpython-312.pyc | Bin 17775 -> 0 bytes .../_sync/__pycache__/http2.cpython-312.pyc | Bin 27239 -> 0 bytes .../__pycache__/http_proxy.cpython-312.pyc | Bin 17172 -> 0 bytes .../__pycache__/interfaces.cpython-312.pyc | Bin 5290 -> 0 bytes .../__pycache__/socks_proxy.cpython-312.pyc | Bin 15637 -> 0 bytes .../httpcore/_sync/connection.py | 222 - .../httpcore/_sync/connection_pool.py | 420 - .../site-packages/httpcore/_sync/http11.py | 379 - .../site-packages/httpcore/_sync/http2.py | 583 -- .../httpcore/_sync/http_proxy.py | 367 - .../httpcore/_sync/interfaces.py | 137 - .../httpcore/_sync/socks_proxy.py | 341 - .../httpcore/_synchronization.py | 318 - .../site-packages/httpcore/_trace.py | 107 - .../site-packages/httpcore/_utils.py | 37 - .../site-packages/httpcore/py.typed | 0 .../httpx-0.28.1.dist-info/INSTALLER | 1 - .../httpx-0.28.1.dist-info/METADATA | 203 - .../httpx-0.28.1.dist-info/RECORD | 54 - .../httpx-0.28.1.dist-info/WHEEL | 4 - .../httpx-0.28.1.dist-info/entry_points.txt | 2 - .../licenses/LICENSE.md | 12 - .../site-packages/httpx/__init__.py | 105 - .../__pycache__/__init__.cpython-312.pyc | Bin 2114 -> 0 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 304 -> 0 bytes .../httpx/__pycache__/_api.cpython-312.pyc | Bin 10339 -> 0 bytes .../httpx/__pycache__/_auth.cpython-312.pyc | Bin 15591 -> 0 bytes .../httpx/__pycache__/_client.cpython-312.pyc | Bin 64176 -> 0 bytes .../httpx/__pycache__/_config.cpython-312.pyc | Bin 10972 -> 0 bytes .../__pycache__/_content.cpython-312.pyc | Bin 10397 -> 0 bytes .../__pycache__/_decoders.cpython-312.pyc | Bin 16749 -> 0 bytes .../__pycache__/_exceptions.cpython-312.pyc | Bin 12074 -> 0 bytes .../httpx/__pycache__/_main.cpython-312.pyc | Bin 20612 -> 0 bytes .../httpx/__pycache__/_models.cpython-312.pyc | Bin 58586 -> 0 bytes .../__pycache__/_multipart.cpython-312.pyc | Bin 13597 -> 0 bytes .../__pycache__/_status_codes.cpython-312.pyc | Bin 7184 -> 0 bytes .../httpx/__pycache__/_types.cpython-312.pyc | Bin 3816 -> 0 bytes .../__pycache__/_urlparse.cpython-312.pyc | Bin 17477 -> 0 bytes .../httpx/__pycache__/_urls.cpython-312.pyc | Bin 27920 -> 0 bytes .../httpx/__pycache__/_utils.cpython-312.pyc | Bin 9353 -> 0 bytes .../site-packages/httpx/__version__.py | 3 - .../python3.12/site-packages/httpx/_api.py | 438 - .../python3.12/site-packages/httpx/_auth.py | 348 - .../python3.12/site-packages/httpx/_client.py | 2019 ---- .../python3.12/site-packages/httpx/_config.py | 248 - .../site-packages/httpx/_content.py | 240 - .../site-packages/httpx/_decoders.py | 393 - .../site-packages/httpx/_exceptions.py | 379 - .../python3.12/site-packages/httpx/_main.py | 506 - .../python3.12/site-packages/httpx/_models.py | 1277 --- .../site-packages/httpx/_multipart.py | 300 - .../site-packages/httpx/_status_codes.py | 162 - .../httpx/_transports/__init__.py | 15 - .../__pycache__/__init__.cpython-312.pyc | Bin 433 -> 0 bytes .../__pycache__/asgi.cpython-312.pyc | Bin 7570 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 3863 -> 0 bytes .../__pycache__/default.cpython-312.pyc | Bin 17116 -> 0 bytes .../__pycache__/mock.cpython-312.pyc | Bin 1931 -> 0 bytes .../__pycache__/wsgi.cpython-312.pyc | Bin 6805 -> 0 bytes .../site-packages/httpx/_transports/asgi.py | 187 - .../site-packages/httpx/_transports/base.py | 86 - .../httpx/_transports/default.py | 406 - .../site-packages/httpx/_transports/mock.py | 43 - .../site-packages/httpx/_transports/wsgi.py | 149 - .../python3.12/site-packages/httpx/_types.py | 114 - .../site-packages/httpx/_urlparse.py | 527 - .../python3.12/site-packages/httpx/_urls.py | 641 -- .../python3.12/site-packages/httpx/_utils.py | 242 - .../python3.12/site-packages/httpx/py.typed | 0 .../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 - .../python3.12/site-packages/idna/__init__.py | 45 - .../idna/__pycache__/__init__.cpython-312.pyc | Bin 872 -> 0 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 4972 -> 0 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 876 -> 0 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 16162 -> 0 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 99462 -> 0 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 2624 -> 0 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 203 -> 0 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 158832 -> 0 bytes .../python3.12/site-packages/idna/codec.py | 122 - .../python3.12/site-packages/idna/compat.py | 15 - .../lib/python3.12/site-packages/idna/core.py | 437 - .../python3.12/site-packages/idna/idnadata.py | 4243 -------- .../site-packages/idna/intranges.py | 57 - .../site-packages/idna/package_data.py | 1 - .../python3.12/site-packages/idna/py.typed | 0 .../site-packages/idna/uts46data.py | 8681 ----------------- .../mistralai-1.6.0.dist-info/INSTALLER | 1 - .../mistralai-1.6.0.dist-info/LICENSE | 201 - .../mistralai-1.6.0.dist-info/METADATA | 899 -- .../mistralai-1.6.0.dist-info/RECORD | 606 -- .../mistralai-1.6.0.dist-info/REQUESTED | 0 .../mistralai-1.6.0.dist-info/WHEEL | 4 - .../site-packages/mistralai/__init__.py | 18 - .../__pycache__/__init__.cpython-312.pyc | Bin 653 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 907 -> 0 bytes .../__pycache__/agents.cpython-312.pyc | Bin 26610 -> 0 bytes .../__pycache__/async_client.cpython-312.pyc | Bin 892 -> 0 bytes .../__pycache__/basesdk.cpython-312.pyc | Bin 11484 -> 0 bytes .../__pycache__/batch.cpython-312.pyc | Bin 1168 -> 0 bytes .../__pycache__/chat.cpython-312.pyc | Bin 33093 -> 0 bytes .../__pycache__/classifiers.cpython-312.pyc | Bin 16094 -> 0 bytes .../__pycache__/client.cpython-312.pyc | Bin 1018 -> 0 bytes .../__pycache__/embeddings.cpython-312.pyc | Bin 8622 -> 0 bytes .../__pycache__/files.cpython-312.pyc | Bin 37421 -> 0 bytes .../mistralai/__pycache__/fim.cpython-312.pyc | Bin 21545 -> 0 bytes .../__pycache__/fine_tuning.cpython-312.pyc | Bin 1173 -> 0 bytes .../__pycache__/httpclient.cpython-312.pyc | Bin 6299 -> 0 bytes .../__pycache__/jobs.cpython-312.pyc | Bin 35649 -> 0 bytes .../__pycache__/mistral_jobs.cpython-312.pyc | Bin 25986 -> 0 bytes .../__pycache__/models_.cpython-312.pyc | Bin 37734 -> 0 bytes .../mistralai/__pycache__/ocr.cpython-312.pyc | Bin 9658 -> 0 bytes .../mistralai/__pycache__/sdk.cpython-312.pyc | Bin 7933 -> 0 bytes .../sdkconfiguration.cpython-312.pyc | Bin 3268 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 427 -> 0 bytes .../mistralai/_hooks/__init__.py | 5 - .../__pycache__/__init__.cpython-312.pyc | Bin 346 -> 0 bytes .../custom_user_agent.cpython-312.pyc | Bin 1182 -> 0 bytes .../deprecation_warning.cpython-312.pyc | Bin 1464 -> 0 bytes .../__pycache__/registration.cpython-312.pyc | Bin 958 -> 0 bytes .../__pycache__/sdkhooks.cpython-312.pyc | Bin 4175 -> 0 bytes .../_hooks/__pycache__/types.cpython-312.pyc | Bin 5639 -> 0 bytes .../mistralai/_hooks/custom_user_agent.py | 22 - .../mistralai/_hooks/deprecation_warning.py | 26 - .../mistralai/_hooks/registration.py | 17 - .../mistralai/_hooks/sdkhooks.py | 76 - .../site-packages/mistralai/_hooks/types.py | 106 - .../site-packages/mistralai/_version.py | 15 - .../site-packages/mistralai/agents.py | 692 -- .../site-packages/mistralai/async_client.py | 15 - .../site-packages/mistralai/basesdk.py | 362 - .../site-packages/mistralai/batch.py | 17 - .../site-packages/mistralai/chat.py | 790 -- .../site-packages/mistralai/classifiers.py | 442 - .../site-packages/mistralai/client.py | 14 - .../site-packages/mistralai/embeddings.py | 222 - .../site-packages/mistralai/extra/README.md | 56 - .../site-packages/mistralai/extra/__init__.py | 5 - .../__pycache__/__init__.cpython-312.pyc | Bin 484 -> 0 bytes .../__pycache__/struct_chat.cpython-312.pyc | Bin 2843 -> 0 bytes .../mistralai/extra/struct_chat.py | 41 - .../mistralai/extra/tests/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 191 -> 0 bytes .../test_struct_chat.cpython-312.pyc | Bin 3627 -> 0 bytes .../__pycache__/test_utils.cpython-312.pyc | Bin 4822 -> 0 bytes .../mistralai/extra/tests/test_struct_chat.py | 103 - .../mistralai/extra/tests/test_utils.py | 162 - .../mistralai/extra/utils/__init__.py | 3 - .../__pycache__/__init__.cpython-312.pyc | Bin 297 -> 0 bytes .../_pydantic_helper.cpython-312.pyc | Bin 1242 -> 0 bytes .../response_format.cpython-312.pyc | Bin 1438 -> 0 bytes .../mistralai/extra/utils/_pydantic_helper.py | 20 - .../mistralai/extra/utils/response_format.py | 24 - .../site-packages/mistralai/files.py | 1191 --- .../python3.12/site-packages/mistralai/fim.py | 560 -- .../site-packages/mistralai/fine_tuning.py | 17 - .../site-packages/mistralai/httpclient.py | 136 - .../site-packages/mistralai/jobs.py | 1081 -- .../site-packages/mistralai/mistral_jobs.py | 821 -- .../mistralai/models/__init__.py | 679 -- .../__pycache__/__init__.cpython-312.pyc | Bin 17909 -> 0 bytes .../agentscompletionrequest.cpython-312.pyc | Bin 5585 -> 0 bytes ...ntscompletionstreamrequest.cpython-312.pyc | Bin 5666 -> 0 bytes .../__pycache__/apiendpoint.cpython-312.pyc | Bin 600 -> 0 bytes .../archiveftmodelout.cpython-312.pyc | Bin 1471 -> 0 bytes .../assistantmessage.cpython-312.pyc | Bin 3118 -> 0 bytes .../__pycache__/basemodelcard.cpython-312.pyc | Bin 3637 -> 0 bytes .../__pycache__/batcherror.cpython-312.pyc | Bin 999 -> 0 bytes .../__pycache__/batchjobin.cpython-312.pyc | Bin 2739 -> 0 bytes .../__pycache__/batchjobout.cpython-312.pyc | Bin 3814 -> 0 bytes .../__pycache__/batchjobsout.cpython-312.pyc | Bin 1577 -> 0 bytes .../batchjobstatus.cpython-312.pyc | Bin 495 -> 0 bytes .../chatcompletionchoice.cpython-312.pyc | Bin 1474 -> 0 bytes .../chatcompletionrequest.cpython-312.pyc | Bin 5674 -> 0 bytes .../chatcompletionresponse.cpython-312.pyc | Bin 1513 -> 0 bytes ...hatcompletionstreamrequest.cpython-312.pyc | Bin 5937 -> 0 bytes .../chatmoderationrequest.cpython-312.pyc | Bin 2942 -> 0 bytes .../__pycache__/checkpointout.cpython-312.pyc | Bin 1057 -> 0 bytes .../classificationobject.cpython-312.pyc | Bin 1158 -> 0 bytes .../classificationrequest.cpython-312.pyc | Bin 1339 -> 0 bytes .../classificationresponse.cpython-312.pyc | Bin 1304 -> 0 bytes .../completionchunk.cpython-312.pyc | Bin 1615 -> 0 bytes .../completionevent.cpython-312.pyc | Bin 935 -> 0 bytes ...letionresponsestreamchoice.cpython-312.pyc | Bin 2755 -> 0 bytes .../__pycache__/contentchunk.cpython-312.pyc | Bin 1429 -> 0 bytes ...1_models_model_id_deleteop.cpython-312.pyc | Bin 1110 -> 0 bytes .../__pycache__/deletefileout.cpython-312.pyc | Bin 953 -> 0 bytes .../deletemodelout.cpython-312.pyc | Bin 1130 -> 0 bytes .../__pycache__/deltamessage.cpython-312.pyc | Bin 2787 -> 0 bytes .../detailedjobout.cpython-312.pyc | Bin 5175 -> 0 bytes .../documenturlchunk.cpython-312.pyc | Bin 2432 -> 0 bytes .../embeddingrequest.cpython-312.pyc | Bin 1250 -> 0 bytes .../embeddingresponse.cpython-312.pyc | Bin 1313 -> 0 bytes .../embeddingresponsedata.cpython-312.pyc | Bin 1190 -> 0 bytes .../__pycache__/eventout.cpython-312.pyc | Bin 2277 -> 0 bytes .../__pycache__/filepurpose.cpython-312.pyc | Bin 513 -> 0 bytes ...s_api_routes_delete_fileop.cpython-312.pyc | Bin 1075 -> 0 bytes ...api_routes_download_fileop.cpython-312.pyc | Bin 1081 -> 0 bytes ...pi_routes_get_signed_urlop.cpython-312.pyc | Bin 1395 -> 0 bytes ...es_api_routes_list_filesop.cpython-312.pyc | Bin 3795 -> 0 bytes ...api_routes_retrieve_fileop.cpython-312.pyc | Bin 1081 -> 0 bytes ...s_api_routes_upload_fileop.cpython-312.pyc | Bin 2487 -> 0 bytes .../__pycache__/fileschema.cpython-312.pyc | Bin 3076 -> 0 bytes .../__pycache__/filesignedurl.cpython-312.pyc | Bin 823 -> 0 bytes .../fimcompletionrequest.cpython-312.pyc | Bin 3449 -> 0 bytes .../fimcompletionresponse.cpython-312.pyc | Bin 1510 -> 0 bytes ...fimcompletionstreamrequest.cpython-312.pyc | Bin 3481 -> 0 bytes .../ftmodelcapabilitiesout.cpython-312.pyc | Bin 1188 -> 0 bytes .../__pycache__/ftmodelcard.cpython-312.pyc | Bin 3913 -> 0 bytes .../__pycache__/ftmodelout.cpython-312.pyc | Bin 3361 -> 0 bytes .../__pycache__/function.cpython-312.pyc | Bin 1186 -> 0 bytes .../__pycache__/functioncall.cpython-312.pyc | Bin 1167 -> 0 bytes .../__pycache__/functionname.cpython-312.pyc | Bin 920 -> 0 bytes .../githubrepositoryin.cpython-312.pyc | Bin 2847 -> 0 bytes .../githubrepositoryout.cpython-312.pyc | Bin 2857 -> 0 bytes .../httpvalidationerror.cpython-312.pyc | Bin 1463 -> 0 bytes .../__pycache__/imageurl.cpython-312.pyc | Bin 2129 -> 0 bytes .../__pycache__/imageurlchunk.cpython-312.pyc | Bin 1510 -> 0 bytes .../models/__pycache__/jobin.cpython-312.pyc | Bin 3567 -> 0 bytes .../jobmetadataout.cpython-312.pyc | Bin 2668 -> 0 bytes .../models/__pycache__/jobout.cpython-312.pyc | Bin 4682 -> 0 bytes ...s_batch_cancel_batch_jobop.cpython-312.pyc | Bin 1100 -> 0 bytes ...utes_batch_get_batch_jobop.cpython-312.pyc | Bin 1091 -> 0 bytes ...tes_batch_get_batch_jobsop.cpython-312.pyc | Bin 3727 -> 0 bytes ...archive_fine_tuned_modelop.cpython-312.pyc | Bin 1148 -> 0 bytes ...g_cancel_fine_tuning_jobop.cpython-312.pyc | Bin 1140 -> 0 bytes ...g_create_fine_tuning_jobop.cpython-312.pyc | Bin 883 -> 0 bytes ...ning_get_fine_tuning_jobop.cpython-312.pyc | Bin 1131 -> 0 bytes ...ing_get_fine_tuning_jobsop.cpython-312.pyc | Bin 4002 -> 0 bytes ...ng_start_fine_tuning_jobop.cpython-312.pyc | Bin 1129 -> 0 bytes ...archive_fine_tuned_modelop.cpython-312.pyc | Bin 1154 -> 0 bytes ..._update_fine_tuned_modelop.cpython-312.pyc | Bin 1439 -> 0 bytes .../__pycache__/jobsout.cpython-312.pyc | Bin 1526 -> 0 bytes .../__pycache__/jsonschema.cpython-312.pyc | Bin 2483 -> 0 bytes .../legacyjobmetadataout.cpython-312.pyc | Bin 3630 -> 0 bytes .../__pycache__/listfilesout.cpython-312.pyc | Bin 1087 -> 0 bytes .../__pycache__/metricout.cpython-312.pyc | Bin 2454 -> 0 bytes .../modelcapabilities.cpython-312.pyc | Bin 1231 -> 0 bytes .../__pycache__/modellist.cpython-312.pyc | Bin 1812 -> 0 bytes .../ocrimageobject.cpython-312.pyc | Bin 2472 -> 0 bytes .../ocrpagedimensions.cpython-312.pyc | Bin 953 -> 0 bytes .../__pycache__/ocrpageobject.cpython-312.pyc | Bin 2500 -> 0 bytes .../__pycache__/ocrrequest.cpython-312.pyc | Bin 3165 -> 0 bytes .../__pycache__/ocrresponse.cpython-312.pyc | Bin 1208 -> 0 bytes .../__pycache__/ocrusageinfo.cpython-312.pyc | Bin 2187 -> 0 bytes .../__pycache__/prediction.cpython-312.pyc | Bin 1345 -> 0 bytes .../referencechunk.cpython-312.pyc | Bin 1145 -> 0 bytes .../responseformat.cpython-312.pyc | Bin 2448 -> 0 bytes .../responseformats.cpython-312.pyc | Bin 444 -> 0 bytes ...l_v1_models_model_id_getop.cpython-312.pyc | Bin 1973 -> 0 bytes .../retrievefileout.cpython-312.pyc | Bin 3151 -> 0 bytes .../__pycache__/sampletype.cpython-312.pyc | Bin 556 -> 0 bytes .../__pycache__/sdkerror.cpython-312.pyc | Bin 1247 -> 0 bytes .../__pycache__/security.cpython-312.pyc | Bin 1183 -> 0 bytes .../models/__pycache__/source.cpython-312.pyc | Bin 509 -> 0 bytes .../__pycache__/systemmessage.cpython-312.pyc | Bin 1406 -> 0 bytes .../__pycache__/textchunk.cpython-312.pyc | Bin 1067 -> 0 bytes .../models/__pycache__/tool.cpython-312.pyc | Bin 1318 -> 0 bytes .../__pycache__/toolcall.cpython-312.pyc | Bin 1537 -> 0 bytes .../__pycache__/toolchoice.cpython-312.pyc | Bin 1447 -> 0 bytes .../toolchoiceenum.cpython-312.pyc | Bin 431 -> 0 bytes .../__pycache__/toolmessage.cpython-312.pyc | Bin 2864 -> 0 bytes .../__pycache__/tooltypes.cpython-312.pyc | Bin 493 -> 0 bytes .../__pycache__/trainingfile.cpython-312.pyc | Bin 1010 -> 0 bytes .../trainingparameters.cpython-312.pyc | Bin 2717 -> 0 bytes .../trainingparametersin.cpython-312.pyc | Bin 2886 -> 0 bytes .../unarchiveftmodelout.cpython-312.pyc | Bin 1481 -> 0 bytes .../updateftmodelin.cpython-312.pyc | Bin 2184 -> 0 bytes .../__pycache__/uploadfileout.cpython-312.pyc | Bin 3088 -> 0 bytes .../__pycache__/usageinfo.cpython-312.pyc | Bin 937 -> 0 bytes .../__pycache__/usermessage.cpython-312.pyc | Bin 2619 -> 0 bytes .../validationerror.cpython-312.pyc | Bin 1164 -> 0 bytes .../wandbintegration.cpython-312.pyc | Bin 2798 -> 0 bytes .../wandbintegrationout.cpython-312.pyc | Bin 2762 -> 0 bytes .../models/agentscompletionrequest.py | 170 - .../models/agentscompletionstreamrequest.py | 168 - .../mistralai/models/apiendpoint.py | 17 - .../mistralai/models/archiveftmodelout.py | 31 - .../mistralai/models/assistantmessage.py | 71 - .../mistralai/models/basemodelcard.py | 105 - .../mistralai/models/batcherror.py | 17 - .../mistralai/models/batchjobin.py | 60 - .../mistralai/models/batchjobout.py | 117 - .../mistralai/models/batchjobsout.py | 30 - .../mistralai/models/batchjobstatus.py | 15 - .../mistralai/models/chatcompletionchoice.py | 28 - .../mistralai/models/chatcompletionrequest.py | 184 - .../models/chatcompletionresponse.py | 31 - .../models/chatcompletionstreamrequest.py | 186 - .../mistralai/models/chatmoderationrequest.py | 86 - .../mistralai/models/checkpointout.py | 26 - .../mistralai/models/classificationobject.py | 21 - .../mistralai/models/classificationrequest.py | 34 - .../models/classificationresponse.py | 21 - .../mistralai/models/completionchunk.py | 34 - .../mistralai/models/completionevent.py | 14 - .../models/completionresponsestreamchoice.py | 62 - .../mistralai/models/contentchunk.py | 33 - ...elete_model_v1_models_model_id_deleteop.py | 18 - .../mistralai/models/deletefileout.py | 25 - .../mistralai/models/deletemodelout.py | 26 - .../mistralai/models/deltamessage.py | 61 - .../mistralai/models/detailedjobout.py | 162 - .../mistralai/models/documenturlchunk.py | 56 - .../mistralai/models/embeddingrequest.py | 30 - .../mistralai/models/embeddingresponse.py | 28 - .../mistralai/models/embeddingresponsedata.py | 20 - .../mistralai/models/eventout.py | 55 - .../mistralai/models/filepurpose.py | 8 - .../models/files_api_routes_delete_fileop.py | 16 - .../files_api_routes_download_fileop.py | 16 - .../files_api_routes_get_signed_urlop.py | 25 - .../models/files_api_routes_list_filesop.py | 96 - .../files_api_routes_retrieve_fileop.py | 16 - .../models/files_api_routes_upload_fileop.py | 69 - .../mistralai/models/fileschema.py | 84 - .../mistralai/models/filesignedurl.py | 13 - .../mistralai/models/fimcompletionrequest.py | 125 - .../mistralai/models/fimcompletionresponse.py | 31 - .../models/fimcompletionstreamrequest.py | 123 - .../models/ftmodelcapabilitiesout.py | 23 - .../mistralai/models/ftmodelcard.py | 121 - .../mistralai/models/ftmodelout.py | 97 - .../mistralai/models/function.py | 23 - .../mistralai/models/functioncall.py | 23 - .../mistralai/models/functionname.py | 17 - .../mistralai/models/githubrepositoryin.py | 71 - .../mistralai/models/githubrepositoryout.py | 71 - .../mistralai/models/httpvalidationerror.py | 21 - .../mistralai/models/imageurl.py | 47 - .../mistralai/models/imageurlchunk.py | 33 - .../site-packages/mistralai/models/jobin.py | 101 - .../mistralai/models/jobmetadataout.py | 78 - .../site-packages/mistralai/models/jobout.py | 174 - ...obs_api_routes_batch_cancel_batch_jobop.py | 16 - .../jobs_api_routes_batch_get_batch_jobop.py | 16 - .../jobs_api_routes_batch_get_batch_jobsop.py | 95 - ..._fine_tuning_archive_fine_tuned_modelop.py | 18 - ...es_fine_tuning_cancel_fine_tuning_jobop.py | 18 - ...es_fine_tuning_create_fine_tuning_jobop.py | 21 - ...outes_fine_tuning_get_fine_tuning_jobop.py | 18 - ...utes_fine_tuning_get_fine_tuning_jobsop.py | 148 - ...tes_fine_tuning_start_fine_tuning_jobop.py | 16 - ...ine_tuning_unarchive_fine_tuned_modelop.py | 18 - ...s_fine_tuning_update_fine_tuned_modelop.py | 25 - .../site-packages/mistralai/models/jobsout.py | 30 - .../mistralai/models/jsonschema.py | 55 - .../mistralai/models/legacyjobmetadataout.py | 128 - .../mistralai/models/listfilesout.py | 21 - .../mistralai/models/metricout.py | 54 - .../mistralai/models/modelcapabilities.py | 26 - .../mistralai/models/modellist.py | 34 - .../mistralai/models/ocrimageobject.py | 77 - .../mistralai/models/ocrpagedimensions.py | 25 - .../mistralai/models/ocrpageobject.py | 64 - .../mistralai/models/ocrrequest.py | 97 - .../mistralai/models/ocrresponse.py | 26 - .../mistralai/models/ocrusageinfo.py | 51 - .../mistralai/models/prediction.py | 25 - .../mistralai/models/referencechunk.py | 20 - .../mistralai/models/responseformat.py | 52 - .../mistralai/models/responseformats.py | 8 - ...retrieve_model_v1_models_model_id_getop.py | 38 - .../mistralai/models/retrievefileout.py | 87 - .../mistralai/models/sampletype.py | 11 - .../mistralai/models/sdkerror.py | 22 - .../mistralai/models/security.py | 25 - .../site-packages/mistralai/models/source.py | 8 - .../mistralai/models/systemmessage.py | 31 - .../mistralai/models/textchunk.py | 20 - .../site-packages/mistralai/models/tool.py | 23 - .../mistralai/models/toolcall.py | 29 - .../mistralai/models/toolchoice.py | 29 - .../mistralai/models/toolchoiceenum.py | 7 - .../mistralai/models/toolmessage.py | 66 - .../mistralai/models/tooltypes.py | 8 - .../mistralai/models/trainingfile.py | 17 - .../mistralai/models/trainingparameters.py | 78 - .../mistralai/models/trainingparametersin.py | 90 - .../mistralai/models/unarchiveftmodelout.py | 31 - .../mistralai/models/updateftmodelin.py | 47 - .../mistralai/models/uploadfileout.py | 84 - .../mistralai/models/usageinfo.py | 19 - .../mistralai/models/usermessage.py | 60 - .../mistralai/models/validationerror.py | 26 - .../mistralai/models/wandbintegration.py | 74 - .../mistralai/models/wandbintegrationout.py | 69 - .../site-packages/mistralai/models_.py | 1178 --- .../python3.12/site-packages/mistralai/ocr.py | 248 - .../site-packages/mistralai/py.typed | 1 - .../python3.12/site-packages/mistralai/sdk.py | 175 - .../mistralai/sdkconfiguration.py | 60 - .../site-packages/mistralai/types/__init__.py | 21 - .../__pycache__/__init__.cpython-312.pyc | Bin 489 -> 0 bytes .../__pycache__/basemodel.cpython-312.pyc | Bin 1980 -> 0 bytes .../mistralai/types/basemodel.py | 39 - .../site-packages/mistralai/utils/__init__.py | 101 - .../__pycache__/__init__.cpython-312.pyc | Bin 2169 -> 0 bytes .../__pycache__/annotations.cpython-312.pyc | Bin 2169 -> 0 bytes .../utils/__pycache__/enums.cpython-312.pyc | Bin 1082 -> 0 bytes .../eventstreaming.cpython-312.pyc | Bin 8330 -> 0 bytes .../utils/__pycache__/forms.cpython-312.pyc | Bin 6297 -> 0 bytes .../utils/__pycache__/headers.cpython-312.pyc | Bin 4484 -> 0 bytes .../utils/__pycache__/logger.cpython-312.pyc | Bin 1808 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 5523 -> 0 bytes .../__pycache__/queryparams.cpython-312.pyc | Bin 6231 -> 0 bytes .../__pycache__/requestbodies.cpython-312.pyc | Bin 2668 -> 0 bytes .../utils/__pycache__/retries.cpython-312.pyc | Bin 8728 -> 0 bytes .../__pycache__/security.cpython-312.pyc | Bin 6432 -> 0 bytes .../__pycache__/serializers.cpython-312.pyc | Bin 8930 -> 0 bytes .../utils/__pycache__/url.cpython-312.pyc | Bin 5472 -> 0 bytes .../utils/__pycache__/values.cpython-312.pyc | Bin 5273 -> 0 bytes .../mistralai/utils/annotations.py | 55 - .../site-packages/mistralai/utils/enums.py | 34 - .../mistralai/utils/eventstreaming.py | 238 - .../site-packages/mistralai/utils/forms.py | 202 - .../site-packages/mistralai/utils/headers.py | 136 - .../site-packages/mistralai/utils/logger.py | 27 - .../site-packages/mistralai/utils/metadata.py | 118 - .../mistralai/utils/queryparams.py | 205 - .../mistralai/utils/requestbodies.py | 66 - .../site-packages/mistralai/utils/retries.py | 217 - .../site-packages/mistralai/utils/security.py | 192 - .../mistralai/utils/serializers.py | 219 - .../site-packages/mistralai/utils/url.py | 155 - .../site-packages/mistralai/utils/values.py | 137 - .../site-packages/mistralai/version.py | 7 - .../site-packages/mistralai_azure/__init__.py | 18 - .../__pycache__/__init__.cpython-312.pyc | Bin 659 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 925 -> 0 bytes .../__pycache__/basesdk.cpython-312.pyc | Bin 11376 -> 0 bytes .../__pycache__/chat.cpython-312.pyc | Bin 29263 -> 0 bytes .../__pycache__/httpclient.cpython-312.pyc | Bin 6305 -> 0 bytes .../__pycache__/sdk.cpython-312.pyc | Bin 6603 -> 0 bytes .../sdkconfiguration.cpython-312.pyc | Bin 3286 -> 0 bytes .../mistralai_azure/_hooks/__init__.py | 5 - .../__pycache__/__init__.cpython-312.pyc | Bin 352 -> 0 bytes .../custom_user_agent.cpython-312.pyc | Bin 1188 -> 0 bytes .../__pycache__/registration.cpython-312.pyc | Bin 793 -> 0 bytes .../__pycache__/sdkhooks.cpython-312.pyc | Bin 4187 -> 0 bytes .../_hooks/__pycache__/types.cpython-312.pyc | Bin 5651 -> 0 bytes .../_hooks/custom_user_agent.py | 22 - .../mistralai_azure/_hooks/registration.py | 15 - .../mistralai_azure/_hooks/sdkhooks.py | 76 - .../mistralai_azure/_hooks/types.py | 106 - .../site-packages/mistralai_azure/_version.py | 15 - .../site-packages/mistralai_azure/basesdk.py | 362 - .../site-packages/mistralai_azure/chat.py | 704 -- .../mistralai_azure/httpclient.py | 136 - .../mistralai_azure/models/__init__.py | 210 - .../__pycache__/__init__.cpython-312.pyc | Bin 4891 -> 0 bytes .../assistantmessage.cpython-312.pyc | Bin 3136 -> 0 bytes .../chatcompletionchoice.cpython-312.pyc | Bin 1535 -> 0 bytes .../chatcompletionrequest.cpython-312.pyc | Bin 5928 -> 0 bytes .../chatcompletionresponse.cpython-312.pyc | Bin 1525 -> 0 bytes ...hatcompletionstreamrequest.cpython-312.pyc | Bin 5775 -> 0 bytes .../completionchunk.cpython-312.pyc | Bin 1627 -> 0 bytes .../completionevent.cpython-312.pyc | Bin 947 -> 0 bytes ...letionresponsestreamchoice.cpython-312.pyc | Bin 2677 -> 0 bytes .../__pycache__/contentchunk.cpython-312.pyc | Bin 1281 -> 0 bytes .../__pycache__/deltamessage.cpython-312.pyc | Bin 2805 -> 0 bytes .../__pycache__/function.cpython-312.pyc | Bin 1198 -> 0 bytes .../__pycache__/functioncall.cpython-312.pyc | Bin 1179 -> 0 bytes .../__pycache__/functionname.cpython-312.pyc | Bin 932 -> 0 bytes .../httpvalidationerror.cpython-312.pyc | Bin 1481 -> 0 bytes .../__pycache__/imageurl.cpython-312.pyc | Bin 2147 -> 0 bytes .../__pycache__/imageurlchunk.cpython-312.pyc | Bin 1522 -> 0 bytes .../__pycache__/jsonschema.cpython-312.pyc | Bin 2501 -> 0 bytes .../__pycache__/prediction.cpython-312.pyc | Bin 1363 -> 0 bytes .../referencechunk.cpython-312.pyc | Bin 1157 -> 0 bytes .../responseformat.cpython-312.pyc | Bin 2466 -> 0 bytes .../responseformats.cpython-312.pyc | Bin 450 -> 0 bytes .../__pycache__/sdkerror.cpython-312.pyc | Bin 1253 -> 0 bytes .../__pycache__/security.cpython-312.pyc | Bin 1076 -> 0 bytes .../__pycache__/systemmessage.cpython-312.pyc | Bin 1418 -> 0 bytes .../__pycache__/textchunk.cpython-312.pyc | Bin 1051 -> 0 bytes .../models/__pycache__/tool.cpython-312.pyc | Bin 1336 -> 0 bytes .../__pycache__/toolcall.cpython-312.pyc | Bin 1555 -> 0 bytes .../__pycache__/toolchoice.cpython-312.pyc | Bin 1465 -> 0 bytes .../toolchoiceenum.cpython-312.pyc | Bin 437 -> 0 bytes .../__pycache__/toolmessage.cpython-312.pyc | Bin 2882 -> 0 bytes .../__pycache__/tooltypes.cpython-312.pyc | Bin 505 -> 0 bytes .../__pycache__/usageinfo.cpython-312.pyc | Bin 949 -> 0 bytes .../__pycache__/usermessage.cpython-312.pyc | Bin 2631 -> 0 bytes .../validationerror.cpython-312.pyc | Bin 1176 -> 0 bytes .../models/assistantmessage.py | 77 - .../models/chatcompletionchoice.py | 30 - .../models/chatcompletionrequest.py | 195 - .../models/chatcompletionresponse.py | 31 - .../models/chatcompletionstreamrequest.py | 189 - .../mistralai_azure/models/completionchunk.py | 34 - .../mistralai_azure/models/completionevent.py | 14 - .../models/completionresponsestreamchoice.py | 59 - .../mistralai_azure/models/contentchunk.py | 26 - .../mistralai_azure/models/deltamessage.py | 67 - .../mistralai_azure/models/function.py | 23 - .../mistralai_azure/models/functioncall.py | 23 - .../mistralai_azure/models/functionname.py | 17 - .../models/httpvalidationerror.py | 21 - .../mistralai_azure/models/imageurl.py | 53 - .../mistralai_azure/models/imageurlchunk.py | 33 - .../mistralai_azure/models/jsonschema.py | 61 - .../mistralai_azure/models/prediction.py | 25 - .../mistralai_azure/models/referencechunk.py | 20 - .../mistralai_azure/models/responseformat.py | 58 - .../mistralai_azure/models/responseformats.py | 8 - .../mistralai_azure/models/sdkerror.py | 22 - .../mistralai_azure/models/security.py | 24 - .../mistralai_azure/models/systemmessage.py | 31 - .../mistralai_azure/models/textchunk.py | 20 - .../mistralai_azure/models/tool.py | 23 - .../mistralai_azure/models/toolcall.py | 29 - .../mistralai_azure/models/toolchoice.py | 29 - .../mistralai_azure/models/toolchoiceenum.py | 7 - .../mistralai_azure/models/toolmessage.py | 72 - .../mistralai_azure/models/tooltypes.py | 8 - .../mistralai_azure/models/usageinfo.py | 19 - .../mistralai_azure/models/usermessage.py | 60 - .../mistralai_azure/models/validationerror.py | 26 - .../site-packages/mistralai_azure/py.typed | 1 - .../site-packages/mistralai_azure/sdk.py | 149 - .../mistralai_azure/sdkconfiguration.py | 60 - .../mistralai_azure/types/__init__.py | 21 - .../__pycache__/__init__.cpython-312.pyc | Bin 495 -> 0 bytes .../__pycache__/basemodel.cpython-312.pyc | Bin 1986 -> 0 bytes .../mistralai_azure/types/basemodel.py | 39 - .../mistralai_azure/utils/__init__.py | 99 - .../__pycache__/__init__.cpython-312.pyc | Bin 2138 -> 0 bytes .../__pycache__/annotations.cpython-312.pyc | Bin 2175 -> 0 bytes .../utils/__pycache__/enums.cpython-312.pyc | Bin 1088 -> 0 bytes .../eventstreaming.cpython-312.pyc | Bin 8336 -> 0 bytes .../utils/__pycache__/forms.cpython-312.pyc | Bin 6303 -> 0 bytes .../utils/__pycache__/headers.cpython-312.pyc | Bin 4490 -> 0 bytes .../utils/__pycache__/logger.cpython-312.pyc | Bin 1494 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 5529 -> 0 bytes .../__pycache__/queryparams.cpython-312.pyc | Bin 6237 -> 0 bytes .../__pycache__/requestbodies.cpython-312.pyc | Bin 2674 -> 0 bytes .../utils/__pycache__/retries.cpython-312.pyc | Bin 8734 -> 0 bytes .../__pycache__/security.cpython-312.pyc | Bin 5818 -> 0 bytes .../__pycache__/serializers.cpython-312.pyc | Bin 8936 -> 0 bytes .../utils/__pycache__/url.cpython-312.pyc | Bin 5478 -> 0 bytes .../utils/__pycache__/values.cpython-312.pyc | Bin 5279 -> 0 bytes .../mistralai_azure/utils/annotations.py | 55 - .../mistralai_azure/utils/enums.py | 34 - .../mistralai_azure/utils/eventstreaming.py | 238 - .../mistralai_azure/utils/forms.py | 202 - .../mistralai_azure/utils/headers.py | 136 - .../mistralai_azure/utils/logger.py | 22 - .../mistralai_azure/utils/metadata.py | 118 - .../mistralai_azure/utils/queryparams.py | 205 - .../mistralai_azure/utils/requestbodies.py | 66 - .../mistralai_azure/utils/retries.py | 217 - .../mistralai_azure/utils/security.py | 174 - .../mistralai_azure/utils/serializers.py | 219 - .../mistralai_azure/utils/url.py | 155 - .../mistralai_azure/utils/values.py | 137 - .../site-packages/mistralai_gcp/__init__.py | 18 - .../__pycache__/__init__.cpython-312.pyc | Bin 657 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 919 -> 0 bytes .../__pycache__/basesdk.cpython-312.pyc | Bin 11368 -> 0 bytes .../__pycache__/chat.cpython-312.pyc | Bin 29101 -> 0 bytes .../__pycache__/fim.cpython-312.pyc | Bin 21337 -> 0 bytes .../__pycache__/httpclient.cpython-312.pyc | Bin 6303 -> 0 bytes .../__pycache__/sdk.cpython-312.pyc | Bin 10870 -> 0 bytes .../sdkconfiguration.cpython-312.pyc | Bin 3280 -> 0 bytes .../mistralai_gcp/_hooks/__init__.py | 5 - .../__pycache__/__init__.cpython-312.pyc | Bin 350 -> 0 bytes .../custom_user_agent.cpython-312.pyc | Bin 1186 -> 0 bytes .../__pycache__/registration.cpython-312.pyc | Bin 791 -> 0 bytes .../__pycache__/sdkhooks.cpython-312.pyc | Bin 4183 -> 0 bytes .../_hooks/__pycache__/types.cpython-312.pyc | Bin 5647 -> 0 bytes .../mistralai_gcp/_hooks/custom_user_agent.py | 22 - .../mistralai_gcp/_hooks/registration.py | 15 - .../mistralai_gcp/_hooks/sdkhooks.py | 76 - .../mistralai_gcp/_hooks/types.py | 106 - .../site-packages/mistralai_gcp/_version.py | 15 - .../site-packages/mistralai_gcp/basesdk.py | 362 - .../site-packages/mistralai_gcp/chat.py | 692 -- .../site-packages/mistralai_gcp/fim.py | 556 -- .../site-packages/mistralai_gcp/httpclient.py | 136 - .../mistralai_gcp/models/__init__.py | 233 - .../__pycache__/__init__.cpython-312.pyc | Bin 5467 -> 0 bytes .../assistantmessage.cpython-312.pyc | Bin 3132 -> 0 bytes .../chatcompletionchoice.cpython-312.pyc | Bin 1529 -> 0 bytes .../chatcompletionrequest.cpython-312.pyc | Bin 5797 -> 0 bytes .../chatcompletionresponse.cpython-312.pyc | Bin 1521 -> 0 bytes ...hatcompletionstreamrequest.cpython-312.pyc | Bin 5645 -> 0 bytes .../completionchunk.cpython-312.pyc | Bin 1623 -> 0 bytes .../completionevent.cpython-312.pyc | Bin 943 -> 0 bytes ...letionresponsestreamchoice.cpython-312.pyc | Bin 2671 -> 0 bytes .../__pycache__/contentchunk.cpython-312.pyc | Bin 1277 -> 0 bytes .../__pycache__/deltamessage.cpython-312.pyc | Bin 2801 -> 0 bytes .../fimcompletionrequest.cpython-312.pyc | Bin 3463 -> 0 bytes .../fimcompletionresponse.cpython-312.pyc | Bin 1518 -> 0 bytes ...fimcompletionstreamrequest.cpython-312.pyc | Bin 3495 -> 0 bytes .../__pycache__/function.cpython-312.pyc | Bin 1194 -> 0 bytes .../__pycache__/functioncall.cpython-312.pyc | Bin 1175 -> 0 bytes .../__pycache__/functionname.cpython-312.pyc | Bin 928 -> 0 bytes .../httpvalidationerror.cpython-312.pyc | Bin 1475 -> 0 bytes .../__pycache__/imageurl.cpython-312.pyc | Bin 2143 -> 0 bytes .../__pycache__/imageurlchunk.cpython-312.pyc | Bin 1518 -> 0 bytes .../__pycache__/jsonschema.cpython-312.pyc | Bin 2497 -> 0 bytes .../__pycache__/prediction.cpython-312.pyc | Bin 1357 -> 0 bytes .../referencechunk.cpython-312.pyc | Bin 1153 -> 0 bytes .../responseformat.cpython-312.pyc | Bin 2462 -> 0 bytes .../responseformats.cpython-312.pyc | Bin 448 -> 0 bytes .../__pycache__/sdkerror.cpython-312.pyc | Bin 1251 -> 0 bytes .../__pycache__/security.cpython-312.pyc | Bin 1070 -> 0 bytes .../__pycache__/systemmessage.cpython-312.pyc | Bin 1414 -> 0 bytes .../__pycache__/textchunk.cpython-312.pyc | Bin 1047 -> 0 bytes .../models/__pycache__/tool.cpython-312.pyc | Bin 1330 -> 0 bytes .../__pycache__/toolcall.cpython-312.pyc | Bin 1549 -> 0 bytes .../__pycache__/toolchoice.cpython-312.pyc | Bin 1459 -> 0 bytes .../toolchoiceenum.cpython-312.pyc | Bin 435 -> 0 bytes .../__pycache__/toolmessage.cpython-312.pyc | Bin 2878 -> 0 bytes .../__pycache__/tooltypes.cpython-312.pyc | Bin 501 -> 0 bytes .../__pycache__/usageinfo.cpython-312.pyc | Bin 945 -> 0 bytes .../__pycache__/usermessage.cpython-312.pyc | Bin 2627 -> 0 bytes .../validationerror.cpython-312.pyc | Bin 1172 -> 0 bytes .../mistralai_gcp/models/assistantmessage.py | 77 - .../models/chatcompletionchoice.py | 30 - .../models/chatcompletionrequest.py | 188 - .../models/chatcompletionresponse.py | 31 - .../models/chatcompletionstreamrequest.py | 182 - .../mistralai_gcp/models/completionchunk.py | 34 - .../mistralai_gcp/models/completionevent.py | 14 - .../models/completionresponsestreamchoice.py | 59 - .../mistralai_gcp/models/contentchunk.py | 26 - .../mistralai_gcp/models/deltamessage.py | 67 - .../models/fimcompletionrequest.py | 131 - .../models/fimcompletionresponse.py | 31 - .../models/fimcompletionstreamrequest.py | 129 - .../mistralai_gcp/models/function.py | 23 - .../mistralai_gcp/models/functioncall.py | 23 - .../mistralai_gcp/models/functionname.py | 17 - .../models/httpvalidationerror.py | 21 - .../mistralai_gcp/models/imageurl.py | 53 - .../mistralai_gcp/models/imageurlchunk.py | 33 - .../mistralai_gcp/models/jsonschema.py | 61 - .../mistralai_gcp/models/prediction.py | 25 - .../mistralai_gcp/models/referencechunk.py | 20 - .../mistralai_gcp/models/responseformat.py | 58 - .../mistralai_gcp/models/responseformats.py | 8 - .../mistralai_gcp/models/sdkerror.py | 22 - .../mistralai_gcp/models/security.py | 24 - .../mistralai_gcp/models/systemmessage.py | 31 - .../mistralai_gcp/models/textchunk.py | 20 - .../mistralai_gcp/models/tool.py | 23 - .../mistralai_gcp/models/toolcall.py | 29 - .../mistralai_gcp/models/toolchoice.py | 29 - .../mistralai_gcp/models/toolchoiceenum.py | 7 - .../mistralai_gcp/models/toolmessage.py | 72 - .../mistralai_gcp/models/tooltypes.py | 8 - .../mistralai_gcp/models/usageinfo.py | 19 - .../mistralai_gcp/models/usermessage.py | 60 - .../mistralai_gcp/models/validationerror.py | 26 - .../site-packages/mistralai_gcp/py.typed | 1 - .../site-packages/mistralai_gcp/sdk.py | 231 - .../mistralai_gcp/sdkconfiguration.py | 60 - .../mistralai_gcp/types/__init__.py | 21 - .../__pycache__/__init__.cpython-312.pyc | Bin 493 -> 0 bytes .../__pycache__/basemodel.cpython-312.pyc | Bin 1984 -> 0 bytes .../mistralai_gcp/types/basemodel.py | 39 - .../mistralai_gcp/utils/__init__.py | 99 - .../__pycache__/__init__.cpython-312.pyc | Bin 2136 -> 0 bytes .../__pycache__/annotations.cpython-312.pyc | Bin 2173 -> 0 bytes .../utils/__pycache__/enums.cpython-312.pyc | Bin 1086 -> 0 bytes .../eventstreaming.cpython-312.pyc | Bin 8334 -> 0 bytes .../utils/__pycache__/forms.cpython-312.pyc | Bin 6301 -> 0 bytes .../utils/__pycache__/headers.cpython-312.pyc | Bin 4488 -> 0 bytes .../utils/__pycache__/logger.cpython-312.pyc | Bin 1492 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 5527 -> 0 bytes .../__pycache__/queryparams.cpython-312.pyc | Bin 6235 -> 0 bytes .../__pycache__/requestbodies.cpython-312.pyc | Bin 2672 -> 0 bytes .../utils/__pycache__/retries.cpython-312.pyc | Bin 8732 -> 0 bytes .../__pycache__/security.cpython-312.pyc | Bin 5816 -> 0 bytes .../__pycache__/serializers.cpython-312.pyc | Bin 8934 -> 0 bytes .../utils/__pycache__/url.cpython-312.pyc | Bin 5476 -> 0 bytes .../utils/__pycache__/values.cpython-312.pyc | Bin 5277 -> 0 bytes .../mistralai_gcp/utils/annotations.py | 55 - .../mistralai_gcp/utils/enums.py | 34 - .../mistralai_gcp/utils/eventstreaming.py | 238 - .../mistralai_gcp/utils/forms.py | 202 - .../mistralai_gcp/utils/headers.py | 136 - .../mistralai_gcp/utils/logger.py | 22 - .../mistralai_gcp/utils/metadata.py | 118 - .../mistralai_gcp/utils/queryparams.py | 205 - .../mistralai_gcp/utils/requestbodies.py | 66 - .../mistralai_gcp/utils/retries.py | 217 - .../mistralai_gcp/utils/security.py | 174 - .../mistralai_gcp/utils/serializers.py | 219 - .../site-packages/mistralai_gcp/utils/url.py | 155 - .../mistralai_gcp/utils/values.py | 137 - .../site-packages/odoorpc/__init__.py | 45 - .../__pycache__/__init__.cpython-312.pyc | Bin 2752 -> 0 bytes .../odoorpc/__pycache__/db.cpython-312.pyc | Bin 11283 -> 0 bytes .../odoorpc/__pycache__/env.cpython-312.pyc | Bin 12261 -> 0 bytes .../odoorpc/__pycache__/error.cpython-312.pyc | Bin 4377 -> 0 bytes .../__pycache__/fields.cpython-312.pyc | Bin 39010 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 19479 -> 0 bytes .../odoorpc/__pycache__/odoo.cpython-312.pyc | Bin 24968 -> 0 bytes .../__pycache__/report.cpython-312.pyc | Bin 8102 -> 0 bytes .../__pycache__/session.cpython-312.pyc | Bin 7318 -> 0 bytes .../odoorpc/__pycache__/tools.cpython-312.pyc | Bin 5233 -> 0 bytes .../python3.12/site-packages/odoorpc/db.py | 316 - .../python3.12/site-packages/odoorpc/env.py | 328 - .../python3.12/site-packages/odoorpc/error.py | 96 - .../site-packages/odoorpc/fields.py | 764 -- .../site-packages/odoorpc/models.py | 479 - .../python3.12/site-packages/odoorpc/odoo.py | 714 -- .../site-packages/odoorpc/report.py | 223 - .../site-packages/odoorpc/rpc/__init__.py | 298 - .../rpc/__pycache__/__init__.cpython-312.pyc | Bin 11193 -> 0 bytes .../rpc/__pycache__/error.cpython-312.pyc | Bin 644 -> 0 bytes .../__pycache__/jsonrpclib.cpython-312.pyc | Bin 8114 -> 0 bytes .../site-packages/odoorpc/rpc/error.py | 11 - .../site-packages/odoorpc/rpc/jsonrpclib.py | 181 - .../site-packages/odoorpc/session.py | 190 - .../python3.12/site-packages/odoorpc/tools.py | 125 - .../pip-24.0.dist-info/AUTHORS.txt | 760 -- .../pip-24.0.dist-info/INSTALLER | 1 - .../pip-24.0.dist-info/LICENSE.txt | 20 - .../site-packages/pip-24.0.dist-info/METADATA | 88 - .../site-packages/pip-24.0.dist-info/RECORD | 1005 -- .../pip-24.0.dist-info/REQUESTED | 0 .../site-packages/pip-24.0.dist-info/WHEEL | 5 - .../pip-24.0.dist-info/entry_points.txt | 4 - .../pip-24.0.dist-info/top_level.txt | 1 - .../python3.12/site-packages/pip/__init__.py | 13 - .../python3.12/site-packages/pip/__main__.py | 24 - .../site-packages/pip/__pip-runner__.py | 50 - .../pip/__pycache__/__init__.cpython-312.pyc | Bin 682 -> 0 bytes .../pip/__pycache__/__main__.cpython-312.pyc | Bin 838 -> 0 bytes .../__pip-runner__.cpython-312.pyc | Bin 2201 -> 0 bytes .../site-packages/pip/_internal/__init__.py | 18 - .../__pycache__/__init__.cpython-312.pyc | Bin 784 -> 0 bytes .../__pycache__/build_env.cpython-312.pyc | Bin 14291 -> 0 bytes .../__pycache__/cache.cpython-312.pyc | Bin 12662 -> 0 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 17663 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 33281 -> 0 bytes .../__pycache__/main.cpython-312.pyc | Bin 667 -> 0 bytes .../__pycache__/pyproject.cpython-312.pyc | Bin 4968 -> 0 bytes .../self_outdated_check.cpython-312.pyc | Bin 10549 -> 0 bytes .../__pycache__/wheel_builder.cpython-312.pyc | Bin 13646 -> 0 bytes .../site-packages/pip/_internal/build_env.py | 311 - .../site-packages/pip/_internal/cache.py | 290 - .../pip/_internal/cli/__init__.py | 4 - .../cli/__pycache__/__init__.cpython-312.pyc | Bin 275 -> 0 bytes .../autocompletion.cpython-312.pyc | Bin 8462 -> 0 bytes .../__pycache__/base_command.cpython-312.pyc | Bin 10452 -> 0 bytes .../__pycache__/cmdoptions.cpython-312.pyc | Bin 30371 -> 0 bytes .../command_context.cpython-312.pyc | Bin 1778 -> 0 bytes .../cli/__pycache__/main.cpython-312.pyc | Bin 2295 -> 0 bytes .../__pycache__/main_parser.cpython-312.pyc | Bin 4902 -> 0 bytes .../cli/__pycache__/parser.cpython-312.pyc | Bin 15019 -> 0 bytes .../__pycache__/progress_bars.cpython-312.pyc | Bin 2617 -> 0 bytes .../__pycache__/req_command.cpython-312.pyc | Bin 18849 -> 0 bytes .../cli/__pycache__/spinners.cpython-312.pyc | Bin 7837 -> 0 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 372 -> 0 bytes .../pip/_internal/cli/autocompletion.py | 172 - .../pip/_internal/cli/base_command.py | 236 - .../pip/_internal/cli/cmdoptions.py | 1074 -- .../pip/_internal/cli/command_context.py | 27 - .../site-packages/pip/_internal/cli/main.py | 79 - .../pip/_internal/cli/main_parser.py | 134 - .../site-packages/pip/_internal/cli/parser.py | 294 - .../pip/_internal/cli/progress_bars.py | 68 - .../pip/_internal/cli/req_command.py | 505 - .../pip/_internal/cli/spinners.py | 159 - .../pip/_internal/cli/status_codes.py | 6 - .../pip/_internal/commands/__init__.py | 132 - .../__pycache__/__init__.cpython-312.pyc | Bin 3999 -> 0 bytes .../__pycache__/cache.cpython-312.pyc | Bin 9708 -> 0 bytes .../__pycache__/check.cpython-312.pyc | Bin 2087 -> 0 bytes .../__pycache__/completion.cpython-312.pyc | Bin 5189 -> 0 bytes .../__pycache__/configuration.cpython-312.pyc | Bin 13209 -> 0 bytes .../__pycache__/debug.cpython-312.pyc | Bin 10158 -> 0 bytes .../__pycache__/download.cpython-312.pyc | Bin 7586 -> 0 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 4413 -> 0 bytes .../commands/__pycache__/hash.cpython-312.pyc | Bin 2980 -> 0 bytes .../commands/__pycache__/help.cpython-312.pyc | Bin 1670 -> 0 bytes .../__pycache__/index.cpython-312.pyc | Bin 6717 -> 0 bytes .../__pycache__/inspect.cpython-312.pyc | Bin 3972 -> 0 bytes .../__pycache__/install.cpython-312.pyc | Bin 28910 -> 0 bytes .../commands/__pycache__/list.cpython-312.pyc | Bin 15653 -> 0 bytes .../__pycache__/search.cpython-312.pyc | Bin 7618 -> 0 bytes .../commands/__pycache__/show.cpython-312.pyc | Bin 9725 -> 0 bytes .../__pycache__/uninstall.cpython-312.pyc | Bin 4723 -> 0 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 8953 -> 0 bytes .../pip/_internal/commands/cache.py | 225 - .../pip/_internal/commands/check.py | 54 - .../pip/_internal/commands/completion.py | 130 - .../pip/_internal/commands/configuration.py | 280 - .../pip/_internal/commands/debug.py | 201 - .../pip/_internal/commands/download.py | 147 - .../pip/_internal/commands/freeze.py | 109 - .../pip/_internal/commands/hash.py | 59 - .../pip/_internal/commands/help.py | 41 - .../pip/_internal/commands/index.py | 139 - .../pip/_internal/commands/inspect.py | 92 - .../pip/_internal/commands/install.py | 774 -- .../pip/_internal/commands/list.py | 370 - .../pip/_internal/commands/search.py | 174 - .../pip/_internal/commands/show.py | 189 - .../pip/_internal/commands/uninstall.py | 113 - .../pip/_internal/commands/wheel.py | 183 - .../pip/_internal/configuration.py | 383 - .../pip/_internal/distributions/__init__.py | 21 - .../__pycache__/__init__.cpython-312.pyc | Bin 938 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 2859 -> 0 bytes .../__pycache__/installed.cpython-312.pyc | Bin 1697 -> 0 bytes .../__pycache__/sdist.cpython-312.pyc | Bin 8485 -> 0 bytes .../__pycache__/wheel.cpython-312.pyc | Bin 2245 -> 0 bytes .../pip/_internal/distributions/base.py | 51 - .../pip/_internal/distributions/installed.py | 29 - .../pip/_internal/distributions/sdist.py | 156 - .../pip/_internal/distributions/wheel.py | 40 - .../site-packages/pip/_internal/exceptions.py | 728 -- .../pip/_internal/index/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 229 -> 0 bytes .../__pycache__/collector.cpython-312.pyc | Bin 21883 -> 0 bytes .../package_finder.cpython-312.pyc | Bin 40732 -> 0 bytes .../index/__pycache__/sources.cpython-312.pyc | Bin 12601 -> 0 bytes .../pip/_internal/index/collector.py | 507 - .../pip/_internal/index/package_finder.py | 1027 -- .../pip/_internal/index/sources.py | 285 - .../pip/_internal/locations/__init__.py | 467 - .../__pycache__/__init__.cpython-312.pyc | Bin 16773 -> 0 bytes .../__pycache__/_distutils.cpython-312.pyc | Bin 6853 -> 0 bytes .../__pycache__/_sysconfig.cpython-312.pyc | Bin 8008 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 3778 -> 0 bytes .../pip/_internal/locations/_distutils.py | 172 - .../pip/_internal/locations/_sysconfig.py | 213 - .../pip/_internal/locations/base.py | 81 - .../site-packages/pip/_internal/main.py | 12 - .../pip/_internal/metadata/__init__.py | 128 - .../__pycache__/__init__.cpython-312.pyc | Bin 5879 -> 0 bytes .../__pycache__/_json.cpython-312.pyc | Bin 2872 -> 0 bytes .../metadata/__pycache__/base.cpython-312.pyc | Bin 35709 -> 0 bytes .../__pycache__/pkg_resources.cpython-312.pyc | Bin 15787 -> 0 bytes .../pip/_internal/metadata/_json.py | 84 - .../pip/_internal/metadata/base.py | 702 -- .../_internal/metadata/importlib/__init__.py | 6 - .../__pycache__/__init__.cpython-312.pyc | Bin 355 -> 0 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 3330 -> 0 bytes .../__pycache__/_dists.cpython-312.pyc | Bin 13422 -> 0 bytes .../__pycache__/_envs.cpython-312.pyc | Bin 11177 -> 0 bytes .../_internal/metadata/importlib/_compat.py | 55 - .../_internal/metadata/importlib/_dists.py | 227 - .../pip/_internal/metadata/importlib/_envs.py | 189 - .../pip/_internal/metadata/pkg_resources.py | 278 - .../pip/_internal/models/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 263 -> 0 bytes .../__pycache__/candidate.cpython-312.pyc | Bin 1902 -> 0 bytes .../__pycache__/direct_url.cpython-312.pyc | Bin 11196 -> 0 bytes .../format_control.cpython-312.pyc | Bin 4224 -> 0 bytes .../models/__pycache__/index.cpython-312.pyc | Bin 1691 -> 0 bytes .../installation_report.cpython-312.pyc | Bin 2269 -> 0 bytes .../models/__pycache__/link.cpython-312.pyc | Bin 25999 -> 0 bytes .../models/__pycache__/scheme.cpython-312.pyc | Bin 1166 -> 0 bytes .../__pycache__/search_scope.cpython-312.pyc | Bin 5085 -> 0 bytes .../selection_prefs.cpython-312.pyc | Bin 1848 -> 0 bytes .../__pycache__/target_python.cpython-312.pyc | Bin 4951 -> 0 bytes .../models/__pycache__/wheel.cpython-312.pyc | Bin 5777 -> 0 bytes .../pip/_internal/models/candidate.py | 30 - .../pip/_internal/models/direct_url.py | 235 - .../pip/_internal/models/format_control.py | 78 - .../pip/_internal/models/index.py | 28 - .../_internal/models/installation_report.py | 56 - .../pip/_internal/models/link.py | 579 -- .../pip/_internal/models/scheme.py | 31 - .../pip/_internal/models/search_scope.py | 132 - .../pip/_internal/models/selection_prefs.py | 51 - .../pip/_internal/models/target_python.py | 122 - .../pip/_internal/models/wheel.py | 92 - .../pip/_internal/network/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 251 -> 0 bytes .../network/__pycache__/auth.cpython-312.pyc | Bin 21993 -> 0 bytes .../network/__pycache__/cache.cpython-312.pyc | Bin 6515 -> 0 bytes .../__pycache__/download.cpython-312.pyc | Bin 8550 -> 0 bytes .../__pycache__/lazy_wheel.cpython-312.pyc | Bin 11660 -> 0 bytes .../__pycache__/session.cpython-312.pyc | Bin 18771 -> 0 bytes .../network/__pycache__/utils.cpython-312.pyc | Bin 2250 -> 0 bytes .../__pycache__/xmlrpc.cpython-312.pyc | Bin 2946 -> 0 bytes .../pip/_internal/network/auth.py | 561 -- .../pip/_internal/network/cache.py | 106 - .../pip/_internal/network/download.py | 186 - .../pip/_internal/network/lazy_wheel.py | 210 - .../pip/_internal/network/session.py | 520 - .../pip/_internal/network/utils.py | 96 - .../pip/_internal/network/xmlrpc.py | 62 - .../pip/_internal/operations/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 194 -> 0 bytes .../__pycache__/check.cpython-312.pyc | Bin 7576 -> 0 bytes .../__pycache__/freeze.cpython-312.pyc | Bin 10114 -> 0 bytes .../__pycache__/prepare.cpython-312.pyc | Bin 25744 -> 0 bytes .../_internal/operations/build/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 200 -> 0 bytes .../__pycache__/build_tracker.cpython-312.pyc | Bin 7820 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 1877 -> 0 bytes .../metadata_editable.cpython-312.pyc | Bin 1911 -> 0 bytes .../metadata_legacy.cpython-312.pyc | Bin 3062 -> 0 bytes .../build/__pycache__/wheel.cpython-312.pyc | Bin 1681 -> 0 bytes .../wheel_editable.cpython-312.pyc | Bin 2022 -> 0 bytes .../__pycache__/wheel_legacy.cpython-312.pyc | Bin 3926 -> 0 bytes .../operations/build/build_tracker.py | 139 - .../_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 | 187 - .../pip/_internal/operations/freeze.py | 255 - .../_internal/operations/install/__init__.py | 2 - .../__pycache__/__init__.cpython-312.pyc | Bin 263 -> 0 bytes .../editable_legacy.cpython-312.pyc | Bin 1814 -> 0 bytes .../install/__pycache__/wheel.cpython-312.pyc | Bin 33856 -> 0 bytes .../operations/install/editable_legacy.py | 46 - .../pip/_internal/operations/install/wheel.py | 734 -- .../pip/_internal/operations/prepare.py | 730 -- .../site-packages/pip/_internal/pyproject.py | 179 - .../pip/_internal/req/__init__.py | 92 - .../req/__pycache__/__init__.cpython-312.pyc | Bin 3740 -> 0 bytes .../__pycache__/constructors.cpython-312.pyc | Bin 21579 -> 0 bytes .../req/__pycache__/req_file.cpython-312.pyc | Bin 21458 -> 0 bytes .../__pycache__/req_install.cpython-312.pyc | Bin 38411 -> 0 bytes .../req/__pycache__/req_set.cpython-312.pyc | Bin 7215 -> 0 bytes .../__pycache__/req_uninstall.cpython-312.pyc | Bin 32974 -> 0 bytes .../pip/_internal/req/constructors.py | 576 -- .../pip/_internal/req/req_file.py | 554 -- .../pip/_internal/req/req_install.py | 923 -- .../pip/_internal/req/req_set.py | 119 - .../pip/_internal/req/req_uninstall.py | 649 -- .../pip/_internal/resolution/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 194 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 1182 -> 0 bytes .../pip/_internal/resolution/base.py | 20 - .../_internal/resolution/legacy/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 201 -> 0 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 22436 -> 0 bytes .../_internal/resolution/legacy/resolver.py | 598 -- .../resolution/resolvelib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 205 -> 0 bytes .../__pycache__/base.cpython-312.pyc | Bin 8334 -> 0 bytes .../__pycache__/candidates.cpython-312.pyc | Bin 30395 -> 0 bytes .../__pycache__/factory.cpython-312.pyc | Bin 32111 -> 0 bytes .../found_candidates.cpython-312.pyc | Bin 6205 -> 0 bytes .../__pycache__/provider.cpython-312.pyc | Bin 10375 -> 0 bytes .../__pycache__/reporter.cpython-312.pyc | Bin 4932 -> 0 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 11426 -> 0 bytes .../__pycache__/resolver.cpython-312.pyc | Bin 12348 -> 0 bytes .../_internal/resolution/resolvelib/base.py | 141 - .../resolution/resolvelib/candidates.py | 597 -- .../resolution/resolvelib/factory.py | 812 -- .../resolution/resolvelib/found_candidates.py | 155 - .../resolution/resolvelib/provider.py | 255 - .../resolution/resolvelib/reporter.py | 80 - .../resolution/resolvelib/requirements.py | 166 - .../resolution/resolvelib/resolver.py | 317 - .../pip/_internal/self_outdated_check.py | 248 - .../pip/_internal/utils/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 189 -> 0 bytes .../__pycache__/_jaraco_text.cpython-312.pyc | Bin 4530 -> 0 bytes .../utils/__pycache__/_log.cpython-312.pyc | Bin 1860 -> 0 bytes .../utils/__pycache__/appdirs.cpython-312.pyc | Bin 2404 -> 0 bytes .../utils/__pycache__/compat.cpython-312.pyc | Bin 2207 -> 0 bytes .../compatibility_tags.cpython-312.pyc | Bin 5555 -> 0 bytes .../__pycache__/datetime.cpython-312.pyc | Bin 678 -> 0 bytes .../__pycache__/deprecation.cpython-312.pyc | Bin 4180 -> 0 bytes .../direct_url_helpers.cpython-312.pyc | Bin 3557 -> 0 bytes .../__pycache__/egg_link.cpython-312.pyc | Bin 3220 -> 0 bytes .../__pycache__/encoding.cpython-312.pyc | Bin 2152 -> 0 bytes .../__pycache__/entrypoints.cpython-312.pyc | Bin 3987 -> 0 bytes .../__pycache__/filesystem.cpython-312.pyc | Bin 7452 -> 0 bytes .../__pycache__/filetypes.cpython-312.pyc | Bin 1158 -> 0 bytes .../utils/__pycache__/glibc.cpython-312.pyc | Bin 2336 -> 0 bytes .../utils/__pycache__/hashes.cpython-312.pyc | Bin 7548 -> 0 bytes .../utils/__pycache__/logging.cpython-312.pyc | Bin 13551 -> 0 bytes .../utils/__pycache__/misc.cpython-312.pyc | Bin 34115 -> 0 bytes .../utils/__pycache__/models.cpython-312.pyc | Bin 2706 -> 0 bytes .../__pycache__/packaging.cpython-312.pyc | Bin 2577 -> 0 bytes .../setuptools_build.cpython-312.pyc | Bin 4544 -> 0 bytes .../__pycache__/subprocess.cpython-312.pyc | Bin 8712 -> 0 bytes .../__pycache__/temp_dir.cpython-312.pyc | Bin 12056 -> 0 bytes .../__pycache__/unpacking.cpython-312.pyc | Bin 11102 -> 0 bytes .../utils/__pycache__/urls.cpython-312.pyc | Bin 2399 -> 0 bytes .../__pycache__/virtualenv.cpython-312.pyc | Bin 4474 -> 0 bytes .../utils/__pycache__/wheel.cpython-312.pyc | Bin 5920 -> 0 bytes .../pip/_internal/utils/_jaraco_text.py | 109 - .../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/egg_link.py | 80 - .../pip/_internal/utils/encoding.py | 36 - .../pip/_internal/utils/entrypoints.py | 84 - .../pip/_internal/utils/filesystem.py | 153 - .../pip/_internal/utils/filetypes.py | 27 - .../pip/_internal/utils/glibc.py | 88 - .../pip/_internal/utils/hashes.py | 151 - .../pip/_internal/utils/logging.py | 348 - .../site-packages/pip/_internal/utils/misc.py | 783 -- .../pip/_internal/utils/models.py | 39 - .../pip/_internal/utils/packaging.py | 57 - .../pip/_internal/utils/setuptools_build.py | 146 - .../pip/_internal/utils/subprocess.py | 260 - .../pip/_internal/utils/temp_dir.py | 296 - .../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 | 134 - .../pip/_internal/vcs/__init__.py | 15 - .../vcs/__pycache__/__init__.cpython-312.pyc | Bin 528 -> 0 bytes .../vcs/__pycache__/bazaar.cpython-312.pyc | Bin 5020 -> 0 bytes .../vcs/__pycache__/git.cpython-312.pyc | Bin 18989 -> 0 bytes .../vcs/__pycache__/mercurial.cpython-312.pyc | Bin 7609 -> 0 bytes .../__pycache__/subversion.cpython-312.pyc | Bin 12481 -> 0 bytes .../versioncontrol.cpython-312.pyc | Bin 29007 -> 0 bytes .../site-packages/pip/_internal/vcs/bazaar.py | 112 - .../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 | 354 - .../site-packages/pip/_vendor/__init__.py | 121 - .../__pycache__/__init__.cpython-312.pyc | Bin 4690 -> 0 bytes .../_vendor/__pycache__/six.cpython-312.pyc | Bin 41267 -> 0 bytes .../typing_extensions.cpython-312.pyc | Bin 122047 -> 0 bytes .../pip/_vendor/cachecontrol/__init__.py | 28 - .../__pycache__/__init__.cpython-312.pyc | Bin 900 -> 0 bytes .../__pycache__/_cmd.cpython-312.pyc | Bin 2644 -> 0 bytes .../__pycache__/adapter.cpython-312.pyc | Bin 6462 -> 0 bytes .../__pycache__/cache.cpython-312.pyc | Bin 3807 -> 0 bytes .../__pycache__/controller.cpython-312.pyc | Bin 16165 -> 0 bytes .../__pycache__/filewrapper.cpython-312.pyc | Bin 4345 -> 0 bytes .../__pycache__/heuristics.cpython-312.pyc | Bin 6692 -> 0 bytes .../__pycache__/serialize.cpython-312.pyc | Bin 6403 -> 0 bytes .../__pycache__/wrapper.cpython-312.pyc | Bin 1672 -> 0 bytes .../pip/_vendor/cachecontrol/_cmd.py | 70 - .../pip/_vendor/cachecontrol/adapter.py | 161 - .../pip/_vendor/cachecontrol/cache.py | 74 - .../_vendor/cachecontrol/caches/__init__.py | 8 - .../__pycache__/__init__.cpython-312.pyc | Bin 433 -> 0 bytes .../__pycache__/file_cache.cpython-312.pyc | Bin 7708 -> 0 bytes .../__pycache__/redis_cache.cpython-312.pyc | Bin 2736 -> 0 bytes .../_vendor/cachecontrol/caches/file_cache.py | 181 - .../cachecontrol/caches/redis_cache.py | 48 - .../pip/_vendor/cachecontrol/controller.py | 494 - .../pip/_vendor/cachecontrol/filewrapper.py | 119 - .../pip/_vendor/cachecontrol/heuristics.py | 154 - .../pip/_vendor/cachecontrol/serialize.py | 206 - .../pip/_vendor/cachecontrol/wrapper.py | 43 - .../pip/_vendor/certifi/__init__.py | 4 - .../pip/_vendor/certifi/__main__.py | 12 - .../__pycache__/__init__.cpython-312.pyc | Bin 316 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 643 -> 0 bytes .../certifi/__pycache__/core.cpython-312.pyc | Bin 3325 -> 0 bytes .../pip/_vendor/certifi/cacert.pem | 4635 --------- .../site-packages/pip/_vendor/certifi/core.py | 119 - .../pip/_vendor/chardet/__init__.py | 115 - .../__pycache__/__init__.cpython-312.pyc | Bin 4566 -> 0 bytes .../__pycache__/big5freq.cpython-312.pyc | Bin 27197 -> 0 bytes .../__pycache__/big5prober.cpython-312.pyc | Bin 1385 -> 0 bytes .../chardistribution.cpython-312.pyc | Bin 9636 -> 0 bytes .../charsetgroupprober.cpython-312.pyc | Bin 4120 -> 0 bytes .../__pycache__/charsetprober.cpython-312.pyc | Bin 5016 -> 0 bytes .../codingstatemachine.cpython-312.pyc | Bin 3876 -> 0 bytes .../codingstatemachinedict.cpython-312.pyc | Bin 787 -> 0 bytes .../__pycache__/cp949prober.cpython-312.pyc | Bin 1394 -> 0 bytes .../chardet/__pycache__/enums.cpython-312.pyc | Bin 2994 -> 0 bytes .../__pycache__/escprober.cpython-312.pyc | Bin 4564 -> 0 bytes .../chardet/__pycache__/escsm.cpython-312.pyc | Bin 15308 -> 0 bytes .../__pycache__/eucjpprober.cpython-312.pyc | Bin 4381 -> 0 bytes .../__pycache__/euckrfreq.cpython-312.pyc | Bin 12080 -> 0 bytes .../__pycache__/euckrprober.cpython-312.pyc | Bin 1388 -> 0 bytes .../__pycache__/euctwfreq.cpython-312.pyc | Bin 27202 -> 0 bytes .../__pycache__/euctwprober.cpython-312.pyc | Bin 1388 -> 0 bytes .../__pycache__/gb2312freq.cpython-312.pyc | Bin 19124 -> 0 bytes .../__pycache__/gb2312prober.cpython-312.pyc | Bin 1401 -> 0 bytes .../__pycache__/hebrewprober.cpython-312.pyc | Bin 5820 -> 0 bytes .../__pycache__/jisfreq.cpython-312.pyc | Bin 22153 -> 0 bytes .../__pycache__/johabfreq.cpython-312.pyc | Bin 83001 -> 0 bytes .../__pycache__/johabprober.cpython-312.pyc | Bin 1392 -> 0 bytes .../__pycache__/jpcntx.cpython-312.pyc | Bin 39547 -> 0 bytes .../langbulgarianmodel.cpython-312.pyc | Bin 83120 -> 0 bytes .../langgreekmodel.cpython-312.pyc | Bin 76986 -> 0 bytes .../langhebrewmodel.cpython-312.pyc | Bin 77497 -> 0 bytes .../langhungarianmodel.cpython-312.pyc | Bin 83074 -> 0 bytes .../langrussianmodel.cpython-312.pyc | Bin 105249 -> 0 bytes .../__pycache__/langthaimodel.cpython-312.pyc | Bin 77675 -> 0 bytes .../langturkishmodel.cpython-312.pyc | Bin 77514 -> 0 bytes .../__pycache__/latin1prober.cpython-312.pyc | Bin 7000 -> 0 bytes .../macromanprober.cpython-312.pyc | Bin 7180 -> 0 bytes .../mbcharsetprober.cpython-312.pyc | Bin 3901 -> 0 bytes .../mbcsgroupprober.cpython-312.pyc | Bin 1586 -> 0 bytes .../__pycache__/mbcssm.cpython-312.pyc | Bin 38643 -> 0 bytes .../__pycache__/resultdict.cpython-312.pyc | Bin 630 -> 0 bytes .../sbcharsetprober.cpython-312.pyc | Bin 6385 -> 0 bytes .../sbcsgroupprober.cpython-312.pyc | Bin 2355 -> 0 bytes .../__pycache__/sjisprober.cpython-312.pyc | Bin 4493 -> 0 bytes .../universaldetector.cpython-312.pyc | Bin 12267 -> 0 bytes .../__pycache__/utf1632prober.cpython-312.pyc | Bin 9977 -> 0 bytes .../__pycache__/utf8prober.cpython-312.pyc | Bin 3173 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 486 -> 0 bytes .../pip/_vendor/chardet/big5freq.py | 386 - .../pip/_vendor/chardet/big5prober.py | 47 - .../pip/_vendor/chardet/chardistribution.py | 261 - .../pip/_vendor/chardet/charsetgroupprober.py | 106 - .../pip/_vendor/chardet/charsetprober.py | 147 - .../pip/_vendor/chardet/cli/__init__.py | 0 .../cli/__pycache__/__init__.cpython-312.pyc | Bin 193 -> 0 bytes .../__pycache__/chardetect.cpython-312.pyc | Bin 4010 -> 0 bytes .../pip/_vendor/chardet/cli/chardetect.py | 112 - .../pip/_vendor/chardet/codingstatemachine.py | 90 - .../_vendor/chardet/codingstatemachinedict.py | 19 - .../pip/_vendor/chardet/cp949prober.py | 49 - .../pip/_vendor/chardet/enums.py | 85 - .../pip/_vendor/chardet/escprober.py | 102 - .../pip/_vendor/chardet/escsm.py | 261 - .../pip/_vendor/chardet/eucjpprober.py | 102 - .../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 | 316 - .../pip/_vendor/chardet/jisfreq.py | 325 - .../pip/_vendor/chardet/johabfreq.py | 2382 ----- .../pip/_vendor/chardet/johabprober.py | 47 - .../pip/_vendor/chardet/jpcntx.py | 238 - .../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 | 147 - .../pip/_vendor/chardet/macromanprober.py | 162 - .../pip/_vendor/chardet/mbcharsetprober.py | 95 - .../pip/_vendor/chardet/mbcsgroupprober.py | 57 - .../pip/_vendor/chardet/mbcssm.py | 661 -- .../pip/_vendor/chardet/metadata/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 198 -> 0 bytes .../__pycache__/languages.cpython-312.pyc | Bin 9753 -> 0 bytes .../pip/_vendor/chardet/metadata/languages.py | 352 - .../pip/_vendor/chardet/resultdict.py | 16 - .../pip/_vendor/chardet/sbcharsetprober.py | 162 - .../pip/_vendor/chardet/sbcsgroupprober.py | 88 - .../pip/_vendor/chardet/sjisprober.py | 105 - .../pip/_vendor/chardet/universaldetector.py | 362 - .../pip/_vendor/chardet/utf1632prober.py | 225 - .../pip/_vendor/chardet/utf8prober.py | 82 - .../pip/_vendor/chardet/version.py | 9 - .../pip/_vendor/colorama/__init__.py | 7 - .../__pycache__/__init__.cpython-312.pyc | Bin 490 -> 0 bytes .../colorama/__pycache__/ansi.cpython-312.pyc | Bin 3948 -> 0 bytes .../__pycache__/ansitowin32.cpython-312.pyc | Bin 16419 -> 0 bytes .../__pycache__/initialise.cpython-312.pyc | Bin 3548 -> 0 bytes .../__pycache__/win32.cpython-312.pyc | Bin 8124 -> 0 bytes .../__pycache__/winterm.cpython-312.pyc | Bin 9086 -> 0 bytes .../pip/_vendor/colorama/ansi.py | 102 - .../pip/_vendor/colorama/ansitowin32.py | 277 - .../pip/_vendor/colorama/initialise.py | 121 - .../pip/_vendor/colorama/tests/__init__.py | 1 - .../__pycache__/__init__.cpython-312.pyc | Bin 196 -> 0 bytes .../__pycache__/ansi_test.cpython-312.pyc | Bin 5465 -> 0 bytes .../ansitowin32_test.cpython-312.pyc | Bin 18101 -> 0 bytes .../initialise_test.cpython-312.pyc | Bin 11746 -> 0 bytes .../__pycache__/isatty_test.cpython-312.pyc | Bin 4902 -> 0 bytes .../tests/__pycache__/utils.cpython-312.pyc | Bin 2486 -> 0 bytes .../__pycache__/winterm_test.cpython-312.pyc | Bin 6610 -> 0 bytes .../pip/_vendor/colorama/tests/ansi_test.py | 76 - .../colorama/tests/ansitowin32_test.py | 294 - .../_vendor/colorama/tests/initialise_test.py | 189 - .../pip/_vendor/colorama/tests/isatty_test.py | 57 - .../pip/_vendor/colorama/tests/utils.py | 49 - .../_vendor/colorama/tests/winterm_test.py | 131 - .../pip/_vendor/colorama/win32.py | 180 - .../pip/_vendor/colorama/winterm.py | 195 - .../pip/_vendor/distlib/__init__.py | 33 - .../__pycache__/__init__.cpython-312.pyc | Bin 1267 -> 0 bytes .../__pycache__/compat.cpython-312.pyc | Bin 45603 -> 0 bytes .../__pycache__/database.cpython-312.pyc | Bin 66025 -> 0 bytes .../distlib/__pycache__/index.cpython-312.pyc | Bin 24364 -> 0 bytes .../__pycache__/locators.cpython-312.pyc | Bin 60156 -> 0 bytes .../__pycache__/manifest.cpython-312.pyc | Bin 15123 -> 0 bytes .../__pycache__/markers.cpython-312.pyc | Bin 7680 -> 0 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 41797 -> 0 bytes .../__pycache__/resources.cpython-312.pyc | Bin 17323 -> 0 bytes .../__pycache__/scripts.cpython-312.pyc | Bin 19578 -> 0 bytes .../distlib/__pycache__/util.cpython-312.pyc | Bin 88254 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 30364 -> 0 bytes .../distlib/__pycache__/wheel.cpython-312.pyc | Bin 51859 -> 0 bytes .../pip/_vendor/distlib/compat.py | 1138 --- .../pip/_vendor/distlib/database.py | 1359 --- .../pip/_vendor/distlib/index.py | 508 - .../pip/_vendor/distlib/locators.py | 1303 --- .../pip/_vendor/distlib/manifest.py | 384 - .../pip/_vendor/distlib/markers.py | 167 - .../pip/_vendor/distlib/metadata.py | 1068 -- .../pip/_vendor/distlib/resources.py | 358 - .../pip/_vendor/distlib/scripts.py | 452 - .../site-packages/pip/_vendor/distlib/util.py | 2025 ---- .../pip/_vendor/distlib/version.py | 751 -- .../pip/_vendor/distlib/wheel.py | 1099 --- .../pip/_vendor/distro/__init__.py | 54 - .../pip/_vendor/distro/__main__.py | 4 - .../__pycache__/__init__.cpython-312.pyc | Bin 958 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 290 -> 0 bytes .../distro/__pycache__/distro.cpython-312.pyc | Bin 53752 -> 0 bytes .../pip/_vendor/distro/distro.py | 1399 --- .../pip/_vendor/idna/__init__.py | 44 - .../idna/__pycache__/__init__.cpython-312.pyc | Bin 879 -> 0 bytes .../idna/__pycache__/codec.cpython-312.pyc | Bin 4631 -> 0 bytes .../idna/__pycache__/compat.cpython-312.pyc | Bin 885 -> 0 bytes .../idna/__pycache__/core.cpython-312.pyc | Bin 16280 -> 0 bytes .../idna/__pycache__/idnadata.cpython-312.pyc | Bin 38380 -> 0 bytes .../__pycache__/intranges.cpython-312.pyc | Bin 2636 -> 0 bytes .../__pycache__/package_data.cpython-312.pyc | Bin 214 -> 0 bytes .../__pycache__/uts46data.cpython-312.pyc | Bin 158868 -> 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 | 400 - .../pip/_vendor/idna/idnadata.py | 2151 ---- .../pip/_vendor/idna/intranges.py | 54 - .../pip/_vendor/idna/package_data.py | 2 - .../pip/_vendor/idna/uts46data.py | 8600 ---------------- .../pip/_vendor/msgpack/__init__.py | 57 - .../__pycache__/__init__.cpython-312.pyc | Bin 1829 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 2023 -> 0 bytes .../msgpack/__pycache__/ext.cpython-312.pyc | Bin 8666 -> 0 bytes .../__pycache__/fallback.cpython-312.pyc | Bin 43574 -> 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-312.pyc | Bin 628 -> 0 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 464 -> 0 bytes .../__pycache__/_manylinux.cpython-312.pyc | Bin 12074 -> 0 bytes .../__pycache__/_musllinux.cpython-312.pyc | Bin 6908 -> 0 bytes .../__pycache__/_structures.cpython-312.pyc | Bin 3239 -> 0 bytes .../__pycache__/markers.cpython-312.pyc | Bin 14056 -> 0 bytes .../__pycache__/requirements.cpython-312.pyc | Bin 6944 -> 0 bytes .../__pycache__/specifiers.cpython-312.pyc | Bin 31245 -> 0 bytes .../__pycache__/tags.cpython-312.pyc | Bin 18954 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 5866 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 19937 -> 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/pkg_resources/__init__.py | 3361 ------- .../__pycache__/__init__.cpython-312.pyc | Bin 146472 -> 0 bytes .../pip/_vendor/platformdirs/__init__.py | 566 -- .../pip/_vendor/platformdirs/__main__.py | 53 - .../__pycache__/__init__.cpython-312.pyc | Bin 18027 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 1944 -> 0 bytes .../__pycache__/android.cpython-312.pyc | Bin 9442 -> 0 bytes .../__pycache__/api.cpython-312.pyc | Bin 9670 -> 0 bytes .../__pycache__/macos.cpython-312.pyc | Bin 5635 -> 0 bytes .../__pycache__/unix.cpython-312.pyc | Bin 12439 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 309 -> 0 bytes .../__pycache__/windows.cpython-312.pyc | Bin 12997 -> 0 bytes .../pip/_vendor/platformdirs/android.py | 210 - .../pip/_vendor/platformdirs/api.py | 223 - .../pip/_vendor/platformdirs/macos.py | 91 - .../pip/_vendor/platformdirs/unix.py | 223 - .../pip/_vendor/platformdirs/version.py | 4 - .../pip/_vendor/platformdirs/windows.py | 255 - .../pip/_vendor/pygments/__init__.py | 82 - .../pip/_vendor/pygments/__main__.py | 17 - .../__pycache__/__init__.cpython-312.pyc | Bin 3487 -> 0 bytes .../__pycache__/__main__.cpython-312.pyc | Bin 733 -> 0 bytes .../__pycache__/cmdline.cpython-312.pyc | Bin 26604 -> 0 bytes .../__pycache__/console.cpython-312.pyc | Bin 2625 -> 0 bytes .../__pycache__/filter.cpython-312.pyc | Bin 3231 -> 0 bytes .../__pycache__/formatter.cpython-312.pyc | Bin 4568 -> 0 bytes .../__pycache__/lexer.cpython-312.pyc | Bin 38328 -> 0 bytes .../__pycache__/modeline.cpython-312.pyc | Bin 1567 -> 0 bytes .../__pycache__/plugin.cpython-312.pyc | Bin 3395 -> 0 bytes .../__pycache__/regexopt.cpython-312.pyc | Bin 4080 -> 0 bytes .../__pycache__/scanner.cpython-312.pyc | Bin 4755 -> 0 bytes .../__pycache__/sphinxext.cpython-312.pyc | Bin 11045 -> 0 bytes .../__pycache__/style.cpython-312.pyc | Bin 6673 -> 0 bytes .../__pycache__/token.cpython-312.pyc | Bin 8141 -> 0 bytes .../__pycache__/unistring.cpython-312.pyc | Bin 32987 -> 0 bytes .../pygments/__pycache__/util.cpython-312.pyc | Bin 13980 -> 0 bytes .../pip/_vendor/pygments/cmdline.py | 668 -- .../pip/_vendor/pygments/console.py | 70 - .../pip/_vendor/pygments/filter.py | 71 - .../pip/_vendor/pygments/filters/__init__.py | 940 -- .../__pycache__/__init__.cpython-312.pyc | Bin 37935 -> 0 bytes .../pip/_vendor/pygments/formatter.py | 124 - .../_vendor/pygments/formatters/__init__.py | 158 - .../__pycache__/__init__.cpython-312.pyc | Bin 6925 -> 0 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 4214 -> 0 bytes .../__pycache__/bbcode.cpython-312.pyc | Bin 4193 -> 0 bytes .../__pycache__/groff.cpython-312.pyc | Bin 7263 -> 0 bytes .../__pycache__/html.cpython-312.pyc | Bin 40571 -> 0 bytes .../__pycache__/img.cpython-312.pyc | Bin 27042 -> 0 bytes .../__pycache__/irc.cpython-312.pyc | Bin 6064 -> 0 bytes .../__pycache__/latex.cpython-312.pyc | Bin 19953 -> 0 bytes .../__pycache__/other.cpython-312.pyc | Bin 6883 -> 0 bytes .../__pycache__/pangomarkup.cpython-312.pyc | Bin 2929 -> 0 bytes .../__pycache__/rtf.cpython-312.pyc | Bin 6125 -> 0 bytes .../__pycache__/svg.cpython-312.pyc | Bin 9065 -> 0 bytes .../__pycache__/terminal.cpython-312.pyc | Bin 5828 -> 0 bytes .../__pycache__/terminal256.cpython-312.pyc | Bin 15156 -> 0 bytes .../_vendor/pygments/formatters/_mapping.py | 23 - .../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 | 645 -- .../pip/_vendor/pygments/formatters/irc.py | 154 - .../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 | 943 -- .../pip/_vendor/pygments/lexers/__init__.py | 362 - .../__pycache__/__init__.cpython-312.pyc | Bin 14651 -> 0 bytes .../__pycache__/_mapping.cpython-312.pyc | Bin 64403 -> 0 bytes .../lexers/__pycache__/python.cpython-312.pyc | Bin 42638 -> 0 bytes .../pip/_vendor/pygments/lexers/_mapping.py | 559 -- .../pip/_vendor/pygments/lexers/python.py | 1198 --- .../pip/_vendor/pygments/modeline.py | 43 - .../pip/_vendor/pygments/plugin.py | 88 - .../pip/_vendor/pygments/regexopt.py | 91 - .../pip/_vendor/pygments/scanner.py | 104 - .../pip/_vendor/pygments/sphinxext.py | 217 - .../pip/_vendor/pygments/style.py | 197 - .../pip/_vendor/pygments/styles/__init__.py | 103 - .../__pycache__/__init__.cpython-312.pyc | Bin 4447 -> 0 bytes .../pip/_vendor/pygments/token.py | 213 - .../pip/_vendor/pygments/unistring.py | 153 - .../pip/_vendor/pygments/util.py | 330 - .../pip/_vendor/pyparsing/__init__.py | 322 - .../__pycache__/__init__.cpython-312.pyc | Bin 7910 -> 0 bytes .../__pycache__/actions.cpython-312.pyc | Bin 8394 -> 0 bytes .../__pycache__/common.cpython-312.pyc | Bin 13413 -> 0 bytes .../__pycache__/core.cpython-312.pyc | Bin 267707 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 12993 -> 0 bytes .../__pycache__/helpers.cpython-312.pyc | Bin 48500 -> 0 bytes .../__pycache__/results.cpython-312.pyc | Bin 34109 -> 0 bytes .../__pycache__/testing.cpython-312.pyc | Bin 17187 -> 0 bytes .../__pycache__/unicode.cpython-312.pyc | Bin 13183 -> 0 bytes .../__pycache__/util.cpython-312.pyc | Bin 14903 -> 0 bytes .../pip/_vendor/pyparsing/actions.py | 217 - .../pip/_vendor/pyparsing/common.py | 432 - .../pip/_vendor/pyparsing/core.py | 6115 ------------ .../pip/_vendor/pyparsing/diagram/__init__.py | 656 -- .../__pycache__/__init__.cpython-312.pyc | Bin 26812 -> 0 bytes .../pip/_vendor/pyparsing/exceptions.py | 299 - .../pip/_vendor/pyparsing/helpers.py | 1100 --- .../pip/_vendor/pyparsing/results.py | 796 -- .../pip/_vendor/pyparsing/testing.py | 331 - .../pip/_vendor/pyparsing/unicode.py | 361 - .../pip/_vendor/pyparsing/util.py | 284 - .../pip/_vendor/pyproject_hooks/__init__.py | 23 - .../__pycache__/__init__.cpython-312.pyc | Bin 612 -> 0 bytes .../__pycache__/_compat.cpython-312.pyc | Bin 373 -> 0 bytes .../__pycache__/_impl.cpython-312.pyc | Bin 14724 -> 0 bytes .../pip/_vendor/pyproject_hooks/_compat.py | 8 - .../pip/_vendor/pyproject_hooks/_impl.py | 330 - .../pyproject_hooks/_in_process/__init__.py | 18 - .../__pycache__/__init__.cpython-312.pyc | Bin 1079 -> 0 bytes .../__pycache__/_in_process.cpython-312.pyc | Bin 14396 -> 0 bytes .../_in_process/_in_process.py | 353 - .../pip/_vendor/requests/__init__.py | 182 - .../__pycache__/__init__.cpython-312.pyc | Bin 5452 -> 0 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 583 -> 0 bytes .../_internal_utils.cpython-312.pyc | Bin 2023 -> 0 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 21279 -> 0 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 7203 -> 0 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 13922 -> 0 bytes .../__pycache__/certs.cpython-312.pyc | Bin 921 -> 0 bytes .../__pycache__/compat.cpython-312.pyc | Bin 1506 -> 0 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 25245 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 7046 -> 0 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 4311 -> 0 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 1051 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 35447 -> 0 bytes .../__pycache__/packages.cpython-312.pyc | Bin 771 -> 0 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 27756 -> 0 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 5958 -> 0 bytes .../__pycache__/structures.cpython-312.pyc | Bin 5616 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 36268 -> 0 bytes .../pip/_vendor/requests/__version__.py | 14 - .../pip/_vendor/requests/_internal_utils.py | 50 - .../pip/_vendor/requests/adapters.py | 538 - .../site-packages/pip/_vendor/requests/api.py | 157 - .../pip/_vendor/requests/auth.py | 315 - .../pip/_vendor/requests/certs.py | 24 - .../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 | 833 -- .../pip/_vendor/requests/status_codes.py | 128 - .../pip/_vendor/requests/structures.py | 99 - .../pip/_vendor/requests/utils.py | 1094 --- .../pip/_vendor/resolvelib/__init__.py | 26 - .../__pycache__/__init__.cpython-312.pyc | Bin 633 -> 0 bytes .../__pycache__/providers.cpython-312.pyc | Bin 6850 -> 0 bytes .../__pycache__/reporters.cpython-312.pyc | Bin 2653 -> 0 bytes .../__pycache__/resolvers.cpython-312.pyc | Bin 25896 -> 0 bytes .../__pycache__/structs.cpython-312.pyc | Bin 10505 -> 0 bytes .../pip/_vendor/resolvelib/compat/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 199 -> 0 bytes .../collections_abc.cpython-312.pyc | Bin 419 -> 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 | 547 -- .../pip/_vendor/resolvelib/structs.py | 170 - .../pip/_vendor/rich/__init__.py | 177 - .../pip/_vendor/rich/__main__.py | 274 - .../rich/__pycache__/__init__.cpython-312.pyc | Bin 7014 -> 0 bytes .../rich/__pycache__/__main__.cpython-312.pyc | Bin 10303 -> 0 bytes .../__pycache__/_cell_widths.cpython-312.pyc | Bin 7820 -> 0 bytes .../__pycache__/_emoji_codes.cpython-312.pyc | Bin 205975 -> 0 bytes .../_emoji_replace.cpython-312.pyc | Bin 1728 -> 0 bytes .../_export_format.cpython-312.pyc | Bin 2320 -> 0 bytes .../__pycache__/_extension.cpython-312.pyc | Bin 536 -> 0 bytes .../rich/__pycache__/_fileno.cpython-312.pyc | Bin 854 -> 0 bytes .../rich/__pycache__/_inspect.cpython-312.pyc | Bin 12076 -> 0 bytes .../__pycache__/_log_render.cpython-312.pyc | Bin 4146 -> 0 bytes .../rich/__pycache__/_loop.cpython-312.pyc | Bin 1884 -> 0 bytes .../__pycache__/_null_file.cpython-312.pyc | Bin 3619 -> 0 bytes .../__pycache__/_palettes.cpython-312.pyc | Bin 5159 -> 0 bytes .../rich/__pycache__/_pick.cpython-312.pyc | Bin 725 -> 0 bytes .../rich/__pycache__/_ratio.cpython-312.pyc | Bin 6578 -> 0 bytes .../__pycache__/_spinners.cpython-312.pyc | Bin 13178 -> 0 bytes .../rich/__pycache__/_stack.cpython-312.pyc | Bin 964 -> 0 bytes .../rich/__pycache__/_timer.cpython-312.pyc | Bin 864 -> 0 bytes .../_win32_console.cpython-312.pyc | Bin 28975 -> 0 bytes .../rich/__pycache__/_windows.cpython-312.pyc | Bin 2489 -> 0 bytes .../_windows_renderer.cpython-312.pyc | Bin 3572 -> 0 bytes .../rich/__pycache__/_wrap.cpython-312.pyc | Bin 2359 -> 0 bytes .../rich/__pycache__/abc.cpython-312.pyc | Bin 1607 -> 0 bytes .../rich/__pycache__/align.cpython-312.pyc | Bin 12321 -> 0 bytes .../rich/__pycache__/ansi.cpython-312.pyc | Bin 9105 -> 0 bytes .../rich/__pycache__/bar.cpython-312.pyc | Bin 4271 -> 0 bytes .../rich/__pycache__/box.cpython-312.pyc | Bin 11857 -> 0 bytes .../rich/__pycache__/cells.cpython-312.pyc | Bin 5617 -> 0 bytes .../rich/__pycache__/color.cpython-312.pyc | Bin 26569 -> 0 bytes .../__pycache__/color_triplet.cpython-312.pyc | Bin 1700 -> 0 bytes .../rich/__pycache__/columns.cpython-312.pyc | Bin 8586 -> 0 bytes .../rich/__pycache__/console.cpython-312.pyc | Bin 113792 -> 0 bytes .../__pycache__/constrain.cpython-312.pyc | Bin 2257 -> 0 bytes .../__pycache__/containers.cpython-312.pyc | Bin 9225 -> 0 bytes .../rich/__pycache__/control.cpython-312.pyc | Bin 10928 -> 0 bytes .../default_styles.cpython-312.pyc | Bin 10372 -> 0 bytes .../rich/__pycache__/diagnose.cpython-312.pyc | Bin 1486 -> 0 bytes .../rich/__pycache__/emoji.cpython-312.pyc | Bin 4208 -> 0 bytes .../rich/__pycache__/errors.cpython-312.pyc | Bin 1844 -> 0 bytes .../__pycache__/file_proxy.cpython-312.pyc | Bin 3576 -> 0 bytes .../rich/__pycache__/filesize.cpython-312.pyc | Bin 3081 -> 0 bytes .../__pycache__/highlighter.cpython-312.pyc | Bin 9897 -> 0 bytes .../rich/__pycache__/json.cpython-312.pyc | Bin 6034 -> 0 bytes .../rich/__pycache__/jupyter.cpython-312.pyc | Bin 5208 -> 0 bytes .../rich/__pycache__/layout.cpython-312.pyc | Bin 20219 -> 0 bytes .../rich/__pycache__/live.cpython-312.pyc | Bin 19142 -> 0 bytes .../__pycache__/live_render.cpython-312.pyc | Bin 4893 -> 0 bytes .../rich/__pycache__/logging.cpython-312.pyc | Bin 13553 -> 0 bytes .../rich/__pycache__/markup.cpython-312.pyc | Bin 9297 -> 0 bytes .../rich/__pycache__/measure.cpython-312.pyc | Bin 6375 -> 0 bytes .../rich/__pycache__/padding.cpython-312.pyc | Bin 7133 -> 0 bytes .../rich/__pycache__/pager.cpython-312.pyc | Bin 1819 -> 0 bytes .../rich/__pycache__/palette.cpython-312.pyc | Bin 5313 -> 0 bytes .../rich/__pycache__/panel.cpython-312.pyc | Bin 12096 -> 0 bytes .../rich/__pycache__/pretty.cpython-312.pyc | Bin 40055 -> 0 bytes .../rich/__pycache__/progress.cpython-312.pyc | Bin 75077 -> 0 bytes .../__pycache__/progress_bar.cpython-312.pyc | Bin 10388 -> 0 bytes .../rich/__pycache__/prompt.cpython-312.pyc | Bin 14780 -> 0 bytes .../rich/__pycache__/protocol.cpython-312.pyc | Bin 1791 -> 0 bytes .../rich/__pycache__/region.cpython-312.pyc | Bin 566 -> 0 bytes .../rich/__pycache__/repr.cpython-312.pyc | Bin 6625 -> 0 bytes .../rich/__pycache__/rule.cpython-312.pyc | Bin 6567 -> 0 bytes .../rich/__pycache__/scope.cpython-312.pyc | Bin 3829 -> 0 bytes .../rich/__pycache__/screen.cpython-312.pyc | Bin 2483 -> 0 bytes .../rich/__pycache__/segment.cpython-312.pyc | Bin 28160 -> 0 bytes .../rich/__pycache__/spinner.cpython-312.pyc | Bin 6063 -> 0 bytes .../rich/__pycache__/status.cpython-312.pyc | Bin 6067 -> 0 bytes .../rich/__pycache__/style.cpython-312.pyc | Bin 33513 -> 0 bytes .../rich/__pycache__/styled.cpython-312.pyc | Bin 2138 -> 0 bytes .../rich/__pycache__/syntax.cpython-312.pyc | Bin 39611 -> 0 bytes .../rich/__pycache__/table.cpython-312.pyc | Bin 43583 -> 0 bytes .../terminal_theme.cpython-312.pyc | Bin 3347 -> 0 bytes .../rich/__pycache__/text.cpython-312.pyc | Bin 58962 -> 0 bytes .../rich/__pycache__/theme.cpython-312.pyc | Bin 6339 -> 0 bytes .../rich/__pycache__/themes.cpython-312.pyc | Bin 313 -> 0 bytes .../__pycache__/traceback.cpython-312.pyc | Bin 31547 -> 0 bytes .../rich/__pycache__/tree.cpython-312.pyc | Bin 11438 -> 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 | 76 - .../pip/_vendor/rich/_extension.py | 10 - .../site-packages/pip/_vendor/rich/_fileno.py | 24 - .../pip/_vendor/rich/_inspect.py | 270 - .../pip/_vendor/rich/_log_render.py | 94 - .../site-packages/pip/_vendor/rich/_loop.py | 43 - .../pip/_vendor/rich/_null_file.py | 69 - .../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 - .../site-packages/pip/_vendor/rich/abc.py | 33 - .../site-packages/pip/_vendor/rich/align.py | 311 - .../site-packages/pip/_vendor/rich/ansi.py | 240 - .../site-packages/pip/_vendor/rich/bar.py | 94 - .../site-packages/pip/_vendor/rich/box.py | 517 - .../site-packages/pip/_vendor/rich/cells.py | 154 - .../site-packages/pip/_vendor/rich/color.py | 622 -- .../pip/_vendor/rich/color_triplet.py | 38 - .../site-packages/pip/_vendor/rich/columns.py | 187 - .../site-packages/pip/_vendor/rich/console.py | 2633 ----- .../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 | 190 - .../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 | 57 - .../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 | 443 - .../site-packages/pip/_vendor/rich/live.py | 375 - .../pip/_vendor/rich/live_render.py | 113 - .../site-packages/pip/_vendor/rich/logging.py | 289 - .../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 | 308 - .../site-packages/pip/_vendor/rich/pretty.py | 994 -- .../pip/_vendor/rich/progress.py | 1702 ---- .../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 | 149 - .../site-packages/pip/_vendor/rich/rule.py | 130 - .../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 | 137 - .../site-packages/pip/_vendor/rich/status.py | 132 - .../site-packages/pip/_vendor/rich/style.py | 796 -- .../site-packages/pip/_vendor/rich/styled.py | 42 - .../site-packages/pip/_vendor/rich/syntax.py | 948 -- .../site-packages/pip/_vendor/rich/table.py | 1002 -- .../pip/_vendor/rich/terminal_theme.py | 153 - .../site-packages/pip/_vendor/rich/text.py | 1307 --- .../site-packages/pip/_vendor/rich/theme.py | 115 - .../site-packages/pip/_vendor/rich/themes.py | 5 - .../pip/_vendor/rich/traceback.py | 756 -- .../site-packages/pip/_vendor/rich/tree.py | 251 - .../site-packages/pip/_vendor/six.py | 998 -- .../pip/_vendor/tenacity/__init__.py | 608 -- .../__pycache__/__init__.cpython-312.pyc | Bin 27085 -> 0 bytes .../__pycache__/_asyncio.cpython-312.pyc | Bin 4805 -> 0 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 2314 -> 0 bytes .../__pycache__/after.cpython-312.pyc | Bin 1623 -> 0 bytes .../__pycache__/before.cpython-312.pyc | Bin 1463 -> 0 bytes .../__pycache__/before_sleep.cpython-312.pyc | Bin 2301 -> 0 bytes .../tenacity/__pycache__/nap.cpython-312.pyc | Bin 1411 -> 0 bytes .../__pycache__/retry.cpython-312.pyc | Bin 14280 -> 0 bytes .../tenacity/__pycache__/stop.cpython-312.pyc | Bin 5567 -> 0 bytes .../__pycache__/tornadoweb.cpython-312.pyc | Bin 2585 -> 0 bytes .../tenacity/__pycache__/wait.cpython-312.pyc | Bin 12412 -> 0 bytes .../pip/_vendor/tenacity/_asyncio.py | 94 - .../pip/_vendor/tenacity/_utils.py | 76 - .../pip/_vendor/tenacity/after.py | 51 - .../pip/_vendor/tenacity/before.py | 46 - .../pip/_vendor/tenacity/before_sleep.py | 71 - .../site-packages/pip/_vendor/tenacity/nap.py | 43 - .../pip/_vendor/tenacity/retry.py | 272 - .../pip/_vendor/tenacity/stop.py | 103 - .../pip/_vendor/tenacity/tornadoweb.py | 59 - .../pip/_vendor/tenacity/wait.py | 228 - .../pip/_vendor/tomli/__init__.py | 11 - .../__pycache__/__init__.cpython-312.pyc | Bin 383 -> 0 bytes .../tomli/__pycache__/_parser.cpython-312.pyc | Bin 26926 -> 0 bytes .../tomli/__pycache__/_re.cpython-312.pyc | Bin 3907 -> 0 bytes .../tomli/__pycache__/_types.cpython-312.pyc | Bin 365 -> 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/truststore/__init__.py | 13 - .../__pycache__/__init__.cpython-312.pyc | Bin 617 -> 0 bytes .../__pycache__/_api.cpython-312.pyc | Bin 15796 -> 0 bytes .../__pycache__/_macos.cpython-312.pyc | Bin 16661 -> 0 bytes .../__pycache__/_openssl.cpython-312.pyc | Bin 2214 -> 0 bytes .../_ssl_constants.cpython-312.pyc | Bin 1098 -> 0 bytes .../__pycache__/_windows.cpython-312.pyc | Bin 15505 -> 0 bytes .../pip/_vendor/truststore/_api.py | 302 - .../pip/_vendor/truststore/_macos.py | 501 - .../pip/_vendor/truststore/_openssl.py | 66 - .../pip/_vendor/truststore/_ssl_constants.py | 31 - .../pip/_vendor/truststore/_windows.py | 554 -- .../pip/_vendor/typing_extensions.py | 3072 ------ .../pip/_vendor/urllib3/__init__.py | 102 - .../__pycache__/__init__.cpython-312.pyc | Bin 3404 -> 0 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 15930 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 217 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 20406 -> 0 bytes .../connectionpool.cpython-312.pyc | Bin 36278 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 13492 -> 0 bytes .../__pycache__/fields.cpython-312.pyc | Bin 10412 -> 0 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 4017 -> 0 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 20301 -> 0 bytes .../__pycache__/request.cpython-312.pyc | Bin 7293 -> 0 bytes .../__pycache__/response.cpython-312.pyc | Bin 33967 -> 0 bytes .../pip/_vendor/urllib3/_collections.py | 337 - .../pip/_vendor/urllib3/_version.py | 2 - .../pip/_vendor/urllib3/connection.py | 572 -- .../pip/_vendor/urllib3/connectionpool.py | 1132 --- .../pip/_vendor/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 197 -> 0 bytes .../_appengine_environ.cpython-312.pyc | Bin 1847 -> 0 bytes .../__pycache__/appengine.cpython-312.pyc | Bin 11563 -> 0 bytes .../__pycache__/ntlmpool.cpython-312.pyc | Bin 5718 -> 0 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 24449 -> 0 bytes .../securetransport.cpython-312.pyc | Bin 35555 -> 0 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 7510 -> 0 bytes .../urllib3/contrib/_appengine_environ.py | 36 - .../contrib/_securetransport/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 214 -> 0 bytes .../__pycache__/bindings.cpython-312.pyc | Bin 17426 -> 0 bytes .../__pycache__/low_level.cpython-312.pyc | Bin 14800 -> 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 | 518 - .../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-312.pyc | Bin 198 -> 0 bytes .../packages/__pycache__/six.cpython-312.pyc | Bin 41318 -> 0 bytes .../urllib3/packages/backports/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 208 -> 0 bytes .../__pycache__/makefile.cpython-312.pyc | Bin 1824 -> 0 bytes .../weakref_finalize.cpython-312.pyc | Bin 7330 -> 0 bytes .../urllib3/packages/backports/makefile.py | 51 - .../packages/backports/weakref_finalize.py | 155 - .../pip/_vendor/urllib3/packages/six.py | 1076 -- .../pip/_vendor/urllib3/poolmanager.py | 537 - .../pip/_vendor/urllib3/request.py | 191 - .../pip/_vendor/urllib3/response.py | 879 -- .../pip/_vendor/urllib3/util/__init__.py | 49 - .../util/__pycache__/__init__.cpython-312.pyc | Bin 1145 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 4755 -> 0 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 1551 -> 0 bytes .../util/__pycache__/queue.cpython-312.pyc | Bin 1351 -> 0 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 4182 -> 0 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 2988 -> 0 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 21717 -> 0 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 15102 -> 0 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 5070 -> 0 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 10771 -> 0 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 11138 -> 0 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 15794 -> 0 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 4402 -> 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 | 622 -- .../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 | 271 - .../pip/_vendor/urllib3/util/url.py | 435 - .../pip/_vendor/urllib3/util/wait.py | 152 - .../site-packages/pip/_vendor/vendor.txt | 24 - .../pip/_vendor/webencodings/__init__.py | 342 - .../__pycache__/__init__.cpython-312.pyc | Bin 12000 -> 0 bytes .../__pycache__/labels.cpython-312.pyc | Bin 7131 -> 0 bytes .../__pycache__/mklabels.cpython-312.pyc | Bin 2698 -> 0 bytes .../__pycache__/tests.cpython-312.pyc | Bin 9250 -> 0 bytes .../x_user_defined.cpython-312.pyc | Bin 3294 -> 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 - .../lib/python3.12/site-packages/pip/py.typed | 4 - .../pydantic-2.11.1.dist-info/INSTALLER | 1 - .../pydantic-2.11.1.dist-info/METADATA | 679 -- .../pydantic-2.11.1.dist-info/RECORD | 215 - .../pydantic-2.11.1.dist-info/WHEEL | 4 - .../licenses/LICENSE | 21 - .../site-packages/pydantic/__init__.py | 445 - .../__pycache__/__init__.cpython-312.pyc | Bin 14183 -> 0 bytes .../__pycache__/_migration.cpython-312.pyc | Bin 10856 -> 0 bytes .../alias_generators.cpython-312.pyc | Bin 3283 -> 0 bytes .../__pycache__/aliases.cpython-312.pyc | Bin 6565 -> 0 bytes .../annotated_handlers.cpython-312.pyc | Bin 5489 -> 0 bytes .../class_validators.cpython-312.pyc | Bin 363 -> 0 bytes .../__pycache__/color.cpython-312.pyc | Bin 30146 -> 0 bytes .../__pycache__/config.cpython-312.pyc | Bin 7050 -> 0 bytes .../__pycache__/dataclasses.cpython-312.pyc | Bin 14870 -> 0 bytes .../datetime_parse.cpython-312.pyc | Bin 363 -> 0 bytes .../__pycache__/decorator.cpython-312.pyc | Bin 353 -> 0 bytes .../__pycache__/env_settings.cpython-312.pyc | Bin 359 -> 0 bytes .../error_wrappers.cpython-312.pyc | Bin 363 -> 0 bytes .../__pycache__/errors.cpython-312.pyc | Bin 7650 -> 0 bytes .../__pycache__/fields.cpython-312.pyc | Bin 63392 -> 0 bytes .../functional_serializers.cpython-312.pyc | Bin 17951 -> 0 bytes .../functional_validators.cpython-312.pyc | Bin 32163 -> 0 bytes .../__pycache__/generics.cpython-312.pyc | Bin 351 -> 0 bytes .../pydantic/__pycache__/json.cpython-312.pyc | Bin 343 -> 0 bytes .../__pycache__/json_schema.cpython-312.pyc | Bin 113873 -> 0 bytes .../pydantic/__pycache__/main.cpython-312.pyc | Bin 74474 -> 0 bytes .../pydantic/__pycache__/mypy.cpython-312.pyc | Bin 62046 -> 0 bytes .../__pycache__/networks.cpython-312.pyc | Bin 49557 -> 0 bytes .../__pycache__/parse.cpython-312.pyc | Bin 345 -> 0 bytes .../__pycache__/root_model.cpython-312.pyc | Bin 7834 -> 0 bytes .../__pycache__/schema.cpython-312.pyc | Bin 347 -> 0 bytes .../__pycache__/tools.cpython-312.pyc | Bin 345 -> 0 bytes .../__pycache__/type_adapter.cpython-312.pyc | Bin 31890 -> 0 bytes .../__pycache__/types.cpython-312.pyc | Bin 96474 -> 0 bytes .../__pycache__/typing.cpython-312.pyc | Bin 343 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 345 -> 0 bytes .../validate_call_decorator.cpython-312.pyc | Bin 5441 -> 0 bytes .../__pycache__/validators.cpython-312.pyc | Bin 355 -> 0 bytes .../__pycache__/version.cpython-312.pyc | Bin 4144 -> 0 bytes .../__pycache__/warnings.cpython-312.pyc | Bin 5735 -> 0 bytes .../pydantic/_internal/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 188 -> 0 bytes .../__pycache__/_config.cpython-312.pyc | Bin 15126 -> 0 bytes .../_core_metadata.cpython-312.pyc | Bin 4608 -> 0 bytes .../__pycache__/_core_utils.cpython-312.pyc | Bin 8057 -> 0 bytes .../__pycache__/_dataclasses.cpython-312.pyc | Bin 9555 -> 0 bytes .../__pycache__/_decorators.cpython-312.pyc | Bin 35547 -> 0 bytes .../_decorators_v1.cpython-312.pyc | Bin 8589 -> 0 bytes .../_discriminated_union.cpython-312.pyc | Bin 20854 -> 0 bytes .../_docs_extraction.cpython-312.pyc | Bin 5203 -> 0 bytes .../__pycache__/_fields.cpython-312.pyc | Bin 18103 -> 0 bytes .../__pycache__/_forward_ref.cpython-312.pyc | Bin 1297 -> 0 bytes .../_generate_schema.cpython-312.pyc | Bin 132576 -> 0 bytes .../__pycache__/_generics.cpython-312.pyc | Bin 24328 -> 0 bytes .../__pycache__/_git.cpython-312.pyc | Bin 1558 -> 0 bytes .../__pycache__/_import_utils.cpython-312.pyc | Bin 816 -> 0 bytes .../_internal_dataclass.cpython-312.pyc | Bin 337 -> 0 bytes .../_known_annotated_metadata.cpython-312.pyc | Bin 14119 -> 0 bytes .../__pycache__/_mock_val_ser.cpython-312.pyc | Bin 11098 -> 0 bytes .../_model_construction.cpython-312.pyc | Bin 33935 -> 0 bytes .../_namespace_utils.cpython-312.pyc | Bin 12299 -> 0 bytes .../__pycache__/_repr.cpython-312.pyc | Bin 7688 -> 0 bytes .../_schema_gather.cpython-312.pyc | Bin 7523 -> 0 bytes .../_schema_generation_shared.cpython-312.pyc | Bin 6214 -> 0 bytes .../__pycache__/_serializers.cpython-312.pyc | Bin 2109 -> 0 bytes .../__pycache__/_signature.cpython-312.pyc | Bin 6757 -> 0 bytes .../__pycache__/_typing_extra.cpython-312.pyc | Bin 27382 -> 0 bytes .../__pycache__/_utils.cpython-312.pyc | Bin 19197 -> 0 bytes .../_validate_call.cpython-312.pyc | Bin 6975 -> 0 bytes .../__pycache__/_validators.cpython-312.pyc | Bin 23004 -> 0 bytes .../pydantic/_internal/_config.py | 373 - .../pydantic/_internal/_core_metadata.py | 97 - .../pydantic/_internal/_core_utils.py | 182 - .../pydantic/_internal/_dataclasses.py | 235 - .../pydantic/_internal/_decorators.py | 838 -- .../pydantic/_internal/_decorators_v1.py | 174 - .../_internal/_discriminated_union.py | 479 - .../pydantic/_internal/_docs_extraction.py | 108 - .../pydantic/_internal/_fields.py | 459 - .../pydantic/_internal/_forward_ref.py | 23 - .../pydantic/_internal/_generate_schema.py | 2862 ------ .../pydantic/_internal/_generics.py | 547 -- .../site-packages/pydantic/_internal/_git.py | 27 - .../pydantic/_internal/_import_utils.py | 20 - .../pydantic/_internal/_internal_dataclass.py | 7 - .../_internal/_known_annotated_metadata.py | 397 - .../pydantic/_internal/_mock_val_ser.py | 228 - .../pydantic/_internal/_model_construction.py | 792 -- .../pydantic/_internal/_namespace_utils.py | 293 - .../site-packages/pydantic/_internal/_repr.py | 125 - .../pydantic/_internal/_schema_gather.py | 204 - .../_internal/_schema_generation_shared.py | 125 - .../pydantic/_internal/_serializers.py | 53 - .../pydantic/_internal/_signature.py | 188 - .../pydantic/_internal/_typing_extra.py | 714 -- .../pydantic/_internal/_utils.py | 429 - .../pydantic/_internal/_validate_call.py | 140 - .../pydantic/_internal/_validators.py | 532 - .../site-packages/pydantic/_migration.py | 308 - .../pydantic/alias_generators.py | 62 - .../site-packages/pydantic/aliases.py | 135 - .../pydantic/annotated_handlers.py | 122 - .../pydantic/class_validators.py | 5 - .../site-packages/pydantic/color.py | 604 -- .../site-packages/pydantic/config.py | 1213 --- .../site-packages/pydantic/dataclasses.py | 374 - .../site-packages/pydantic/datetime_parse.py | 5 - .../site-packages/pydantic/decorator.py | 5 - .../pydantic/deprecated/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 189 -> 0 bytes .../class_validators.cpython-312.pyc | Bin 11713 -> 0 bytes .../__pycache__/config.cpython-312.pyc | Bin 4066 -> 0 bytes .../copy_internals.cpython-312.pyc | Bin 8645 -> 0 bytes .../__pycache__/decorator.cpython-312.pyc | Bin 14027 -> 0 bytes .../__pycache__/json.cpython-312.pyc | Bin 6185 -> 0 bytes .../__pycache__/parse.cpython-312.pyc | Bin 3395 -> 0 bytes .../__pycache__/tools.cpython-312.pyc | Bin 3531 -> 0 bytes .../pydantic/deprecated/class_validators.py | 256 - .../pydantic/deprecated/config.py | 72 - .../pydantic/deprecated/copy_internals.py | 224 - .../pydantic/deprecated/decorator.py | 284 - .../site-packages/pydantic/deprecated/json.py | 141 - .../pydantic/deprecated/parse.py | 80 - .../pydantic/deprecated/tools.py | 103 - .../site-packages/pydantic/env_settings.py | 5 - .../site-packages/pydantic/error_wrappers.py | 5 - .../site-packages/pydantic/errors.py | 190 - .../pydantic/experimental/__init__.py | 10 - .../__pycache__/__init__.cpython-312.pyc | Bin 559 -> 0 bytes .../arguments_schema.cpython-312.pyc | Bin 2395 -> 0 bytes .../__pycache__/pipeline.cpython-312.pyc | Bin 34760 -> 0 bytes .../pydantic/experimental/arguments_schema.py | 44 - .../pydantic/experimental/pipeline.py | 667 -- .../site-packages/pydantic/fields.py | 1542 --- .../pydantic/functional_serializers.py | 450 - .../pydantic/functional_validators.py | 828 -- .../site-packages/pydantic/generics.py | 5 - .../python3.12/site-packages/pydantic/json.py | 5 - .../site-packages/pydantic/json_schema.py | 2695 ----- .../python3.12/site-packages/pydantic/main.py | 1772 ---- .../python3.12/site-packages/pydantic/mypy.py | 1373 --- .../site-packages/pydantic/networks.py | 1312 --- .../site-packages/pydantic/parse.py | 5 - .../site-packages/pydantic/plugin/__init__.py | 188 - .../__pycache__/__init__.cpython-312.pyc | Bin 8506 -> 0 bytes .../__pycache__/_loader.cpython-312.pyc | Bin 2405 -> 0 bytes .../_schema_validator.cpython-312.pyc | Bin 6931 -> 0 bytes .../site-packages/pydantic/plugin/_loader.py | 57 - .../pydantic/plugin/_schema_validator.py | 140 - .../site-packages/pydantic/py.typed | 0 .../site-packages/pydantic/root_model.py | 157 - .../site-packages/pydantic/schema.py | 5 - .../site-packages/pydantic/tools.py | 5 - .../site-packages/pydantic/type_adapter.py | 727 -- .../site-packages/pydantic/types.py | 3285 ------- .../site-packages/pydantic/typing.py | 5 - .../site-packages/pydantic/utils.py | 5 - .../site-packages/pydantic/v1/__init__.py | 131 - .../v1/__pycache__/__init__.cpython-312.pyc | Bin 2212 -> 0 bytes .../_hypothesis_plugin.cpython-312.pyc | Bin 20534 -> 0 bytes .../annotated_types.cpython-312.pyc | Bin 3865 -> 0 bytes .../class_validators.cpython-312.pyc | Bin 19664 -> 0 bytes .../v1/__pycache__/color.cpython-312.pyc | Bin 25819 -> 0 bytes .../v1/__pycache__/config.cpython-312.pyc | Bin 8392 -> 0 bytes .../__pycache__/dataclasses.cpython-312.pyc | Bin 22762 -> 0 bytes .../datetime_parse.cpython-312.pyc | Bin 10338 -> 0 bytes .../v1/__pycache__/decorator.cpython-312.pyc | Bin 13921 -> 0 bytes .../__pycache__/env_settings.cpython-312.pyc | Bin 17728 -> 0 bytes .../error_wrappers.cpython-312.pyc | Bin 8921 -> 0 bytes .../v1/__pycache__/errors.cpython-312.pyc | Bin 29590 -> 0 bytes .../v1/__pycache__/fields.cpython-312.pyc | Bin 57419 -> 0 bytes .../v1/__pycache__/generics.cpython-312.pyc | Bin 16985 -> 0 bytes .../v1/__pycache__/json.cpython-312.pyc | Bin 5222 -> 0 bytes .../v1/__pycache__/main.cpython-312.pyc | Bin 48162 -> 0 bytes .../v1/__pycache__/mypy.cpython-312.pyc | Bin 46484 -> 0 bytes .../v1/__pycache__/networks.cpython-312.pyc | Bin 29551 -> 0 bytes .../v1/__pycache__/parse.cpython-312.pyc | Bin 2739 -> 0 bytes .../v1/__pycache__/schema.cpython-312.pyc | Bin 48491 -> 0 bytes .../v1/__pycache__/tools.cpython-312.pyc | Bin 3872 -> 0 bytes .../v1/__pycache__/types.cpython-312.pyc | Bin 48494 -> 0 bytes .../v1/__pycache__/typing.cpython-312.pyc | Bin 22250 -> 0 bytes .../v1/__pycache__/utils.cpython-312.pyc | Bin 35237 -> 0 bytes .../v1/__pycache__/validators.cpython-312.pyc | Bin 30890 -> 0 bytes .../v1/__pycache__/version.cpython-312.pyc | Bin 1951 -> 0 bytes .../pydantic/v1/_hypothesis_plugin.py | 391 - .../pydantic/v1/annotated_types.py | 72 - .../pydantic/v1/class_validators.py | 361 - .../site-packages/pydantic/v1/color.py | 494 - .../site-packages/pydantic/v1/config.py | 191 - .../site-packages/pydantic/v1/dataclasses.py | 500 - .../pydantic/v1/datetime_parse.py | 248 - .../site-packages/pydantic/v1/decorator.py | 264 - .../site-packages/pydantic/v1/env_settings.py | 350 - .../pydantic/v1/error_wrappers.py | 161 - .../site-packages/pydantic/v1/errors.py | 646 -- .../site-packages/pydantic/v1/fields.py | 1253 --- .../site-packages/pydantic/v1/generics.py | 400 - .../site-packages/pydantic/v1/json.py | 112 - .../site-packages/pydantic/v1/main.py | 1107 --- .../site-packages/pydantic/v1/mypy.py | 949 -- .../site-packages/pydantic/v1/networks.py | 747 -- .../site-packages/pydantic/v1/parse.py | 66 - .../site-packages/pydantic/v1/py.typed | 0 .../site-packages/pydantic/v1/schema.py | 1163 --- .../site-packages/pydantic/v1/tools.py | 92 - .../site-packages/pydantic/v1/types.py | 1205 --- .../site-packages/pydantic/v1/typing.py | 608 -- .../site-packages/pydantic/v1/utils.py | 804 -- .../site-packages/pydantic/v1/validators.py | 768 -- .../site-packages/pydantic/v1/version.py | 38 - .../pydantic/validate_call_decorator.py | 116 - .../site-packages/pydantic/validators.py | 5 - .../site-packages/pydantic/version.py | 86 - .../site-packages/pydantic/warnings.py | 96 - .../pydantic_core-2.33.0.dist-info/INSTALLER | 1 - .../pydantic_core-2.33.0.dist-info/METADATA | 160 - .../pydantic_core-2.33.0.dist-info/RECORD | 12 - .../pydantic_core-2.33.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 21 - .../site-packages/pydantic_core/__init__.py | 144 - .../__pycache__/__init__.cpython-312.pyc | Bin 3094 -> 0 bytes .../__pycache__/core_schema.cpython-312.pyc | Bin 150559 -> 0 bytes ...antic_core.cpython-312-x86_64-linux-gnu.so | Bin 4786440 -> 0 bytes .../pydantic_core/_pydantic_core.pyi | 1039 -- .../pydantic_core/core_schema.py | 4325 -------- .../site-packages/pydantic_core/py.typed | 0 .../INSTALLER | 1 - .../LICENSE | 54 - .../METADATA | 204 - .../RECORD | 44 - .../WHEEL | 6 - .../top_level.txt | 1 - .../zip-safe | 1 - .../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 - .../site-packages/requests/__init__.py | 184 - .../__pycache__/__init__.cpython-312.pyc | Bin 5407 -> 0 bytes .../__pycache__/__version__.cpython-312.pyc | Bin 571 -> 0 bytes .../_internal_utils.cpython-312.pyc | Bin 2011 -> 0 bytes .../__pycache__/adapters.cpython-312.pyc | Bin 28351 -> 0 bytes .../requests/__pycache__/api.cpython-312.pyc | Bin 7191 -> 0 bytes .../requests/__pycache__/auth.cpython-312.pyc | Bin 13910 -> 0 bytes .../__pycache__/certs.cpython-312.pyc | Bin 653 -> 0 bytes .../__pycache__/compat.cpython-312.pyc | Bin 2072 -> 0 bytes .../__pycache__/cookies.cpython-312.pyc | Bin 25263 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 7572 -> 0 bytes .../requests/__pycache__/help.cpython-312.pyc | Bin 4314 -> 0 bytes .../__pycache__/hooks.cpython-312.pyc | Bin 1039 -> 0 bytes .../__pycache__/models.cpython-312.pyc | Bin 35393 -> 0 bytes .../__pycache__/packages.cpython-312.pyc | Bin 1126 -> 0 bytes .../__pycache__/sessions.cpython-312.pyc | Bin 27869 -> 0 bytes .../__pycache__/status_codes.cpython-312.pyc | Bin 6018 -> 0 bytes .../__pycache__/structures.cpython-312.pyc | Bin 5604 -> 0 bytes .../__pycache__/utils.cpython-312.pyc | Bin 36417 -> 0 bytes .../site-packages/requests/__version__.py | 14 - .../site-packages/requests/_internal_utils.py | 50 - .../site-packages/requests/adapters.py | 719 -- .../python3.12/site-packages/requests/api.py | 157 - .../python3.12/site-packages/requests/auth.py | 314 - .../site-packages/requests/certs.py | 17 - .../site-packages/requests/compat.py | 94 - .../site-packages/requests/cookies.py | 561 -- .../site-packages/requests/exceptions.py | 151 - .../python3.12/site-packages/requests/help.py | 134 - .../site-packages/requests/hooks.py | 33 - .../site-packages/requests/models.py | 1037 -- .../site-packages/requests/packages.py | 23 - .../site-packages/requests/sessions.py | 831 -- .../site-packages/requests/status_codes.py | 128 - .../site-packages/requests/structures.py | 99 - .../site-packages/requests/utils.py | 1096 --- .../six-1.17.0.dist-info/INSTALLER | 1 - .../six-1.17.0.dist-info/LICENSE | 18 - .../six-1.17.0.dist-info/METADATA | 43 - .../site-packages/six-1.17.0.dist-info/RECORD | 8 - .../site-packages/six-1.17.0.dist-info/WHEEL | 6 - .../six-1.17.0.dist-info/top_level.txt | 1 - venv/lib/python3.12/site-packages/six.py | 1003 -- .../sniffio-1.3.1.dist-info/INSTALLER | 1 - .../sniffio-1.3.1.dist-info/LICENSE | 3 - .../sniffio-1.3.1.dist-info/LICENSE.APACHE2 | 202 - .../sniffio-1.3.1.dist-info/LICENSE.MIT | 20 - .../sniffio-1.3.1.dist-info/METADATA | 104 - .../sniffio-1.3.1.dist-info/RECORD | 19 - .../sniffio-1.3.1.dist-info/WHEEL | 5 - .../sniffio-1.3.1.dist-info/top_level.txt | 1 - .../site-packages/sniffio/__init__.py | 17 - .../__pycache__/__init__.cpython-312.pyc | Bin 453 -> 0 bytes .../sniffio/__pycache__/_impl.cpython-312.pyc | Bin 3164 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 205 -> 0 bytes .../python3.12/site-packages/sniffio/_impl.py | 95 - .../site-packages/sniffio/_tests/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 184 -> 0 bytes .../__pycache__/test_sniffio.cpython-312.pyc | Bin 3913 -> 0 bytes .../sniffio/_tests/test_sniffio.py | 84 - .../site-packages/sniffio/_version.py | 3 - .../python3.12/site-packages/sniffio/py.typed | 0 .../soupsieve-2.6.dist-info/INSTALLER | 1 - .../soupsieve-2.6.dist-info/METADATA | 114 - .../soupsieve-2.6.dist-info/RECORD | 20 - .../soupsieve-2.6.dist-info/WHEEL | 4 - .../licenses/LICENSE.md | 21 - .../site-packages/soupsieve/__init__.py | 168 - .../site-packages/soupsieve/__meta__.py | 197 - .../__pycache__/__init__.cpython-312.pyc | Bin 6093 -> 0 bytes .../__pycache__/__meta__.cpython-312.pyc | Bin 8106 -> 0 bytes .../__pycache__/css_match.cpython-312.pyc | Bin 61880 -> 0 bytes .../__pycache__/css_parser.cpython-312.pyc | Bin 49563 -> 0 bytes .../__pycache__/css_types.cpython-312.pyc | Bin 17327 -> 0 bytes .../__pycache__/pretty.cpython-312.pyc | Bin 5046 -> 0 bytes .../__pycache__/util.cpython-312.pyc | Bin 4716 -> 0 bytes .../site-packages/soupsieve/css_match.py | 1582 --- .../site-packages/soupsieve/css_parser.py | 1289 --- .../site-packages/soupsieve/css_types.py | 407 - .../site-packages/soupsieve/pretty.py | 139 - .../site-packages/soupsieve/py.typed | 0 .../site-packages/soupsieve/util.py | 117 - .../INSTALLER | 1 - .../METADATA | 68 - .../typing_extensions-4.13.0.dist-info/RECORD | 7 - .../typing_extensions-4.13.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 279 - .../site-packages/typing_extensions.py | 4566 --------- .../INSTALLER | 1 - .../METADATA | 49 - .../typing_inspection-0.4.0.dist-info/RECORD | 13 - .../typing_inspection-0.4.0.dist-info/WHEEL | 4 - .../licenses/LICENSE | 21 - .../typing_inspection/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 187 -> 0 bytes .../__pycache__/introspection.cpython-312.pyc | Bin 16965 -> 0 bytes .../typing_objects.cpython-312.pyc | Bin 16918 -> 0 bytes .../typing_inspection/introspection.py | 548 -- .../site-packages/typing_inspection/py.typed | 0 .../typing_inspection/typing_objects.py | 582 -- .../typing_inspection/typing_objects.pyi | 396 - .../urllib3-2.3.0.dist-info/INSTALLER | 1 - .../urllib3-2.3.0.dist-info/METADATA | 154 - .../urllib3-2.3.0.dist-info/RECORD | 79 - .../urllib3-2.3.0.dist-info/WHEEL | 4 - .../licenses/LICENSE.txt | 21 - .../site-packages/urllib3/__init__.py | 211 - .../__pycache__/__init__.cpython-312.pyc | Bin 7302 -> 0 bytes .../_base_connection.cpython-312.pyc | Bin 6840 -> 0 bytes .../__pycache__/_collections.cpython-312.pyc | Bin 22561 -> 0 bytes .../_request_methods.cpython-312.pyc | Bin 10594 -> 0 bytes .../__pycache__/_version.cpython-312.pyc | Bin 579 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 36153 -> 0 bytes .../connectionpool.cpython-312.pyc | Bin 39727 -> 0 bytes .../__pycache__/exceptions.cpython-312.pyc | Bin 16095 -> 0 bytes .../__pycache__/fields.cpython-312.pyc | Bin 12014 -> 0 bytes .../__pycache__/filepost.cpython-312.pyc | Bin 3481 -> 0 bytes .../__pycache__/poolmanager.cpython-312.pyc | Bin 24066 -> 0 bytes .../__pycache__/response.cpython-312.pyc | Bin 51061 -> 0 bytes .../site-packages/urllib3/_base_connection.py | 165 - .../site-packages/urllib3/_collections.py | 479 - .../site-packages/urllib3/_request_methods.py | 278 - .../site-packages/urllib3/_version.py | 16 - .../site-packages/urllib3/connection.py | 1044 -- .../site-packages/urllib3/connectionpool.py | 1178 --- .../site-packages/urllib3/contrib/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 185 -> 0 bytes .../__pycache__/pyopenssl.cpython-312.pyc | Bin 27548 -> 0 bytes .../contrib/__pycache__/socks.cpython-312.pyc | Bin 8163 -> 0 bytes .../urllib3/contrib/emscripten/__init__.py | 16 - .../__pycache__/__init__.cpython-312.pyc | Bin 893 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 10234 -> 0 bytes .../__pycache__/fetch.cpython-312.pyc | Bin 28105 -> 0 bytes .../__pycache__/request.cpython-312.pyc | Bin 1413 -> 0 bytes .../__pycache__/response.cpython-312.pyc | Bin 12674 -> 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 | 285 - .../urllib3/contrib/pyopenssl.py | 554 -- .../site-packages/urllib3/contrib/socks.py | 228 - .../site-packages/urllib3/exceptions.py | 327 - .../site-packages/urllib3/fields.py | 341 - .../site-packages/urllib3/filepost.py | 89 - .../site-packages/urllib3/http2/__init__.py | 53 - .../__pycache__/__init__.cpython-312.pyc | Bin 1738 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 17045 -> 0 bytes .../http2/__pycache__/probe.cpython-312.pyc | Bin 3689 -> 0 bytes .../site-packages/urllib3/http2/connection.py | 356 - .../site-packages/urllib3/http2/probe.py | 87 - .../site-packages/urllib3/poolmanager.py | 637 -- .../python3.12/site-packages/urllib3/py.typed | 2 - .../site-packages/urllib3/response.py | 1278 --- .../site-packages/urllib3/util/__init__.py | 42 - .../util/__pycache__/__init__.cpython-312.pyc | Bin 998 -> 0 bytes .../__pycache__/connection.cpython-312.pyc | Bin 4688 -> 0 bytes .../util/__pycache__/proxy.cpython-312.pyc | Bin 1210 -> 0 bytes .../util/__pycache__/request.cpython-312.pyc | Bin 8165 -> 0 bytes .../util/__pycache__/response.cpython-312.pyc | Bin 2866 -> 0 bytes .../util/__pycache__/retry.cpython-312.pyc | Bin 20279 -> 0 bytes .../util/__pycache__/ssl_.cpython-312.pyc | Bin 16568 -> 0 bytes .../ssl_match_hostname.cpython-312.pyc | Bin 5550 -> 0 bytes .../__pycache__/ssltransport.cpython-312.pyc | Bin 13317 -> 0 bytes .../util/__pycache__/timeout.cpython-312.pyc | Bin 11682 -> 0 bytes .../util/__pycache__/url.cpython-312.pyc | Bin 16219 -> 0 bytes .../util/__pycache__/util.cpython-312.pyc | Bin 1987 -> 0 bytes .../util/__pycache__/wait.cpython-312.pyc | Bin 3433 -> 0 bytes .../site-packages/urllib3/util/connection.py | 137 - .../site-packages/urllib3/util/proxy.py | 43 - .../site-packages/urllib3/util/request.py | 258 - .../site-packages/urllib3/util/response.py | 101 - .../site-packages/urllib3/util/retry.py | 533 - .../site-packages/urllib3/util/ssl_.py | 504 - .../urllib3/util/ssl_match_hostname.py | 159 - .../urllib3/util/ssltransport.py | 271 - .../site-packages/urllib3/util/timeout.py | 275 - .../site-packages/urllib3/util/url.py | 469 - .../site-packages/urllib3/util/util.py | 42 - .../site-packages/urllib3/util/wait.py | 124 - venv/lib64 | 1 - venv/pyvenv.cfg | 5 - 2651 files changed, 401719 deletions(-) delete mode 100644 README.md delete mode 100644 __pycache__/post_process.cpython-312.pyc delete mode 100644 agents/__init__.py delete mode 100644 agents/__pycache__/__init__.cpython-312.pyc delete mode 100644 agents/__pycache__/agent_analyse_image.cpython-312.pyc delete mode 100644 agents/__pycache__/agent_base.cpython-312.pyc delete mode 100644 agents/__pycache__/agent_filtre_images.cpython-312.pyc delete mode 100644 agents/__pycache__/agent_question_reponse.cpython-312.pyc delete mode 100644 agents/agent_analyse_image.py delete mode 100644 agents/agent_base.py delete mode 100644 agents/agent_filtre_images.py delete mode 100644 agents/agent_question_reponse.py delete mode 100644 config.json delete mode 100644 config.json.example delete mode 100644 extract_ticket.log delete mode 100644 filter_images.log delete mode 100644 llm-ticket3.code-workspace delete mode 100644 llm/__init__.py delete mode 100644 llm/__pycache__/__init__.cpython-312.pyc delete mode 100644 llm/__pycache__/llm_base.cpython-312.pyc delete mode 100644 llm/__pycache__/mistral.cpython-312.pyc delete mode 100644 llm/__pycache__/pixtral.cpython-312.pyc delete mode 100644 llm/llm_base.py delete mode 100644 llm/mistral.py delete mode 100644 llm/pixtral.py delete mode 100644 main.py delete mode 100644 output/ticket_T0140/attachments/31975_ecran - 2020-04-07T120505.164.png delete mode 100644 output/ticket_T0140/attachments_info.json delete mode 100644 output/ticket_T0140/messages.json delete mode 100644 output/ticket_T0140/messages.json.backup delete mode 100644 output/ticket_T0140/questions_reponses.md delete mode 100644 output/ticket_T0140/rapport/ticket_analysis.json delete mode 100644 output/ticket_T0140/rapport/ticket_analysis.md delete mode 100644 output/ticket_T0140/ticket_info.json delete mode 100644 output/ticket_T0150/attachments_info.json delete mode 100644 output/ticket_T0150/messages.json delete mode 100644 output/ticket_T0150/messages.json.backup delete mode 100644 output/ticket_T0150/messages.json.original delete mode 100644 output/ticket_T0150/questions_reponses.md delete mode 100644 output/ticket_T0150/rapport/ticket_analysis.json delete mode 100644 output/ticket_T0150/rapport/ticket_analysis.md delete mode 100644 output/ticket_T0150/ticket_info.json delete mode 100644 output/ticket_T0167/attachments/32380_image001.png delete mode 100644 output/ticket_T0167/attachments/32382_Problème partie.png delete mode 100644 output/ticket_T0167/attachments_info.json delete mode 100644 output/ticket_T0167/messages.json delete mode 100644 output/ticket_T0167/messages.json.backup delete mode 100644 output/ticket_T0167/questions_reponses.md delete mode 100644 output/ticket_T0167/rapport/ticket_analysis.json delete mode 100644 output/ticket_T0167/rapport/ticket_analysis.md delete mode 100644 output/ticket_T0167/ticket_info.json delete mode 100644 output/ticket_T11067/attachments/144792_image003.png delete mode 100644 output/ticket_T11067/attachments/144794_image004.jpg delete mode 100644 output/ticket_T11067/attachments/144796_image.png delete mode 100644 output/ticket_T11067/attachments_info.json delete mode 100644 output/ticket_T11067/messages.json delete mode 100644 output/ticket_T11067/messages.json.backup delete mode 100644 output/ticket_T11067/questions_reponses.md delete mode 100644 output/ticket_T11067/rapport/ticket_analysis.json delete mode 100644 output/ticket_T11067/rapport/ticket_analysis.md delete mode 100644 output/ticket_T11067/ticket_info.json delete mode 100644 output/ticket_T11094/attachments/144918_image.png delete mode 100644 output/ticket_T11094/attachments_info.json delete mode 100644 output/ticket_T11094/messages.json delete mode 100644 output/ticket_T11094/messages.json.backup delete mode 100644 output/ticket_T11094/questions_reponses.md delete mode 100644 output/ticket_T11094/rapport/ticket_analysis.json delete mode 100644 output/ticket_T11094/rapport/ticket_analysis.md delete mode 100644 output/ticket_T11094/ticket_info.json delete mode 100644 output_processed/ticket_T0167/messages.json delete mode 100644 output_processed/ticket_T0167/pretraitement_rapport.json delete mode 100644 output_processed/ticket_T0167/ticket_info.json delete mode 100644 post_process.py delete mode 100644 requirements.txt delete mode 100644 scripts/analyze_image_contexte.py delete mode 100644 scripts/analyze_ticket.py delete mode 100644 scripts/extract_question_reponse.py delete mode 100644 scripts/extract_ticket.py delete mode 100644 scripts/filter_images.py delete mode 100644 scripts/processus_complet.py delete mode 100644 utils/__init__.py delete mode 100644 utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 utils/__pycache__/ticket_analyzer.cpython-312.pyc delete mode 100644 utils/__pycache__/ticket_manager.cpython-312.pyc delete mode 100644 utils/ticket_analyzer.py delete mode 100644 utils/ticket_manager.py delete mode 100644 venv/bin/Activate.ps1 delete mode 100644 venv/bin/activate delete mode 100644 venv/bin/activate.csh delete mode 100644 venv/bin/activate.fish delete mode 100755 venv/bin/httpx delete mode 100755 venv/bin/normalizer delete mode 100755 venv/bin/pip delete mode 100755 venv/bin/pip3 delete mode 100755 venv/bin/pip3.12 delete mode 120000 venv/bin/python delete mode 120000 venv/bin/python3 delete mode 120000 venv/bin/python3.12 delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/AUTHORS delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/REQUESTED delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/README.rst delete mode 100644 venv/lib/python3.12/site-packages/__pycache__/six.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/__pycache__/typing_extensions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/annotated_types/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/annotated_types/py.typed delete mode 100644 venv/lib/python3.12/site-packages/annotated_types/test_cases.py delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/entry_points.txt delete mode 100644 venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/anyio/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/from_thread.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/lowlevel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/pytest_plugin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/to_process.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/__pycache__/to_thread.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_backends/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_backends/_trio.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_eventloop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_resources.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_sockets.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_subprocesses.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_synchronization.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_asyncio_selector_thread.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_eventloop.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_fileio.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_resources.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_signals.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_sockets.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_streams.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_subprocesses.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_synchronization.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_tasks.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_tempfile.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_testing.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/_core/_typedattr.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_resources.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_sockets.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_streams.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_tasks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_testing.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_eventloop.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_resources.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_sockets.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_streams.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_subprocesses.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_tasks.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/abc/_testing.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/from_thread.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/lowlevel.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/py.typed delete mode 100644 venv/lib/python3.12/site-packages/anyio/pytest_plugin.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/file.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/text.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/buffered.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/file.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/memory.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/stapled.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/text.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/streams/tls.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/to_interpreter.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/to_process.py delete mode 100644 venv/lib/python3.12/site-packages/anyio/to_thread.py delete mode 100644 venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/AUTHORS delete mode 100644 venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/REQUESTED delete mode 100644 venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/bs4/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/_deprecation.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/_typing.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/_warnings.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/css.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/dammit.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/diagnose.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/element.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/filter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/__pycache__/formatter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/_deprecation.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/_typing.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/_warnings.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/__pycache__/_html5lib.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/__pycache__/_htmlparser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/__pycache__/_lxml.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/_html5lib.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/_htmlparser.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/builder/_lxml.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/css.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/dammit.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/diagnose.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/element.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/filter.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/formatter.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/py.typed delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_builder.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_css.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_dammit.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_element.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_filter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_formatter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_fuzz.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_html5lib.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_htmlparser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_lxml.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_navigablestring.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_pageelement.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_soup.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_tag.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_tree.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_builder.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_builder_registry.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_css.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_dammit.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_element.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_filter.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_formatter.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_fuzz.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_html5lib.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_htmlparser.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_lxml.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_navigablestring.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_pageelement.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_soup.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_tag.py delete mode 100644 venv/lib/python3.12/site-packages/bs4/tests/test_tree.py delete mode 100644 venv/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/certifi-2025.1.31.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/certifi/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/certifi/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/certifi/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/certifi/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/certifi/__pycache__/core.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/certifi/cacert.pem delete mode 100644 venv/lib/python3.12/site-packages/certifi/core.py delete mode 100644 venv/lib/python3.12/site-packages/certifi/py.typed delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/entry_points.txt delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer-3.4.1.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/cd.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/constant.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/legacy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/md.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/api.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cd.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/cli/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/constant.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/legacy.py delete mode 100755 venv/lib/python3.12/site-packages/charset_normalizer/md.cpython-312-x86_64-linux-gnu.so delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/md.py delete mode 100755 venv/lib/python3.12/site-packages/charset_normalizer/md__mypyc.cpython-312-x86_64-linux-gnu.so delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/models.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/py.typed delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/utils.py delete mode 100644 venv/lib/python3.12/site-packages/charset_normalizer/version.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/_common.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/easter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/relativedelta.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/rrule.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/tzwin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/_common.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/_version.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/easter.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/parser/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/parser/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/parser/__pycache__/_parser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/parser/__pycache__/isoparser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/parser/_parser.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/parser/isoparser.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/relativedelta.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/rrule.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/__pycache__/_common.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/__pycache__/_factories.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/__pycache__/tz.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/__pycache__/win.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/_common.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/_factories.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/tz.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tz/win.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/tzwin.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/utils.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/zoneinfo/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/dateutil/zoneinfo/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/zoneinfo/__pycache__/rebuild.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz delete mode 100644 venv/lib/python3.12/site-packages/dateutil/zoneinfo/rebuild.py delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport-0.2.2.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport-0.2.2.dist-info/LICENSE.txt delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport-0.2.2.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport-0.2.2.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport-0.2.2.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport-0.2.2.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/__pycache__/eval_type_backport.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/eval_type_backport.py delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/py.typed delete mode 100644 venv/lib/python3.12/site-packages/eval_type_backport/version.py delete mode 100644 venv/lib/python3.12/site-packages/h11-0.14.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/h11-0.14.0.dist-info/LICENSE.txt delete mode 100644 venv/lib/python3.12/site-packages/h11-0.14.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/h11-0.14.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/h11-0.14.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/h11-0.14.0.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/h11/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_abnf.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_events.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_headers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_readers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_receivebuffer.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_state.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/__pycache__/_writers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/_abnf.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_connection.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_events.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_headers.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_readers.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_receivebuffer.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_state.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_util.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_version.py delete mode 100644 venv/lib/python3.12/site-packages/h11/_writers.py delete mode 100644 venv/lib/python3.12/site-packages/h11/py.typed delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/helpers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_against_stdlib_http.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_events.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_headers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_helpers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_io.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_receivebuffer.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_state.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/__pycache__/test_util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/data/test-file delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/helpers.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_against_stdlib_http.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_connection.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_events.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_headers.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_helpers.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_io.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_receivebuffer.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_state.py delete mode 100644 venv/lib/python3.12/site-packages/h11/tests/test_util.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore-1.0.7.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/httpcore-1.0.7.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/httpcore-1.0.7.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/httpcore-1.0.7.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/httpcore-1.0.7.dist-info/licenses/LICENSE.md delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_ssl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_synchronization.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_trace.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/__pycache__/_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_api.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/connection_pool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/http11.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/http2.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/http_proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/interfaces.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/__pycache__/socks_proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/connection.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/connection_pool.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/http11.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/http2.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/http_proxy.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/interfaces.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_async/socks_proxy.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/anyio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/auto.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/mock.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/sync.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/__pycache__/trio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/anyio.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/auto.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/base.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/mock.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/sync.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_backends/trio.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_models.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_ssl.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/connection_pool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/http11.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/http2.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/http_proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/interfaces.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/__pycache__/socks_proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/connection.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/connection_pool.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/http11.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/http2.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/http_proxy.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/interfaces.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_sync/socks_proxy.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_synchronization.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_trace.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/_utils.py delete mode 100644 venv/lib/python3.12/site-packages/httpcore/py.typed delete mode 100644 venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/entry_points.txt delete mode 100644 venv/lib/python3.12/site-packages/httpx-0.28.1.dist-info/licenses/LICENSE.md delete mode 100644 venv/lib/python3.12/site-packages/httpx/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/__version__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_auth.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_client.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_config.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_content.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_decoders.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_main.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_multipart.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_status_codes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_urlparse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_urls.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__pycache__/_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/__version__.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_api.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_auth.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_client.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_config.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_content.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_decoders.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_main.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_models.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_multipart.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_status_codes.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__pycache__/asgi.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__pycache__/default.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__pycache__/mock.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/__pycache__/wsgi.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/asgi.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/base.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/default.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/mock.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_transports/wsgi.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_types.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_urlparse.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_urls.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/_utils.py delete mode 100644 venv/lib/python3.12/site-packages/httpx/py.typed delete mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md delete mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/idna/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/codec.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/core.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/idnadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/intranges.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/package_data.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/__pycache__/uts46data.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/idna/codec.py delete mode 100644 venv/lib/python3.12/site-packages/idna/compat.py delete mode 100644 venv/lib/python3.12/site-packages/idna/core.py delete mode 100644 venv/lib/python3.12/site-packages/idna/idnadata.py delete mode 100644 venv/lib/python3.12/site-packages/idna/intranges.py delete mode 100644 venv/lib/python3.12/site-packages/idna/package_data.py delete mode 100644 venv/lib/python3.12/site-packages/idna/py.typed delete mode 100644 venv/lib/python3.12/site-packages/idna/uts46data.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai-1.6.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/mistralai-1.6.0.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/mistralai-1.6.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/mistralai-1.6.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/mistralai-1.6.0.dist-info/REQUESTED delete mode 100644 venv/lib/python3.12/site-packages/mistralai-1.6.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/agents.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/async_client.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/basesdk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/batch.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/chat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/classifiers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/client.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/embeddings.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/files.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/fim.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/fine_tuning.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/httpclient.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/jobs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/mistral_jobs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/models_.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/ocr.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/sdk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/sdkconfiguration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__pycache__/custom_user_agent.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__pycache__/deprecation_warning.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__pycache__/registration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__pycache__/sdkhooks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/__pycache__/types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/custom_user_agent.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/deprecation_warning.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/registration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/sdkhooks.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_hooks/types.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/_version.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/agents.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/async_client.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/basesdk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/batch.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/chat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/classifiers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/client.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/embeddings.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/README.md delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/__pycache__/struct_chat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/struct_chat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/tests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/tests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/tests/__pycache__/test_struct_chat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/tests/__pycache__/test_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/tests/test_struct_chat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/tests/test_utils.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/utils/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/utils/__pycache__/_pydantic_helper.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/utils/__pycache__/response_format.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/utils/_pydantic_helper.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/extra/utils/response_format.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/files.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/fim.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/fine_tuning.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/httpclient.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/jobs.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/mistral_jobs.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/agentscompletionrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/agentscompletionstreamrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/apiendpoint.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/archiveftmodelout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/assistantmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/basemodelcard.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/batcherror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/batchjobin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/batchjobout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/batchjobsout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/batchjobstatus.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/chatcompletionchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/chatcompletionrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/chatcompletionresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/chatcompletionstreamrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/chatmoderationrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/checkpointout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/classificationobject.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/classificationrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/classificationresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/completionchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/completionevent.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/completionresponsestreamchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/contentchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/delete_model_v1_models_model_id_deleteop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/deletefileout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/deletemodelout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/deltamessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/detailedjobout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/documenturlchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/embeddingrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/embeddingresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/embeddingresponsedata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/eventout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/filepurpose.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/files_api_routes_delete_fileop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/files_api_routes_download_fileop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/files_api_routes_get_signed_urlop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/files_api_routes_list_filesop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/files_api_routes_retrieve_fileop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/files_api_routes_upload_fileop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/fileschema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/filesignedurl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/fimcompletionrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/fimcompletionresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/fimcompletionstreamrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ftmodelcapabilitiesout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ftmodelcard.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ftmodelout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/function.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/functioncall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/functionname.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/githubrepositoryin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/githubrepositoryout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/httpvalidationerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/imageurl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/imageurlchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobmetadataout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_batch_cancel_batch_jobop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_batch_get_batch_jobop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_batch_get_batch_jobsop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_archive_fine_tuned_modelop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_cancel_fine_tuning_jobop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_create_fine_tuning_jobop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_get_fine_tuning_jobop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_get_fine_tuning_jobsop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_start_fine_tuning_jobop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_unarchive_fine_tuned_modelop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobs_api_routes_fine_tuning_update_fine_tuned_modelop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jobsout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/jsonschema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/legacyjobmetadataout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/listfilesout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/metricout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/modelcapabilities.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/modellist.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ocrimageobject.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ocrpagedimensions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ocrpageobject.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ocrrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ocrresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/ocrusageinfo.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/prediction.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/referencechunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/responseformat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/responseformats.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/retrieve_model_v1_models_model_id_getop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/retrievefileout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/sampletype.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/sdkerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/security.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/source.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/systemmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/textchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/tool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/toolcall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/toolchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/toolchoiceenum.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/toolmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/tooltypes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/trainingfile.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/trainingparameters.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/trainingparametersin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/unarchiveftmodelout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/updateftmodelin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/uploadfileout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/usageinfo.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/usermessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/validationerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/wandbintegration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/__pycache__/wandbintegrationout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/agentscompletionrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/agentscompletionstreamrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/apiendpoint.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/archiveftmodelout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/assistantmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/basemodelcard.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/batcherror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/batchjobin.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/batchjobout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/batchjobsout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/batchjobstatus.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/chatcompletionchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/chatcompletionrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/chatcompletionresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/chatcompletionstreamrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/chatmoderationrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/checkpointout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/classificationobject.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/classificationrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/classificationresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/completionchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/completionevent.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/completionresponsestreamchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/contentchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/delete_model_v1_models_model_id_deleteop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/deletefileout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/deletemodelout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/deltamessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/detailedjobout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/documenturlchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/embeddingrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/embeddingresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/embeddingresponsedata.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/eventout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/filepurpose.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/files_api_routes_delete_fileop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/files_api_routes_download_fileop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/files_api_routes_get_signed_urlop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/files_api_routes_list_filesop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/files_api_routes_retrieve_fileop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/files_api_routes_upload_fileop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/fileschema.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/filesignedurl.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/fimcompletionrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/fimcompletionresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/fimcompletionstreamrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ftmodelcapabilitiesout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ftmodelcard.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ftmodelout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/function.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/functioncall.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/functionname.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/githubrepositoryin.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/githubrepositoryout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/httpvalidationerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/imageurl.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/imageurlchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobin.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobmetadataout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_batch_cancel_batch_jobop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_batch_get_batch_jobop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_batch_get_batch_jobsop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_archive_fine_tuned_modelop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_cancel_fine_tuning_jobop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_create_fine_tuning_jobop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_get_fine_tuning_jobop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_get_fine_tuning_jobsop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_start_fine_tuning_jobop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_unarchive_fine_tuned_modelop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobs_api_routes_fine_tuning_update_fine_tuned_modelop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jobsout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/jsonschema.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/legacyjobmetadataout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/listfilesout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/metricout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/modelcapabilities.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/modellist.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ocrimageobject.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ocrpagedimensions.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ocrpageobject.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ocrrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ocrresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/ocrusageinfo.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/prediction.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/referencechunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/responseformat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/responseformats.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/retrieve_model_v1_models_model_id_getop.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/retrievefileout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/sampletype.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/sdkerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/security.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/source.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/systemmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/textchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/tool.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/toolcall.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/toolchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/toolchoiceenum.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/toolmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/tooltypes.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/trainingfile.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/trainingparameters.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/trainingparametersin.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/unarchiveftmodelout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/updateftmodelin.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/uploadfileout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/usageinfo.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/usermessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/validationerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/wandbintegration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models/wandbintegrationout.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/models_.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/ocr.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/py.typed delete mode 100644 venv/lib/python3.12/site-packages/mistralai/sdk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/sdkconfiguration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/types/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/types/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/types/__pycache__/basemodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/types/basemodel.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/annotations.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/enums.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/eventstreaming.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/forms.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/headers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/logger.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/queryparams.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/requestbodies.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/retries.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/security.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/serializers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/url.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/__pycache__/values.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/annotations.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/enums.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/eventstreaming.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/forms.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/headers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/logger.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/metadata.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/queryparams.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/requestbodies.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/retries.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/security.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/serializers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/url.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/utils/values.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai/version.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/basesdk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/chat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/httpclient.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/sdk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/__pycache__/sdkconfiguration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/__pycache__/custom_user_agent.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/__pycache__/registration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/__pycache__/sdkhooks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/__pycache__/types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/custom_user_agent.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/registration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/sdkhooks.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_hooks/types.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/_version.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/basesdk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/chat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/httpclient.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/assistantmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/chatcompletionchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/chatcompletionrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/chatcompletionresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/chatcompletionstreamrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/completionchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/completionevent.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/completionresponsestreamchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/contentchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/deltamessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/function.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/functioncall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/functionname.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/httpvalidationerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/imageurl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/imageurlchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/jsonschema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/prediction.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/referencechunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/responseformat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/responseformats.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/sdkerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/security.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/systemmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/textchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/tool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/toolcall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/toolchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/toolchoiceenum.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/toolmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/tooltypes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/usageinfo.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/usermessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/__pycache__/validationerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/assistantmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/chatcompletionchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/chatcompletionrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/chatcompletionresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/chatcompletionstreamrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/completionchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/completionevent.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/completionresponsestreamchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/contentchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/deltamessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/function.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/functioncall.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/functionname.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/httpvalidationerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/imageurl.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/imageurlchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/jsonschema.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/prediction.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/referencechunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/responseformat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/responseformats.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/sdkerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/security.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/systemmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/textchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/tool.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/toolcall.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/toolchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/toolchoiceenum.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/toolmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/tooltypes.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/usageinfo.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/usermessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/models/validationerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/py.typed delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/sdk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/sdkconfiguration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/types/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/types/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/types/__pycache__/basemodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/types/basemodel.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/annotations.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/enums.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/eventstreaming.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/forms.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/headers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/logger.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/queryparams.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/requestbodies.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/retries.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/security.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/serializers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/url.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/__pycache__/values.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/annotations.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/enums.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/eventstreaming.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/forms.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/headers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/logger.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/metadata.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/queryparams.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/requestbodies.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/retries.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/security.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/serializers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/url.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_azure/utils/values.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/basesdk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/chat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/fim.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/httpclient.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/sdk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/__pycache__/sdkconfiguration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/__pycache__/custom_user_agent.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/__pycache__/registration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/__pycache__/sdkhooks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/__pycache__/types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/custom_user_agent.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/registration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/sdkhooks.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_hooks/types.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/_version.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/basesdk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/chat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/fim.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/httpclient.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/assistantmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/chatcompletionchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/chatcompletionrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/chatcompletionresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/chatcompletionstreamrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/completionchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/completionevent.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/completionresponsestreamchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/contentchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/deltamessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/fimcompletionrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/fimcompletionresponse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/fimcompletionstreamrequest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/function.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/functioncall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/functionname.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/httpvalidationerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/imageurl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/imageurlchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/jsonschema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/prediction.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/referencechunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/responseformat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/responseformats.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/sdkerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/security.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/systemmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/textchunk.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/tool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/toolcall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/toolchoice.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/toolchoiceenum.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/toolmessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/tooltypes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/usageinfo.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/usermessage.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/__pycache__/validationerror.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/assistantmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/chatcompletionchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/chatcompletionrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/chatcompletionresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/chatcompletionstreamrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/completionchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/completionevent.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/completionresponsestreamchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/contentchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/deltamessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/fimcompletionrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/fimcompletionresponse.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/fimcompletionstreamrequest.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/function.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/functioncall.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/functionname.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/httpvalidationerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/imageurl.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/imageurlchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/jsonschema.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/prediction.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/referencechunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/responseformat.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/responseformats.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/sdkerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/security.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/systemmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/textchunk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/tool.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/toolcall.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/toolchoice.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/toolchoiceenum.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/toolmessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/tooltypes.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/usageinfo.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/usermessage.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/models/validationerror.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/py.typed delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/sdk.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/sdkconfiguration.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/types/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/types/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/types/__pycache__/basemodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/types/basemodel.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/annotations.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/enums.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/eventstreaming.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/forms.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/headers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/logger.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/queryparams.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/requestbodies.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/retries.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/security.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/serializers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/url.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/__pycache__/values.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/annotations.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/enums.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/eventstreaming.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/forms.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/headers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/logger.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/metadata.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/queryparams.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/requestbodies.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/retries.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/security.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/serializers.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/url.py delete mode 100644 venv/lib/python3.12/site-packages/mistralai_gcp/utils/values.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/db.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/env.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/error.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/fields.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/odoo.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/report.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/session.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/__pycache__/tools.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/db.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/env.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/error.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/fields.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/models.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/odoo.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/report.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/rpc/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/rpc/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/rpc/__pycache__/error.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/rpc/__pycache__/jsonrpclib.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/rpc/error.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/rpc/jsonrpclib.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/session.py delete mode 100644 venv/lib/python3.12/site-packages/odoorpc/tools.py delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/LICENSE.txt delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt delete mode 100644 venv/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/pip/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/__pip-runner__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/__pycache__/__pip-runner__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/build_env.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/cache.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/configuration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/main.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/pyproject.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/__pycache__/wheel_builder.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/build_env.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cache.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/base_command.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/command_context.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/parser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/req_command.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/spinners.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/autocompletion.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/base_command.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/cmdoptions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/command_context.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/main.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/main_parser.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/parser.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/req_command.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/spinners.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/cli/status_codes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/cache.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/check.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/completion.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/configuration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/debug.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/download.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/freeze.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/hash.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/help.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/index.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/inspect.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/install.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/list.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/search.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/show.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/cache.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/check.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/completion.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/configuration.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/debug.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/download.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/freeze.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/hash.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/help.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/index.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/inspect.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/install.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/list.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/search.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/show.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/uninstall.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/commands/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/configuration.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/installed.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/base.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/installed.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/sdist.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/distributions/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/collector.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/package_finder.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/__pycache__/sources.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/collector.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/package_finder.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/index/sources.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/_distutils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/_sysconfig.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/locations/base.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/main.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/_json.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/_json.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/base.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_compat.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_dists.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/importlib/_envs.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/metadata/pkg_resources.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/candidate.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/direct_url.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/format_control.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/index.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/installation_report.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/link.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/scheme.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/search_scope.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/target_python.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/candidate.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/direct_url.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/format_control.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/index.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/installation_report.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/link.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/scheme.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/search_scope.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/selection_prefs.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/target_python.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/models/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/auth.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/cache.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/download.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/session.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/auth.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/cache.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/download.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/lazy_wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/session.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/utils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/network/xmlrpc.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/check.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/freeze.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/__pycache__/prepare.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/build_tracker.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/metadata.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_editable.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/metadata_legacy.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_editable.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/build/wheel_legacy.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/check.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/freeze.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/editable_legacy.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/install/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/operations/prepare.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/pyproject.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/constructors.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_file.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_install.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_set.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/constructors.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_file.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_install.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_set.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/req/req_uninstall.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/base.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/legacy/resolver.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/base.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/candidates.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/factory.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/found_candidates.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/provider.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/reporter.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/requirements.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/resolution/resolvelib/resolver.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/self_outdated_check.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/_log.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/datetime.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/encoding.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/glibc.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/hashes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/logging.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/misc.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/urls.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/_jaraco_text.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/_log.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/appdirs.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/compat.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/compatibility_tags.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/datetime.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/deprecation.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/direct_url_helpers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/egg_link.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/encoding.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/entrypoints.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/filesystem.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/filetypes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/glibc.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/hashes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/logging.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/misc.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/models.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/packaging.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/setuptools_build.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/subprocess.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/temp_dir.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/unpacking.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/urls.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/virtualenv.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/utils/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/git.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/bazaar.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/git.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/mercurial.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/subversion.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/vcs/versioncontrol.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_internal/wheel_builder.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__pycache__/six.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/_cmd.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/adapter.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/cache.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/controller.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/filewrapper.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/heuristics.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/serialize.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/cachecontrol/wrapper.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/cacert.pem delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/certifi/core.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/big5freq.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/big5prober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/chardistribution.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/charsetgroupprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/charsetprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/cli/chardetect.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachine.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/codingstatemachinedict.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/cp949prober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/enums.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/escprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/escsm.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/eucjpprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/euckrfreq.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/euckrprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/euctwfreq.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/euctwprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312freq.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/gb2312prober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/hebrewprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/jisfreq.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/johabfreq.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/johabprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/jpcntx.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langbulgarianmodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langgreekmodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langhebrewmodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langhungarianmodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langrussianmodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langthaimodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/langturkishmodel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/latin1prober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/macromanprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/mbcharsetprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/mbcsgroupprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/mbcssm.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/metadata/languages.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/resultdict.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/sbcharsetprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/sbcsgroupprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/sjisprober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/universaldetector.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/utf1632prober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/utf8prober.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/chardet/version.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/ansi.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/ansitowin32.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/initialise.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansi_test.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/ansitowin32_test.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/initialise_test.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/isatty_test.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/utils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/tests/winterm_test.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/win32.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/colorama/winterm.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/database.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/index.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/compat.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/database.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/index.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/locators.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/manifest.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/markers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/metadata.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/resources.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/scripts.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/util.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/version.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distlib/wheel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/__pycache__/distro.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/distro/distro.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/codec.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/core.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/codec.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/compat.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/core.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/idnadata.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/intranges.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/package_data.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/idna/uts46data.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/ext.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/msgpack/fallback.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__about__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_manylinux.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_musllinux.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/_structures.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/markers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/requirements.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/specifiers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/tags.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/utils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/packaging/version.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/android.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/api.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/macos.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/unix.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/version.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/platformdirs/windows.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/console.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/style.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/token.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/__pycache__/util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/cmdline.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/console.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/filter.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatter.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/_mapping.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/bbcode.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/groff.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/html.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/img.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/irc.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/latex.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/other.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/rtf.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/svg.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/formatters/terminal256.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexer.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/_mapping.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/lexers/python.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/modeline.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/plugin.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/regexopt.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/scanner.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/sphinxext.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/style.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/token.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/unistring.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pygments/util.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/actions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/common.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/core.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/helpers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/results.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/testing.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/unicode.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyparsing/util.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_compat.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_impl.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/auth.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/certs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/help.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/structures.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/__version__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/_internal_utils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/adapters.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/api.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/auth.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/certs.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/compat.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/cookies.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/help.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/hooks.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/models.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/packages.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/sessions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/status_codes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/structures.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/requests/utils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/compat/collections_abc.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/providers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/reporters.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/resolvers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/resolvelib/structs.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__main__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/abc.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/align.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/bar.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/box.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/cells.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/columns.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/console.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/containers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/control.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/errors.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/json.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/layout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/logging.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/markup.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/measure.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/padding.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pager.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/palette.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/panel.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/region.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/repr.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/rule.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/scope.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/screen.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/segment.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/status.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/style.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/styled.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/table.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/text.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/theme.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/themes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/__pycache__/tree.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_cell_widths.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_codes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_emoji_replace.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_export_format.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_extension.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_fileno.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_inspect.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_log_render.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_loop.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_null_file.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_palettes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_pick.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_spinners.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_stack.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_timer.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_win32_console.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_windows_renderer.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/_wrap.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/abc.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/align.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/bar.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/box.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/cells.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/color.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/color_triplet.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/columns.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/console.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/constrain.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/containers.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/control.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/default_styles.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/diagnose.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/emoji.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/errors.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/file_proxy.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/filesize.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/highlighter.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/json.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/jupyter.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/layout.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/live.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/live_render.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/logging.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/markup.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/measure.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/padding.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/pager.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/palette.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/panel.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/pretty.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/progress.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/progress_bar.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/prompt.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/protocol.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/region.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/repr.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/rule.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/scope.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/screen.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/segment.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/spinner.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/status.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/style.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/styled.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/syntax.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/table.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/terminal_theme.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/text.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/theme.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/themes.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/traceback.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/rich/tree.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/six.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/_asyncio.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/_utils.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/after.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/before.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/before_sleep.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/nap.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/retry.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/stop.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/tornadoweb.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tenacity/wait.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/_parser.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/_re.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/tomli/_types.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_api.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_macos.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_openssl.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_ssl_constants.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/truststore/_windows.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/typing_extensions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/_collections.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/_version.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/connection.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/connectionpool.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_appengine_environ.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/bindings.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/_securetransport/low_level.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/appengine.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/ntlmpool.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/securetransport.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/contrib/socks.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/vendor.txt delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py delete mode 100644 venv/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py delete mode 100644 venv/lib/python3.12/site-packages/pip/py.typed delete mode 100644 venv/lib/python3.12/site-packages/pydantic-2.11.1.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/pydantic-2.11.1.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/pydantic-2.11.1.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/pydantic-2.11.1.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/pydantic-2.11.1.dist-info/licenses/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/_migration.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/alias_generators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/aliases.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/annotated_handlers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/class_validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/color.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/config.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/dataclasses.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/datetime_parse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/decorator.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/env_settings.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/error_wrappers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/errors.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/fields.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/functional_serializers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/functional_validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/generics.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/json.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/json_schema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/main.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/mypy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/networks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/parse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/root_model.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/schema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/tools.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/type_adapter.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/typing.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/validate_call_decorator.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/__pycache__/warnings.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_config.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_core_metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_core_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_dataclasses.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_decorators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_decorators_v1.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_discriminated_union.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_docs_extraction.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_fields.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_forward_ref.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_generate_schema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_generics.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_git.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_import_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_internal_dataclass.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_known_annotated_metadata.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_mock_val_ser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_model_construction.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_namespace_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_repr.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_schema_gather.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_schema_generation_shared.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_serializers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_signature.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_typing_extra.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_validate_call.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/__pycache__/_validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_config.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_core_metadata.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_core_utils.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_dataclasses.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_decorators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_decorators_v1.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_discriminated_union.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_docs_extraction.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_fields.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_forward_ref.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_generate_schema.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_generics.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_git.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_import_utils.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_internal_dataclass.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_known_annotated_metadata.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_mock_val_ser.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_model_construction.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_namespace_utils.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_repr.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_schema_gather.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_schema_generation_shared.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_serializers.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_signature.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_typing_extra.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_utils.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_validate_call.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_internal/_validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/_migration.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/alias_generators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/aliases.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/annotated_handlers.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/class_validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/color.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/config.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/dataclasses.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/datetime_parse.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/decorator.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/class_validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/config.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/copy_internals.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/decorator.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/json.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/parse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/__pycache__/tools.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/class_validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/config.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/copy_internals.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/decorator.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/json.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/parse.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/deprecated/tools.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/env_settings.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/error_wrappers.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/errors.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/experimental/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/experimental/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/experimental/__pycache__/arguments_schema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/experimental/__pycache__/pipeline.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/experimental/arguments_schema.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/experimental/pipeline.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/fields.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/functional_serializers.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/functional_validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/generics.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/json.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/json_schema.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/main.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/mypy.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/networks.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/parse.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/plugin/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/plugin/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/plugin/__pycache__/_loader.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/plugin/__pycache__/_schema_validator.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/plugin/_loader.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/plugin/_schema_validator.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/py.typed delete mode 100644 venv/lib/python3.12/site-packages/pydantic/root_model.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/schema.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/tools.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/type_adapter.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/types.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/typing.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/utils.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/_hypothesis_plugin.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/annotated_types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/class_validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/color.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/config.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/dataclasses.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/datetime_parse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/decorator.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/env_settings.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/error_wrappers.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/errors.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/fields.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/generics.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/json.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/main.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/mypy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/networks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/parse.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/schema.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/tools.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/typing.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/validators.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/__pycache__/version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/_hypothesis_plugin.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/annotated_types.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/class_validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/color.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/config.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/dataclasses.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/datetime_parse.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/decorator.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/env_settings.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/error_wrappers.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/errors.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/fields.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/generics.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/json.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/main.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/mypy.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/networks.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/parse.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/py.typed delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/schema.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/tools.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/types.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/typing.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/utils.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/v1/version.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/validate_call_decorator.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/validators.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/version.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic/warnings.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core-2.33.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core-2.33.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core-2.33.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core-2.33.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core-2.33.0.dist-info/licenses/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core/__pycache__/core_schema.cpython-312.pyc delete mode 100755 venv/lib/python3.12/site-packages/pydantic_core/_pydantic_core.cpython-312-x86_64-linux-gnu.so delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core/_pydantic_core.pyi delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core/core_schema.py delete mode 100644 venv/lib/python3.12/site-packages/pydantic_core/py.typed delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/python_dateutil-2.9.0.post0.dist-info/zip-safe delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/REQUESTED delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/requests-2.32.3.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/requests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/__version__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/_internal_utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/adapters.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/api.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/auth.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/certs.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/compat.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/cookies.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/help.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/hooks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/models.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/packages.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/sessions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/status_codes.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/structures.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__pycache__/utils.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/requests/__version__.py delete mode 100644 venv/lib/python3.12/site-packages/requests/_internal_utils.py delete mode 100644 venv/lib/python3.12/site-packages/requests/adapters.py delete mode 100644 venv/lib/python3.12/site-packages/requests/api.py delete mode 100644 venv/lib/python3.12/site-packages/requests/auth.py delete mode 100644 venv/lib/python3.12/site-packages/requests/certs.py delete mode 100644 venv/lib/python3.12/site-packages/requests/compat.py delete mode 100644 venv/lib/python3.12/site-packages/requests/cookies.py delete mode 100644 venv/lib/python3.12/site-packages/requests/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/requests/help.py delete mode 100644 venv/lib/python3.12/site-packages/requests/hooks.py delete mode 100644 venv/lib/python3.12/site-packages/requests/models.py delete mode 100644 venv/lib/python3.12/site-packages/requests/packages.py delete mode 100644 venv/lib/python3.12/site-packages/requests/sessions.py delete mode 100644 venv/lib/python3.12/site-packages/requests/status_codes.py delete mode 100644 venv/lib/python3.12/site-packages/requests/structures.py delete mode 100644 venv/lib/python3.12/site-packages/requests/utils.py delete mode 100644 venv/lib/python3.12/site-packages/six-1.17.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/six-1.17.0.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/six-1.17.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/six-1.17.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/six-1.17.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/six-1.17.0.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/six.py delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/sniffio-1.3.1.dist-info/top_level.txt delete mode 100644 venv/lib/python3.12/site-packages/sniffio/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/sniffio/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/sniffio/__pycache__/_impl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/sniffio/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/sniffio/_impl.py delete mode 100644 venv/lib/python3.12/site-packages/sniffio/_tests/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/sniffio/_tests/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/sniffio/_tests/__pycache__/test_sniffio.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/sniffio/_tests/test_sniffio.py delete mode 100644 venv/lib/python3.12/site-packages/sniffio/_version.py delete mode 100644 venv/lib/python3.12/site-packages/sniffio/py.typed delete mode 100644 venv/lib/python3.12/site-packages/soupsieve-2.6.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/soupsieve-2.6.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/soupsieve-2.6.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/soupsieve-2.6.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/soupsieve-2.6.dist-info/licenses/LICENSE.md delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__meta__.py delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/__meta__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/css_match.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/css_parser.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/css_types.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/pretty.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/__pycache__/util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/css_match.py delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/css_parser.py delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/css_types.py delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/pretty.py delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/py.typed delete mode 100644 venv/lib/python3.12/site-packages/soupsieve/util.py delete mode 100644 venv/lib/python3.12/site-packages/typing_extensions-4.13.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/typing_extensions-4.13.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/typing_extensions-4.13.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/typing_extensions-4.13.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/typing_extensions-4.13.0.dist-info/licenses/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/typing_extensions.py delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection-0.4.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection-0.4.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection-0.4.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection-0.4.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection-0.4.0.dist-info/licenses/LICENSE delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/__pycache__/introspection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/__pycache__/typing_objects.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/introspection.py delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/py.typed delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/typing_objects.py delete mode 100644 venv/lib/python3.12/site-packages/typing_inspection/typing_objects.pyi delete mode 100644 venv/lib/python3.12/site-packages/urllib3-2.3.0.dist-info/INSTALLER delete mode 100644 venv/lib/python3.12/site-packages/urllib3-2.3.0.dist-info/METADATA delete mode 100644 venv/lib/python3.12/site-packages/urllib3-2.3.0.dist-info/RECORD delete mode 100644 venv/lib/python3.12/site-packages/urllib3-2.3.0.dist-info/WHEEL delete mode 100644 venv/lib/python3.12/site-packages/urllib3-2.3.0.dist-info/licenses/LICENSE.txt delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_base_connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_collections.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_request_methods.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/_version.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/connectionpool.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/exceptions.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/fields.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/filepost.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/poolmanager.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/__pycache__/response.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/_base_connection.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/_collections.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/_request_methods.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/_version.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/connection.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/connectionpool.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/__pycache__/socks.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/fetch.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/request.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/__pycache__/response.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/connection.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/emscripten_fetch_worker.js delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/fetch.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/request.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/emscripten/response.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/pyopenssl.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/contrib/socks.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/exceptions.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/fields.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/filepost.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/__pycache__/probe.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/connection.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/http2/probe.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/poolmanager.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/py.typed delete mode 100644 venv/lib/python3.12/site-packages/urllib3/response.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__init__.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/__init__.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/connection.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/proxy.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/request.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/response.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/retry.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/ssl_.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/ssltransport.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/timeout.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/url.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/util.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/__pycache__/wait.cpython-312.pyc delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/connection.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/proxy.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/request.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/response.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/retry.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/ssl_.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/ssl_match_hostname.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/ssltransport.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/timeout.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/url.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/util.py delete mode 100644 venv/lib/python3.12/site-packages/urllib3/util/wait.py delete mode 120000 venv/lib64 delete mode 100644 venv/pyvenv.cfg diff --git a/README.md b/README.md deleted file mode 100644 index 5b55bc4..0000000 --- a/README.md +++ /dev/null @@ -1,199 +0,0 @@ -# Système d'Analyse de Tickets de Support - -Ce système d'analyse de tickets de support permet de traiter les donnĂ©es des tickets pour en extraire des informations pertinentes, analyser les images, et gĂ©nĂ©rer des rapports d'analyse. - -## Architecture - -Le système est dĂ©sormais structurĂ© de manière modulaire, avec des Ă©tapes de traitement distinctes qui peuvent ĂŞtre exĂ©cutĂ©es indĂ©pendamment: - -1. **Extraction des donnĂ©es** (`extract_ticket.py`) - Nettoie et prĂ©pare les donnĂ©es brutes des tickets -2. **Filtrage des images** (`filter_images.py`) - Identifie les images pertinentes dans les pièces jointes -3. **Analyse d'images** (`analyze_image_contexte.py`) - Analyse les images pertinentes en fonction du contexte -4. **Analyse de ticket** (`analyze_ticket.py`) - Analyse le contenu du ticket pour en extraire les informations clĂ©s -5. **Questions-RĂ©ponses** (`extract_question_reponse.py`) - Extrait les paires de questions et rĂ©ponses du ticket - -Ces Ă©tapes peuvent ĂŞtre exĂ©cutĂ©es individuellement ou dans une sĂ©quence complète via le script principal (`processus_complet.py`). - -## PrĂ©requis - -- Python 3.9+ -- Bibliothèques requises (listĂ©es dans `requirements.txt`) -- ClĂ© API pour les modèles de langage utilisĂ©s (configurĂ©e dans `config.json`) - -## Installation - -```bash -# Cloner le dĂ©pĂ´t -git clone -cd - -# Installer les dĂ©pendances -pip install -r requirements.txt - -# Configurer la clĂ© API -cp config.json.example config.json -# Éditer config.json pour ajouter votre clĂ© API -``` - -## Configuration - -CrĂ©ez un fichier `config.json` Ă  la racine du projet avec le contenu suivant: - -```json -{ - "llm": { - "api_key": "votre-clĂ©-api-ici", - "api_base": "https://api.mistral.ai/v1", - "organization": "votre-organisation" - } -} -``` - -## Utilisation - -### Processus complet - -Pour exĂ©cuter l'ensemble du processus d'analyse sur un ticket: - -```bash -python scripts/processus_complet.py --ticket T0167 -``` - -Options disponibles: -- `--ticket` ou `-t`: Code du ticket Ă  analyser (obligatoire) -- `--source` ou `-s`: Dossier source contenant les tickets bruts (par dĂ©faut: `output/`) -- `--output` ou `-o`: Dossier de sortie pour les rĂ©sultats (par dĂ©faut: `output_processed/`) -- `--verbose` ou `-v`: Afficher plus d'informations - -### Étapes individuelles - -Vous pouvez exĂ©cuter uniquement une Ă©tape spĂ©cifique: - -```bash -python scripts/processus_complet.py --ticket T0167 --etapes extraction -``` - -Étapes disponibles: -- `extraction`: Extraction et nettoyage des donnĂ©es du ticket -- `filtrage`: Filtrage des images pertinentes -- `analyse_images`: Analyse des images pertinentes -- `analyse_ticket`: Analyse du contenu du ticket -- `questions_reponses`: Extraction des questions et rĂ©ponses -- `tout`: ExĂ©cute toutes les Ă©tapes (par dĂ©faut) - -### Scripts individuels - -Vous pouvez aussi exĂ©cuter directement les scripts individuels pour plus de contrĂ´le: - -#### 1. Extraction des donnĂ©es - -```bash -python scripts/extract_ticket.py output/ticket_T0167 --output-dir output_processed/ticket_T0167 -``` - -#### 2. Filtrage des images - -```bash -python scripts/filter_images.py --dossier-ticket output_processed/ticket_T0167 -``` - -#### 3. Analyse d'images - -```bash -python scripts/analyze_image_contexte.py --image chemin/vers/image.jpg --ticket-info output_processed/ticket_T0167/ticket_info.json -``` - -#### 4. Analyse de ticket - -```bash -python scripts/analyze_ticket.py --messages output_processed/ticket_T0167/messages.json --images-rapport output_processed/ticket_T0167/filter_report.json -``` - -#### 5. Questions-RĂ©ponses - -```bash -python scripts/extract_question_reponse.py --messages output_processed/ticket_T0167/messages.json -``` - -## Structure des dossiers - -``` -. -├── config.json # Configuration (clĂ©s API, etc.) -├── main.py # Script principal original (pour compatibilitĂ©) -├── post_process.py # Post-traitement original (pour compatibilitĂ©) -├── requirements.txt # DĂ©pendances du projet -├── scripts/ # Scripts modulaires -│ ├── analyze_image_contexte.py # Analyse d'images avec contexte -│ ├── analyze_ticket.py # Analyse de ticket -│ ├── extract_question_reponse.py # Extraction de questions-rĂ©ponses -│ ├── extract_ticket.py # Extraction et nettoyage de donnĂ©es -│ ├── filter_images.py # Filtrage d'images -│ └── processus_complet.py # Orchestration du processus complet -├── output/ # DonnĂ©es brutes des tickets -│ └── ticket_TXXXX/ # Dossier d'un ticket brut -├── output_processed/ # DonnĂ©es traitĂ©es et rĂ©sultats -│ └── ticket_TXXXX/ # Dossier d'un ticket traitĂ© -│ ├── messages.json # Messages nettoyĂ©s -│ ├── ticket_info.json # Informations du ticket -│ ├── attachments/ # Pièces jointes -│ ├── filter_report.json # Rapport de filtrage d'images -│ ├── images_analyses/ # Analyses d'images -│ ├── questions_reponses.md # Questions et rĂ©ponses extraites -│ └── rapport/ # Rapports d'analyse -├── agents/ # Agents d'analyse (pour compatibilitĂ©) -├── llm/ # Interfaces avec les modèles de langage -└── utils/ # Utilitaires communs -``` - -## DĂ©pannage - -### Problèmes courants - -1. **Messages non traitĂ©s correctement**: - - ExĂ©cutez `extract_ticket.py` avec l'option `--verbose` pour voir les dĂ©tails du traitement - - VĂ©rifiez que le fichier messages.json est correctement formatĂ© - -2. **Images non dĂ©tectĂ©es**: - - Assurez-vous que les images sont dans le dossier `attachments/` - - VĂ©rifiez les formats d'image supportĂ©s (.jpg, .png, .gif, etc.) - -3. **Erreurs LLM**: - - VĂ©rifiez que votre clĂ© API est valide et correctement configurĂ©e dans `config.json` - - Assurez-vous d'avoir une connexion internet stable - -### Journaux - -Chaque script gĂ©nère un fichier de journal dans le rĂ©pertoire de travail: -- `extract_ticket.log` -- `filter_images.log` -- `analyze_image.log` -- `analyze_ticket.log` -- `extract_qr.log` -- `processus_complet.log` - -Consultez ces fichiers pour plus de dĂ©tails sur les erreurs rencontrĂ©es. - -## Exemples - -### Exemple 1: Analyser un ticket complet - -```bash -python scripts/processus_complet.py --ticket T0167 --verbose -``` - -### Exemple 2: Extraire uniquement les questions-rĂ©ponses - -```bash -python scripts/extract_question_reponse.py --messages output/ticket_T0167/messages.json --output output/ticket_T0167/questions_reponses.md -``` - -### Exemple 3: RĂ©analyser un ticket avec des changements - -```bash -# Nettoyer d'abord les donnĂ©es -python scripts/extract_ticket.py output/ticket_T0167 --output-dir output_processed/ticket_T0167 - -# Puis extraire les questions-rĂ©ponses -python scripts/extract_question_reponse.py --messages output_processed/ticket_T0167/messages.json -``` \ No newline at end of file diff --git a/__pycache__/post_process.cpython-312.pyc b/__pycache__/post_process.cpython-312.pyc deleted file mode 100644 index 0b0e2be263b0cd10b290fa2bf39684bccb56dafb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30944 zcmdsg3s_s%o#(xJzmY(I5HEo-AoDT?8;p6Fr;Q)j25iSR4v}>Q76wGFBs-{5;5p6}cFX1-k_7GfUu>$7A_2u z7#EBS%zF1e@KE$vY5SPVMA=MZ4yUWkMO*AH+lXz{1#UNOvWzTTAGSMa8*Li4IZXq0 z>uI}L4uNhi}VTQgjd)`oHP@J zPxR;%z0kD00+)>AV@So>qVLxguZdWfPjInB1i4t3FD0eo^Yv&RC^h7omkXet#H9}Y zTkW5hW!j*c;gjwGIrm+%QVS{HAxLraL#y%<;{CHCtZkNkRRjju&9Tx#OEavZxO}l&d?=#s(O-}dN7;PUx9S?QLQGda^f~)_PHt){@MN~wA$@DYk8U&ww>U;eZ6OKM1={XI`Bk0V%c@0P;Ios?lM8M7`B)wC=gUK&+s$su7*&}1NKo9)mLP3 zI^Ae?a6|Ep*zCi@PLt)^ET|fxkvdHls};)3S!XiKLkhdoKI(K?My^7d!KjUpt5t~crm z325}meJZ5r+|_lUyS=r!r#+O+k+sqNVR|7k#J7)`#WWfnL!>RF#$BL4+~Gp{F^kJ( zqeq?nmi}=B)@s^0Z}r z`jq&EJrnIKDv>y6*J^nxtPXoKxm#vC=X`#{{t5NR3T>8z z5gAqr#A0{WWUWC%_Se)XlsJbAMT*t8WvUe+ydT`(5{{_;NAQAB;HAf2F`-mpFJKkX-*@BC zjaEi;a7lKEksbO-Y2b7GU`0woo>rY-fNFVB*_uSWoZebRyp`UTLA;Y%-d0S!D=u%V zA>OT4wo8bGBzfy*;etWaS|VI15hHt*ye&<*P_J#%3E$I+!Tw%`yltcKy#f-M#qzdl z;d@miGHc}RLg9}EBr+xP_HDu+Cu!O%g+HzogFR;Th1LOh^;L>jU+b*9lDx!un9pJT zkZ|>7hgAS2e1Sx(EHEXM6igW<2U9^Q!BkOdFf~*Xm|98)W-^rmrk+X#GmT0I(?Df_ zX{0j2%%ZZv%%O6@G*NkA=2IJ9AR(OsY9qJ`sUk3oDKnUxs1h(ssWLFjsR}SRQyx@1{Dz z+(YdJb04)I%r5ExmId^F$^zyo z$_ge$*}xp222o1XY06FwQD>-OYJ?i49Ml-~G(}TR%0;pE> zXgWdkK`r_OKB1Qwimc3{5xfGgkXu9hh>IDb^;XMgVXYiqbEDNCT3d~i>>AE|&K&^C zcsbA&9$C@K#c8ryXp7agFhfU1SogwpC%dm$xPBJ)8SJJ4#;#Mt3o|e^nW!S$sMSF| z_6i0qUbr+LZ~0<5YqPG!8Al4Z#Mziv{hlB6&pTNV-_jn6Dn)x2*!K0n;F##T(e25Ewote zv^89$-vYOd=l%}3?L7DQ!0q6<-vqat=l&tMn|bapfxDgO{wlaTdG0?2_W_>!>)<}j zbAJOEhQ+}!#g*h=fQOCsaH9e5AOGe*gAXhNQ4lw37Vn`};NZvkOYm^>Li`woXy%9b zGI+FyL$Fle2A@t|ocBY>qmg2WNZK`6uA)j5;rY^FY-3=iodXb-n~_!kUV*b9}wZcAl@WukW+3 z%d`@TZk4QGC1ER2xJu@)l0~?H|LIGw;~?)|XJ6lAeV_l9Sq+q1S;}C8g)XWBuyuuP zlETqb&aoXHQQ@!)nS)@83oRqyB`JK`?Eohf7_6Dl8`i20^tL+2#!)cZHn;=Y0<2zv zXh_)A(Q1~^8sL#e(_=`CL?h0Sl(vlxTVQ#pbdTC$w6amK=L*Tgqld?47P0F+wQ~$w zwPm>9dfGxeLn5>s3yH7;?Vi!Xj?P5HQ#s=#Se!a&3+IXZuue-0uh4=@?LMh_-woSw z{IH#kA9ir@u~R|FlP9ZJlqkM}Fm9M`ILChS2+15h!8%oJd^L)% zV&jMHIDXj9#t%EV_}Hmo`A?_V(y=>{pgEqVnIYRFU$u+bOB5PBc=ysBB9j-b)g+r3gdP@J=>n z5sSJN8cFXh!(QhrqOXWS=1Y2svjna3f(=Vs1>geFAM5HNK#(T{K^_Tj5xfPkV1l^u z4<)7~+yZC_r4aXUi?6SWDd`0tX7h}nsx$$36dyDB@sM%M+-@QUGUL^Oz zE&xgCPl7}n?MW^`$NF>f3P}oWtLtvPN^ch53VjrbI zR2Py!8nBdz$r3#ZA=b~#cOXD}QM_=0MGRV5gtXx*aAIK-^np+c zn*(S6sADAJDFzv`^)&5-DD(&zPBd^qqc-i_iEAsQj;SL0S@=AG!mWbw+w%m>4>HYU z`l8e@b#(g3)qZAk`(k!`Fez>F?1kqTSI2gHV3GmWFB5E8ktQE0Yzg#+Q`yZ>F+`A2@oHSj=5d^10c-|DIIPX=dgyi&nOU<$KiSE z4(u?Y6Ord(-ti%EN@VVV5fnryuZuX9(^lBdM};jzsFBA#JOvKYX2L&i>?R3UWbPS? zD4?Rzha$5^)Q_i36Ri_FGJEi1gW!it-6ysaJ_+RQ(LA6PcHH9?y%sJHpVTW&q>_SJ zIUIsch7ghYCrStjpEyoNNw3r=TZa!cVZ}XOaU_+pm^u=Fjygh`<(N7eBzy`=>Qlm> z3jWlfT9nXpUda&JBg8$FlH=%$nJ%QEz|UG?qb0z_8YNLmYlK&Ep&o-aaLSb~7Yox? ztwCGOg?bFy>NRMq*PyNW6tp#7*~5H$Wj-0Db>&9NGg8XWkWMk^{B>R#Qf+!=yfBf{ zf-nLIBlW70Fq6`wuv989WP}>{r}6w%;h5++frDbWmXy4T=M_NI6B!No`W*}eEBzf^T zf=sw7BDJjm^#ExksN&~|*Uemhz1TMs#Wdn}(!p!NB|ORr`yMD3vZ)-eCSe;ci9ziMTVM5qufgkLLUyk@}`JQztJTdpPyjvby*`5~k1) zQ&QV`V}+b+?QwNvq{v~TFOye~b>7UO8m^Y3Z%(oh8~;n;`i<7A8KmUUuoY+*(MwxK zooM@v@hxFQ8MkeBmJc~WDGy)`*vhke><9*J;X1238ZHV$&P@CE?O$^nA6mfrl5^1ZK|8?HFn@?g-oiamYyh@6VfzFKo#HVIjZhK;umvmyRD~53^fCED z8Z8&#N^E9KyemY~t75lnpse;f8Ioabmwj|_Rm<+;`;lM)7ePoG_Q6|p_bw>&IA8-G zXj24u9zgDaoB~6JfIrA9O90s*{V@QNI3PfsDI`7IwYTfQ(JoKTBPfEz1Eki2prVWC z3@C_3EhDhK0q6uq4}ugVq_omDi_6vzvTz#+9zZJY?s%BzgPf`_jPC({S=O0^ju4kntyAKsHgn*zD2$$VcQF zAA?Mua!})*gK=fJ4^UVvNHVUCL9&QVEQlJjI5A)bZPRV0vj9e+Y~`k2pjv05(MB;* zeeVxLckF|pX@I@}>Q$4~W*RL*NFkOYWF{)IiV%DeW#uWvxa^P{0z-AV(JrtXS_R0j zZ1e#722vx8Q=s~@(EoT4m^9;C4e zk12G2SQh8xiH^eIc0gn-Y&lOb-91a)M;E(~GEY3oJax+7Z9PxW&#|cp&)CL2b#e8| z?`;U*1SnXnG#|csv601K{knySXm&g9J7svL})?)iI&4cg#->z zqX9bVG)NQekbM}0L_-eyXh?PnhF$Dd0CbCXInUW$r)k)}5H!L*(TK&61Ym4VmlHQ8 zEEmIyH;~?qK{^zx=Nm_%QL7G#P+!8bEexT8!3IWr8wLLEkue%A&Ox#Y00-MCi}g%M z!Om6vwr8y7Ec!g6@t{#Ta9}i)(&^}1 zGKjPh$je4W+IVDO#8Hwt`uuU3^F!luD$6Bgqd)A8=9`cPk3dnPLTG)s8?(cmDx86S zJnSX0l5jT%VvF|tkOZ|_7(mg8fxB-=_YlkUoAA+zwsUBnUF%`xjQU7}0ZbiNiu6w) z?kpnmD^RU~v{6gQQW&W*m}Z(#u858c#F{&5-Q=bz>&&izx_SiwX$5oSa(d>K@yp}W zx);0?yFURCTETr8k!HAZ^zzXw{g?ZvkNZVq`{;Vy0(ID1+I#;9!{&N##$Gx08&)mi<4ec&CEt ze!|~!jA^mGWSuT~wc_Q9*}}Pee||$Cr;#}`GN}w6Jh61JfAL^H^VEp{;3#v@^GeT5 z<{P=!bLX;e2>j-~fsOlCVC)jK3K(sEu(S76r7e(T#;`#uV6!trwBP1rC>N9L4yeusp}2QLsT(sVG{Kb2dqjiW zG|_q|C40*HN_8Nmcv+ju7=Rs$v7PomWoP<_n6xti?Ql?wB+mNuD>avErnXIQ@uw6{ zwB1fgf5|gb@TM@3TMYpqeSO|^ia%xJL|f2YHfy+P-hQ=i&NHzOzT}q9wE1%?Cl1_B z$!EhFOJ`c&*mZr^?7sPYe`&ivqhn&va$50B${Xp|(`Pg0TKwiFf7;H8U662E25Qz* zy^wHf;Y7#nl#F0z?zCp+=|$6KCbyEw*fJ?W$>&TBykZTcYywz;u4XygG@bU16O$dF zU(d+8CcP@1R?b*vlV^_l4O=HVmm$;k*Y$yv@?dt(v|wu2r2OG5qCnIutxz(EWX^JC z&XnsL+W|MAAkwpg*@ZzvR?tv@%$(w2W`596gsMlwsIoz2pw3-VZCq4sWD08ns@kB+ zIAvK><$kqmD*1$%JQRPfMJw-FBd`Jdj9lEK^ zK^2;OD4^>8NR`7<4W?}f8cab0BwDs)s9ZEu&Z1UqXbT!EKtHjxxpQ%I=Z!+9`=o#K zlT1ZF)BhA>u-sKjiZu5Li8|?iGNDPHECF@*(SUj@8dUa@bGl`f_EP7CP6jF>Z?<{9 z{g!GE8e8^~P`q*tqcy+20k!K*&5XH)X*t3iwJ}Eqn1OSQ=9ycv@lR|b7>Dkn0qVhh zLm0zafE(iprtc(k;z=gCKcIRlXx#9pdohl+VD%FX3(R>B0ScOqYaV0uw&YoakeYpJbAsTvGMlRQ029@a@6M7)k1C zg1H-}yJjmF3#yq7Tbb-_FLXRuF_5~PU}p9UZ4d4jhG{`PAfRp6ji+x|ndI&zRnJXT z52n;hu6|-d1;Ccj1Ekdl*sVyc!LZn-_k{D!3zE5K7|rg0tn&kz0lX&_Q`?s^D;6^= z{F#-EaSNlV3dpL1G63buA>yhNE!+NB(`zQao^~ij_?>1sSl_8`79BDX@7Csm1HiG} zdSan4ty>DPSQ*&g6Uo5;J#|Z6_jckZ(sm=bex9%F$r1d#tXTn$zpGXDlnZ_#ECBm2 ziuFCU#4qZbGr+;58hf*aOvMJUFQ$kOWlI+gh}NP>-YpU?nze_Tgp1oH$frpRJ~u@| zu-}x5yLHl=DwOt3y}Wyy@MgBAyHa?w1ckg=DMmiqaLDcQo=l-%py^2y`nBk*KTV8$ zGSOFmj-sbT>@UXt<)WUgV*eIwua);2g#l92n<@+>A)i3182K1ctU$K7w@@0$mm<4a zez-yy*iw6VlknCiG1y}?Pg0mTvF7P-pisXe`9tWQCM2NE7e6oiszg9skUSTWJi~!0 z;DLQW)+Kp_tSh29;=+S;Oa!tnIF$9e{1LLQ2$F(QxX|(vKZy=r4JFb(MQ{tT(v62@ zVHYEkoj7?+b3`7aOEKdn1LV#TffE188CA=?1XZJp%*aRQ@1JEs;q(Ny$A-BIjfeHO($SD0h zGX4mRn4Kls#p0c%9$M0ibHLZ6@qcGNu(p2QrSV{Q1$IRaxA_!veOYlwF_-$zAy1Prq{B!n|c zArXQ%hR8D^@@y!H!$QN#8*RXx2*!j~>nvb{{slNafJ9-N0S>~QdWr74<7k|Q;&P&$ zJfJp~lQO0@yyOfdZCFk>&us9gmowV(WnJb}>nr+zt}s~F@P2yZY{Au}8PP36+0FDu zII|J+`A6or%s(tyO7Hl7!ED~_p(*le(@dp5vux2&=1=cnv>hL%8z&XN{a8*IntuDM z^bQOl`+ib$ljxnolopYMo(4wfm%-?u5u)VR8^J(b$rcqwaUF=;1he8t&!&fWwx}Q; zjtIM01^pjUIqS$>f=Enkc(;W|u#!nvrF|q9<;Rw1>Y&Dw@&FR?cs|rRqfS_i$^Zt#6+C z>%s32E^X^r+}1Jg@o(#9w)QZZ-dnQ6pOip4XeF^>^^*b=1=;t&qJ~{nz)laZD(c>@ zntS?(+vbWHO>02bhF1=7PzP2H?U2K-Xj-a?7t>m@gs*J?+dCR#OR?~s;wrGen ztK4iGHw%w&{;suWVcBPzh2`#lg#!L;v+#ZkeTH(J8~uzkF&7;j)a3d(W&{lYf3Vq@ z9Yuc$h2Y)*Mp(Sg8x28}k3?2jHGwY_@a%Zp(UV=bfIed+TvCzY6ws133&l$B#OG+3 zw$>R@C2=Dv%>c9XA~KL01M))|T#5E`X>*es{XT?$4vn6_2FpW(r~cu=Gk1;* zrlnsQxIFN}X?Ez$1<_M>#mqT>Rt=1ru#HxwFlj|Ml|^@Ssgq}>t7g*!y6rI3sY~V# z1+}^>(#ulDU=Ckjo&Tevw~ChP_AJ)zxl!k@JHl)~$|OH=OLgoH z+MLzAE%=f2E$LG2?#0^OH;n$;UZ&gXrgq&yc5rMau0Bm+g96nFNK8&voH zycKqoKkK+r3uAFWc9=J+?uDHHv8FYZ_`0s8LHO-Lu)U*9Zj}q)$*uzXySfr&Hi%m# z(glGO>b_dd~>$wvUZZB6;Sp7u3#V7q`?_ZxT7LGjR7Q46um!U zC^EQm;n60ITO#|!loI{pN(O2TE!^?*oH(iw=e|3YJmqr)V)do<$}qyP)T0#S<;yj<;^Rmk`U1ZP!_RQg1*+nS4x{8o_39RGJuguP&C3RfY=A;(k9$db*q z>o39Sa;TSRi_dkLxtKBFC=-9?@yeW5Y9m#+PI*4EM}*sC5mo$>XpreXg0_c8UfiRW7qDT7G+iwVnv%dJxeiP}_T4yV5!GtUS=M{B@sVU2l4nV>Z^0_0W6 zD{~=0ch{cd5{;zFPgUln(b63?@Y-7$uf6es!sYz-HoD{Ua5@O{@uwK`E2Et9_}mip z9nXp1f&rlK-?+_I>?RDp6mwr(CazV1F!UEbDUW(O51c0DQi@%Zt<%mP+1J)v0sQ|o z`;4mMYiCr*)&Q@(BLG}{OPA6oeO3xJ)lFerRNNd-3BowI+Kj7b!Nqy*3%{OWEtwfp z(|M0k)6vm5pKA*+`uty<`{*}f#wq#d7^fbZwH{Gl(Uo$7`HbGf8xsVddh~jX8DnkE z;^xc^(OMcc!rgBCehxP<^4eWNG~_X2RK(r12B2N84Sw%2+TZ}!(jIDq57zwhx7?Q) z?uKI8X2oN)&FI?kQ_mQWGY+p^=Dbqe%rC`o$q6nlty^+}i}w?jLUT+hRIOhMaGQ>D zIL)Wx@wC;e8mi#N_vrhzur+op=jwZ06wkAHoBO{*6a|uIA)KNGpsjGn9Z2Hsqj2vA zzV!}aT`>%ey|0og0v#6%Ycc_dl)WD>f+htWh6@YI93x`@f?QMT#=)iRG#~g2>2d(t zD6$qahZtnJeCWD7+Kta74_h$)7B0iV_l;o}!qk##U$LtkmX*$u@=RQNAc{xG3PlG6XZU0Km1*)Iom*BCM)8 zFcpRxds5*RGK=*zy7ki;MIgs1-nu-MJj@si(_RyM8b&zM6ObBv#`tT<_EltDLdKsU zV;UJRBja0O;G6dT>7^IKj7J#>mjWOWw?eQy)58KpR6ShzMsgk{0D?mi3+TlR;IuEI z6cN3|DcY<+6G1c4bwO~8o7)Qam4YY|S|8jUXLDDr74y;Y;G#Pg#mnN{%Q@h=J3maX z#{yUW4O(c(1@{eb!^cd_fD1dor;$F8gOffbFi#0YCdlV7GrrDDnDO0Q} zj)?)lPZLlA*nV8Qw7SO@uCr|#HN-6mlLN-ta8Q(#ZOmtxYa?4D?3{vg4J`f=l^5DwqNew#m>}1N1_yXrcSSgK z!j2m0AEx4P69725IntyO$Ke_Ri{2fxFU)|P-h{xkE*qeCH^w%JgfyUOtiu;qa4~$9 zJu)xhqJAhwH@}NV&Nf6!DBMxqRx2Q>^Kj|1!(#NHfhF;18b;jH-v+kKhB!q6T>0Y! zL@xb0e5Bt%Mw~hqbo2y`H0dG55zDaK24fSbg1?J=k0K)p8Cd6w#G?QrK8@~#3W?E; zLtE%^^c6vgF{l+oW9h#Hr&*1K;`Cc6PGqpgFyWAvUl$lSjC8~pJ~)4XEN%Ovj$sP+d_ z5DpTqihLM!i|(2P5aKn}Rn_$I*<8P&c|sir&)w_K+z0Snpb&$uy@k-VMe2i(iLM1@ zj3Ixz56j{#YOF%Ip!l)hszeaBqqJnc{4GbswDWK3r+rj)+9 zXYLC(wkg~GuGfa2? zV#iZ~Q?|g4fna47gitT)%YmCTV=Pv99|>S#z2Qpd<<6-yGnKQ4<`3V}W5n=2q+8de zF@~+Tv^DpO(WRPDluL%gSFD=GU+{Xv}*h|J9S zt@GzMF6DPD=6B4GGu^%Z{KHJ%5yo&dn41Ux@5;rQ8h|uwiR3gUt#C#-I~dS4A{EkZ zaz1ZatH-xAluSQ8tD8@~rA1f)_yYVOrPZ#0suT2GS$R-x%Str|iJmG8C;>8BpzbB_ zZ*?KR2y)BSl ziR=A<-*}MGAN*)T5u-I>Oy!n0t7f11LBnjtypc)U7trp%TTW^SJ5W)zlXFjV zMO8fAJY$)&-O{$9qH5OG&K z)d%wnCigC9WHUMCv%1fn0k=Bk+*Efx+cFWpDvksdQNvE^_JlP@CaY-pd#OU zOTQmm8sB!#@9;MrU>XlH2Q7^8R6uY24FG228%R^MedJGBX2?15Eo~#pbQ9KCHV0I# zchKdj4FOqGFe&Aeei4UtUHznx)a@e??sXrAf9SJ6CN!vvBk1e?pIhNL&(8*KJi(+L z322W((PZad+jVu>*v=ez!e4ld*?64EIuYEk5&lC}<|a=np%y<)5Bvo4%5uC49HH*G ze@T1bruM*tm2AZO>L*)J*MJ~kBG|016a_DR07a+IzDJ}$cfk4E`lfX*?*{|3kiEu$ zwh8&A)dsZNfog7Eg5Hvnih$==8ZS3amjGaUMW9LrO4)f(jn28Ff$Vmu-i+!Sy5*vh zSI1u-pVj?^cMA21jA~#yqZ*jVs75Sj6;7XiQxwSDdM9t=^vG<_d`%#4FT~A0Ox}2U z*;MeV{AKw}@oe*)<%aE+sTU}~7a##9&;WB4y2|EiCaZKAdVIl=K-Lq#UCt~3&@$r3 z0PU^&eM1ibkiq%C|9xd6%JAwZJ4w_FP^q+o%NT6}D%A48A54S*LQO!7+B<3j4R2fL z^L{um2SwBo(C)euf3BjHH&&jS&YNkTYrmy$0giR8h+{B;Fqo@%5Vc)P+RmHW&Ic<> zl)&mIT4V&@bLG)2 z;%7V3jwT6zu4@4M-)U;$!!IPpK9TSjrsfoI{IXipS3)p?v_74XF%*M+kudh<2p5f| zV81Czf-pBzjZfwYZ&u`h-LDb%7^MCb86@h@6!&bD`c2qgEI-mD^jEgXkJJfo)ftau zi{IBH`}^7ABZcz!^OKRiS^^~AuMM)~c!jbIPu8cztsq3y{31A+L2QvQKd zkL;Nw#Qh*kf1*nK!Da!nZy}MrN{H;+5Gx7yo^g9NFu|Pm1LqlF4BIFa=TmFhdL> zKg>atKg<(9St9+g5K;cHT;5+R{II5`ze@NIRbsGPVVx9t5E=`E8gc+Z%15d`TA=wF zG#2zwaIyuKc}Mv_w7`7>(OLxSMMab`HzJM)-!K4xAQIgs zM9HFjQR}E0;ikO*7jhK29RczVwZJ}!z$TOo=^uO`#(Z?Rvw$I{RO^NjQ0jHV2tN;| z&bfitay0Sqm&dPXxVdmY|9(KO1^7f>5u6o`w$3E(%cp5Yy!erOUe=Azt23_v)DNZW zlv6~=&ebo5^5{6VF#uSSee2;OQ=@S?8}IHYDtg1=P#X6=`i_QdBTm9^^YlS4^TB;p zKDk#8KF#1#z%>pg zrXql-nEq?*RqqPJ>!2dh1n$I`pw<&&`OZ?j@mD4X(rey1ir;Ck>QhaR=u;8M&hMa4sa<)I-VwP04KB)ThW@lKra%2|^Y8~47ZT)Qy)ofY zrT%$2evB~zam;JinbEOeJbOGF)Ry^NT>(5{n@__Fo8>~MMDP>6gYC2SIZ%FO`!vsL z#hnTsL8Ma7CO z6dQ>i;n$<^!^(j1j}39!EdYj6!^4lc#I8dGBpn%z96s_e%;DuvVcq+s|`F7 zHXOcZ#Uqd8)+1xBBNVc+$+}UuO{87}jU9J;2S~vY3T~ezv3S{JLAL^(cEC?xlw%E7 zFMD|nXcR!E8qqL?1=n!5JlsYB7fp14dT)g4bt9Z7Dzt|W7s0Phg|!15P@Y#4Trrlr z(Xh^5KEfUU_@2IvDrkfL!9?BT-_k4|LZ)Hn$Hoo^p>V zMquy8ZI}0ZgmtDaa|(O!h7j)k35no#qO!LEeWjAt}1JPz-c1igyev3CrL^Qs@o+&>KP$WEr8*Zx^B_i7w26pEz)W zWIbGG{pel~IckwmTj-_`+Tn18$o`NR-3ALB<4a+sBNTf(Y*em~{pIMG9V?wj5_~7p z9B^$p{AQ)`B6N*1{Tujv2-a-Qe}!ct{9J$nZoR!&b*c73?U#L%Pv4ZHlhur-Eg)+L z%fwJXmVrI`0JyA+Fp%^dr-->0oC?pRnn#1 z7j{n`y0{nTq%0sS=f#8@i6JIj2Qqkh@XGMz;pw`Waevx&xNAe7F(HpK0oQj-l?0T9 z%lQRJU_Jx)TWmv8DD!2_q-fGIl^V>-gVXLh^JH5PE*$Y)_DvtYm0l7K{%YyVr8BNs zkf_&9NtfXUf}((-E?7`}Reo0vaaQ0Lw#*=9OijPC=klH@58P%9wB&hkKSWXrR-qie z1;-_gS=WlL7F{d7S~~5St@ayhC#B0;^Gs1dyCs-qx-5r7^YXmA==Z3Qwk7%CE!80; zUQMnFsQA?jnSz9NUEYNy>BgCUzrNx8{&=B0E^QG0P4_dJtpV9KUYV_kOk({Vo>*F2 zKI5Blu(bjOs!EAvb-Ul#FtK+zNryE;&t7ddXAO?L{5ksx;FjK8oBm0ZK+uF1Bk zys5)M)5ebpVQRya2rjR<)^N39CjC}s<#O?+H>B64Z>X-TW_#zV{lz<{I+wF5XU(^= z>hDS+_=*r{+}99A<`}X~ab%mKWK(ZtRxGnzygK~y@ND&*-e1@_1;1dnb$0MpRwE+Y zgvd4lS&%F5xw>cCk z&G>!5?1=FvV_o{^cw9;OwFd!9!JtXUgV@&qZ{(kl}aC%7E-%mNL;JyyD=zm7WtH?-3 z#uLc+0F00X?)!ne>1ZVFp+(3*ClYCNK$_KSqJZhuw zh0{ILva6u60_O~TgV)`Iq)k9-rh8Th^qzfYUif_7TkFCt%WA~8PN(<=_knnpMD+GE^yYAul$EU=@ cB&lD4&Av!A;khZyxGj?XQO626jkt*Z54*0d5dZ)H diff --git a/agents/__init__.py b/agents/__init__.py deleted file mode 100644 index 86b5e18..0000000 --- a/agents/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from .agent_base import Agent -from .agent_filtre_images import AgentFiltreImages -from .agent_analyse_image import AgentAnalyseImage -from .agent_question_reponse import AgentQuestionReponse - -__all__ = [ - 'Agent', - 'AgentFiltreImages', - 'AgentAnalyseImage', - 'AgentQuestionReponse' -] \ No newline at end of file diff --git a/agents/__pycache__/__init__.cpython-312.pyc b/agents/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 35edb3fe41495218298ae47df77dd0025ab96578..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 425 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 diff --git a/agents/__pycache__/agent_base.cpython-312.pyc b/agents/__pycache__/agent_base.cpython-312.pyc deleted file mode 100644 index f156114bfa38fc54043e04109b0ee8b9530684e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7583 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 diff --git a/agents/__pycache__/agent_filtre_images.cpython-312.pyc b/agents/__pycache__/agent_filtre_images.cpython-312.pyc deleted file mode 100644 index 6b1c2927d9aa6f877223ec865f60439d54b93396..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6801 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 RTee9HRk39M5|LVG_&-M=??C_n diff --git a/agents/__pycache__/agent_question_reponse.cpython-312.pyc b/agents/__pycache__/agent_question_reponse.cpython-312.pyc deleted file mode 100644 index d75c4f258790efafb04b5a9623d20ef5f88f57e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16286 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 diff --git a/agents/agent_analyse_image.py b/agents/agent_analyse_image.py deleted file mode 100644 index 5933e44..0000000 --- a/agents/agent_analyse_image.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Agent pour analyser en dĂ©tail les images pertinentes dans un contexte de support technique. -""" - -import os -from typing import Dict, Any, Optional - -from .agent_base import Agent -from llm import Pixtral - -class AgentAnalyseImage(Agent): - """ - Agent qui analyse en dĂ©tail le contenu d'une image technique. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'agent d'analyse d'images. - - Args: - api_key: ClĂ© API pour le LLM - """ - super().__init__("AgentAnalyseImage") - self.llm = Pixtral(api_key=api_key) - self.llm.system_prompt = """ -Vous ĂŞtes un expert en analyse d'images techniques. -Votre rĂ´le est d'examiner des captures d'Ă©cran ou des photos liĂ©es Ă  des problèmes techniques et de: -1. DĂ©crire prĂ©cisĂ©ment le contenu de l'image -2. Identifier les Ă©lĂ©ments techniques visibles (erreurs, interfaces, configurations) -3. Extraire tout texte visible (messages d'erreur, logs, indicateurs) - -Soyez prĂ©cis et factuel dans votre analyse. -""" - - def executer(self, image_path: str, contexte: Optional[str] = None) -> Dict[str, Any]: - """ - Analyse en dĂ©tail une image technique. - - Args: - image_path: Chemin vers l'image Ă  analyser - contexte: Contexte optionnel du ticket pour une analyse plus pertinente - - Returns: - Dictionnaire contenant l'analyse de l'image - """ - # VĂ©rifier que l'image existe - if not os.path.exists(image_path): - erreur = f"L'image {image_path} n'existe pas" - self.ajouter_historique("analyse_image_erreur", image_path, erreur) - return {"error": erreur} - - # Construire le prompt pour l'analyse - if contexte: - prompt = f""" -Analysez cette image dans le contexte suivant: - -{contexte} - -DĂ©crivez prĂ©cisĂ©ment: -1. Ce que vous voyez dans l'image -2. Les Ă©lĂ©ments techniques visibles -3. Tout texte visible (messages d'erreur, logs, etc.) -4. Les indices sur le problème potentiel -""" - else: - prompt = """ -Analysez cette image en dĂ©tail et dĂ©crivez ce que vous voyez. -Identifiez tout problème technique visible, messages d'erreur, et Ă©lĂ©ments importants. -""" - - # Enregistrer l'action dans l'historique - self.ajouter_historique("analyse_image", image_path, "Analyse en cours...") - - # Appel au LLM - try: - resultat = self.llm.analyze_image(image_path, prompt) - - # VĂ©rifier si l'appel a rĂ©ussi - if "error" in resultat: - self.ajouter_historique("analyse_image_erreur", image_path, resultat["error"]) - return resultat - - self.ajouter_historique("analyse_image_resultat", "Analyse terminĂ©e", - resultat.get("content", "")[:200]) - return resultat - except Exception as e: - erreur = f"Erreur lors de l'analyse: {str(e)}" - self.ajouter_historique("analyse_image_erreur", image_path, erreur) - return {"error": erreur} \ No newline at end of file diff --git a/agents/agent_base.py b/agents/agent_base.py deleted file mode 100644 index 580d659..0000000 --- a/agents/agent_base.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Module dĂ©finissant la classe abstraite Agent qui servira de base pour tous les agents -spĂ©cialisĂ©s du système d'analyse de tickets. -""" - -import os -import json -from abc import ABC, abstractmethod -from datetime import datetime -from typing import Dict, List, Any, Optional - -class Agent(ABC): - """ - Classe abstraite dĂ©finissant l'interface commune de tous les agents. - """ - def __init__(self, nom: str): - """ - Initialise un agent avec son nom et son historique d'actions. - - Args: - nom: Nom de l'agent - """ - self.nom: str = nom - self.historique: List[Dict[str, Any]] = [] - self.llm_params: Dict[str, Any] = {} - self.llm = None - - def ajouter_historique(self, action: str, input_data: Any, output_data: Any) -> None: - """ - Ajoute une entrĂ©e dans l'historique de l'agent. - - Args: - action: Type d'action rĂ©alisĂ©e - input_data: DonnĂ©es d'entrĂ©e (limitĂ©es pour Ă©conomiser l'espace) - output_data: DonnĂ©es de sortie (limitĂ©es pour Ă©conomiser l'espace) - """ - self.historique.append({ - "timestamp": datetime.now().isoformat(), - "action": action, - "input": str(input_data)[:500], # Limitation pour Ă©viter des historiques trop volumineux - "output": str(output_data)[:500] # Limitation pour Ă©viter des historiques trop volumineux - }) - - def obtenir_historique(self) -> List[Dict[str, Any]]: - """ - Retourne l'historique complet de l'agent. - - Returns: - Liste d'actions avec leurs timestamp et donnĂ©es - """ - return self.historique - - def sauvegarder_historique(self, chemin_fichier: str) -> bool: - """ - Sauvegarde l'historique de l'agent dans un fichier JSON. - - Args: - chemin_fichier: Chemin oĂą sauvegarder le fichier JSON - - Returns: - True si la sauvegarde a rĂ©ussi, False sinon - """ - try: - # CrĂ©er le rĂ©pertoire parent si nĂ©cessaire - os.makedirs(os.path.dirname(chemin_fichier), exist_ok=True) - - with open(chemin_fichier, 'w', encoding='utf-8') as f: - json.dump(self.historique, f, ensure_ascii=False, indent=2) - return True - except Exception as e: - print(f"Erreur lors de la sauvegarde de l'historique: {e}") - return False - - def configurer_llm(self, **parametres: Any) -> None: - """ - Configure les paramètres du LLM associĂ© Ă  l'agent. - - Args: - **parametres: Paramètres Ă  configurer (tempĂ©rature, modèle, etc.) - """ - if self.llm is None: - raise ValueError("Aucun LLM associĂ© Ă  cet agent") - - # Enregistrer les paramètres modifiĂ©s - self.llm_params.update(parametres) - - # Appliquer les paramètres au LLM - for param, valeur in parametres.items(): - if hasattr(self.llm, param): - setattr(self.llm, param, valeur) - else: - print(f"Avertissement: Le paramètre '{param}' n'existe pas dans le LLM") - - # Ajouter Ă  l'historique - self.ajouter_historique("configuration_llm", - f"Paramètres: {parametres}", - f"Paramètres actuels: {self.obtenir_parametres_llm()}") - - def obtenir_parametres_llm(self) -> Dict[str, Any]: - """ - Obtient les paramètres actuels du LLM associĂ© Ă  l'agent. - - Returns: - Dictionnaire des paramètres actuels du LLM - """ - if self.llm is None: - return {} - - # Paramètres Ă  rĂ©cupĂ©rer (Ă©tendre selon vos besoins) - params_keys = [ - "model", "temperature", "max_tokens", "top_p", - "frequency_penalty", "presence_penalty", "system_prompt" - ] - - # Extraire les valeurs des paramètres - params = {} - for key in params_keys: - if hasattr(self.llm, key): - params[key] = getattr(self.llm, key) - - return params - - def generer_rapport_parametres(self) -> Dict[str, Any]: - """ - GĂ©nère un rapport des paramètres utilisĂ©s par l'agent. - - Returns: - Dictionnaire contenant les informations sur les paramètres - """ - return { - "agent": self.nom, - "llm_type": self.llm.__class__.__name__ if self.llm else "Aucun", - "parametres": self.obtenir_parametres_llm(), - "parametres_modifies": self.llm_params - } - - def appliquer_parametres_globaux(self, params_globaux: Dict[str, Any]) -> None: - """ - Applique des paramètres globaux au LLM de l'agent. - Les paramètres spĂ©cifiques dĂ©jĂ  dĂ©finis ont prioritĂ© sur les globaux. - - Args: - params_globaux: Dictionnaire de paramètres globaux Ă  appliquer - """ - if self.llm is None: - return - - # Filtrer les paramètres applicables - params_a_appliquer = {} - for param, valeur in params_globaux.items(): - # Ne pas Ă©craser les paramètres dĂ©jĂ  dĂ©finis spĂ©cifiquement pour cet agent - if param not in self.llm_params and hasattr(self.llm, param): - params_a_appliquer[param] = valeur - - # Appliquer les paramètres filtrĂ©s - if params_a_appliquer: - self.configurer_llm(**params_a_appliquer) - self.ajouter_historique("application_params_globaux", - f"Paramètres globaux appliquĂ©s: {params_a_appliquer}", - f"Paramètres actuels: {self.obtenir_parametres_llm()}") - - @abstractmethod - def executer(self, *args, **kwargs) -> Dict[str, Any]: - """ - MĂ©thode abstraite que chaque agent concret doit implĂ©menter. - Cette mĂ©thode exĂ©cute la fonction principale de l'agent. - - Returns: - Dictionnaire contenant les rĂ©sultats de l'exĂ©cution - """ - pass \ No newline at end of file diff --git a/agents/agent_filtre_images.py b/agents/agent_filtre_images.py deleted file mode 100644 index d03d4da..0000000 --- a/agents/agent_filtre_images.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Agent pour filtrer les images non pertinentes dans un contexte de support technique. -""" - -import os -import json -import re -from typing import Dict, Any, Optional - -from .agent_base import Agent -from llm import Pixtral - -class AgentFiltreImages(Agent): - """ - Agent qui dĂ©termine si une image est pertinente dans un contexte de support technique. - Filtre les logos, signatures, icĂ´nes, etc. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'agent de filtrage d'images. - - Args: - api_key: ClĂ© API pour le LLM - """ - super().__init__("AgentFiltreImages") - self.llm = Pixtral(api_key=api_key) - - # Configuration par dĂ©faut du LLM - default_system_prompt = """ -Vous ĂŞtes un expert en analyse d'images techniques. Votre mission est de dĂ©terminer -si une image est pertinente dans un contexte de support technique ou non. - -Images PERTINENTES: -- Captures d'Ă©cran montrant des problèmes, erreurs, bugs -- Photos d'Ă©quipements avec problèmes visibles -- SchĂ©mas techniques ou diagrammes -- Graphiques de donnĂ©es techniques - -Images NON PERTINENTES: -- Logos d'entreprise -- Signatures ou avatars -- IcĂ´nes ou boutons isolĂ©s -- Bannières dĂ©coratives, sĂ©parateurs -- Images gĂ©nĂ©riques sans information technique -""" - self.configurer_llm( - system_prompt=default_system_prompt, - temperature=0.2, # Basse tempĂ©rature pour des rĂ©ponses prĂ©cises - max_tokens=500 # RĂ©ponses courtes pour le filtrage - ) - - def executer(self, image_path: str) -> Dict[str, Any]: - """ - DĂ©termine si une image est pertinente pour l'analyse technique. - - Args: - image_path: Chemin vers l'image Ă  analyser - - Returns: - Dictionnaire contenant le rĂ©sultat du filtrage avec au minimum - {'pertinente': True/False} - """ - # VĂ©rifier que l'image existe - if not os.path.exists(image_path): - erreur = f"L'image {image_path} n'existe pas" - self.ajouter_historique("filtre_image_erreur", image_path, erreur) - return {"pertinente": False, "error": erreur} - - # Construire le prompt pour la classification - prompt = """ -Analysez cette image et dĂ©terminez si elle est PERTINENTE ou NON PERTINENTE dans un contexte de support technique. - -RĂ©pondez au format JSON suivant: -{ - "pertinente": true/false, - "type_image": "capture_ecran|photo_equipement|schema|graphique|logo|icone|decorative|autre", - "description": "Brève description du contenu", - "confiance": "valeur de 0 Ă  100", - "justification": "Explication de votre dĂ©cision" -} -""" - - # Enregistrer l'action dans l'historique - self.ajouter_historique("filtre_image", image_path, "Filtrage en cours...") - - # Appel au LLM - try: - # Pour les cas complexes, augmenter lĂ©gèrement la tempĂ©rature - if "complexe" in image_path or os.path.getsize(image_path) > 500000: - self.configurer_llm(temperature=0.4) - self.ajouter_historique("ajustement_temperature", "Augmentation pour image complexe", "temperature=0.4") - - resultat_brut = self.llm.analyze_image(image_path, prompt) - - # Essayer d'extraire le JSON de la rĂ©ponse - try: - content = resultat_brut.get("content", "") - - # Si le contenu est dĂ©jĂ  au format JSON correctement formatĂ© - if content.strip().startswith("{") and content.strip().endswith("}"): - try: - resultat_json = json.loads(content) - except json.JSONDecodeError: - # Si le contenu a la structure JSON mais ne peut pas ĂŞtre dĂ©codĂ© - # nettoyer et rĂ©essayer - content_cleaned = content.replace("```json", "").replace("```", "").strip() - resultat_json = json.loads(content_cleaned) - else: - # Chercher un bloc JSON dans la rĂ©ponse - json_match = re.search(r'```json\s*(.*?)\s*```', content, re.DOTALL) - if json_match: - json_str = json_match.group(1).strip() - else: - # Essayer d'extraire un objet JSON sans les blocs de code - json_match = re.search(r'(\{.*?\})', content, re.DOTALL) - if json_match: - json_str = json_match.group(1).strip() - else: - # Sinon, prendre tout le contenu comme JSON potentiel - json_str = content.strip() - - # Parser le JSON - resultat_json = json.loads(json_str) - - # S'assurer que le champ 'pertinente' existe - if "pertinente" not in resultat_json: - resultat_json["pertinente"] = False - resultat_json["error"] = "Format de rĂ©ponse incorrect" - - # Ajouter les paramètres LLM utilisĂ©s - resultat_json["parametres_llm"] = self.generer_rapport_parametres() - - self.ajouter_historique("filtre_image_resultat", "Filtrage terminĂ©", - f"Pertinente: {resultat_json.get('pertinente', False)}") - return resultat_json - - except Exception as e: - # Pour les modules en mode simulation, utiliser directement la rĂ©ponse - if "pertinente" in resultat_brut.get("content", ""): - try: - resultat_json = json.loads(resultat_brut.get("content", "")) - resultat_json["parametres_llm"] = self.generer_rapport_parametres() - self.ajouter_historique("filtre_image_resultat", "Filtrage terminĂ©", - f"Pertinente: {resultat_json.get('pertinente', False)}") - return resultat_json - except: - pass - - # En cas d'erreur de parsing, retourner un rĂ©sultat par dĂ©faut - resultat = { - "pertinente": False, - "error": f"Erreur de parsing JSON: {str(e)}", - "response_raw": resultat_brut.get("content", "")[:200], - "parametres_llm": self.generer_rapport_parametres() - } - self.ajouter_historique("filtre_image_parsing_erreur", "Erreur de parsing", str(e)) - return resultat - - except Exception as e: - erreur = f"Erreur lors du filtrage: {str(e)}" - self.ajouter_historique("filtre_image_erreur", image_path, erreur) - return { - "pertinente": False, - "error": erreur, - "parametres_llm": self.generer_rapport_parametres() - } \ No newline at end of file diff --git a/agents/agent_question_reponse.py b/agents/agent_question_reponse.py deleted file mode 100644 index 36fc0e5..0000000 --- a/agents/agent_question_reponse.py +++ /dev/null @@ -1,474 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Agent pour extraire et structurer les questions et rĂ©ponses des tickets de support. -""" - -import os -import re -from typing import Dict, List, Any, Optional - -from .agent_base import Agent -from llm import Mistral -from post_process import normaliser_accents - -class AgentQuestionReponse(Agent): - """ - Agent qui extrait les questions et rĂ©ponses des messages de support. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'agent d'extraction de questions et rĂ©ponses. - - Args: - api_key: ClĂ© API pour le LLM - """ - super().__init__("AgentQuestionReponse") - self.llm = Mistral(api_key=api_key) - # Configuration par dĂ©faut du LLM - default_system_prompt = """ -Vous ĂŞtes un expert en analyse de conversations de support technique. - -Votre mission est d'identifier avec prĂ©cision: -1. Le rĂ´le de chaque intervenant (client ou support technique) -2. La nature de chaque message (question, rĂ©ponse, information additionnelle) -3. Le contenu essentiel de chaque message en Ă©liminant les formules de politesse, - signatures, mentions lĂ©gales et autres Ă©lĂ©ments non pertinents - -Pour l'identification client/support: -- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email - comme @cbao.fr, @odoo.com, mentions "support technique", etc. -- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions - -Pour la classification en question/rĂ©ponse: -- Questions: Demandes explicites (avec "?"), demandes implicites de rĂ©solution - de problèmes, descriptions de bugs ou dysfonctionnements -- RĂ©ponses: Explications techniques, solutions proposĂ©es, instructions fournies - par le support - -Concentrez-vous uniquement sur le contenu technique utile en ignorant tous les -Ă©lĂ©ments superflus qui n'apportent pas d'information sur le problème ou sa solution. -""" - self.configurer_llm( - system_prompt=default_system_prompt, - temperature=0.3, # Basse tempĂ©rature pour une extraction prĂ©cise - max_tokens=2000 - ) - - def _nettoyer_contenu(self, texte: str) -> str: - """ - Nettoie le contenu en supprimant signatures, mentions lĂ©gales, etc. - - Args: - texte: Texte brut Ă  nettoyer - - Returns: - Texte nettoyĂ© des Ă©lĂ©ments non pertinents - """ - # Si l'entrĂ©e n'est pas une chaĂ®ne, convertir en chaĂ®ne ou retourner vide - if not isinstance(texte, str): - if texte is None: - return "" - try: - texte = str(texte) - except: - return "" - - # DĂ©tection de contenu HTML - contient_html = bool(re.search(r'<[a-z]+[^>]*>', texte, re.IGNORECASE)) - - # Supprimer les balises HTML - approche plus robuste - try: - # Première passe - balises standard - texte_nettoye = re.sub(r']*>', ' ', texte, flags=re.IGNORECASE) - - # Deuxième passe - balises restantes, y compris les mal formĂ©es - texte_nettoye = re.sub(r'<[^>]*>', ' ', texte_nettoye) - - # Troisième passe pour les balises qui pourraient avoir Ă©chappĂ© - texte_nettoye = re.sub(r'<[^>]*$', ' ', texte_nettoye) # Balises incomplètes Ă  la fin - except Exception as e: - self.ajouter_historique("erreur_nettoyage_html", "Échec", str(e)) - texte_nettoye = texte - - # Remplacer les rĂ©fĂ©rences aux images - texte_nettoye = re.sub(r'\[Image:[^\]]+\]', '[Image]', texte_nettoye) - texte_nettoye = re.sub(r']+>', '[Image]', texte_nettoye, flags=re.IGNORECASE) - - # Supprimer les Ă©lĂ©ments courants non pertinents - patterns_a_supprimer = [ - r'Cordialement,[\s\S]*?$', - r'Bien cordialement,[\s\S]*?$', - r'Bonne rĂ©ception[\s\S]*?$', - r'Ă€ votre disposition[\s\S]*?$', - r'Support technique[\s\S]*?$', - r'L\'objectif du Support Technique[\s\S]*?$', - r'Notre service est ouvert[\s\S]*?$', - r'Dès rĂ©ception[\s\S]*?$', - r'ConfidentialitĂ©[\s\S]*?$', - r'Ce message Ă©lectronique[\s\S]*?$', - r'Droit Ă  la dĂ©connexion[\s\S]*?$', - r'Afin d\'assurer une meilleure traçabilitĂ©[\s\S]*?$', - r'tĂ©l\s*:\s*[\d\s\+]+', - r'mobile\s*:\s*[\d\s\+]+', - r'www\.[^\s]+\.[a-z]{2,3}', - r'\*{10,}.*?\*{10,}', # Lignes de sĂ©paration avec astĂ©risques - r'----.*?----', # Lignes de sĂ©paration avec tirets - ] - - for pattern in patterns_a_supprimer: - texte_nettoye = re.sub(pattern, '', texte_nettoye, flags=re.IGNORECASE) - - # Supprimer les lignes multiples vides - texte_nettoye = re.sub(r'\n\s*\n', '\n', texte_nettoye) - - # Supprimer les espaces multiples - texte_nettoye = re.sub(r'\s+', ' ', texte_nettoye) - - # Convertir les entitĂ©s HTML - html_entities = { - ' ': ' ', '<': '<', '>': '>', '&': '&', - '"': '"', ''': "'", '€': '€', '©': '©', - '®': '®', 'é': 'Ă©', 'è': 'è', 'à': 'Ă ', - 'ç': 'ç', 'ê': 'ĂŞ', 'â': 'â', 'î': 'Ă®', - 'ô': 'Ă´', 'û': 'Ă»' - } - - for entity, char in html_entities.items(): - texte_nettoye = texte_nettoye.replace(entity, char) - - # Normaliser les caractères accentuĂ©s - try: - texte_nettoye = normaliser_accents(texte_nettoye) - except Exception as e: - self.ajouter_historique("erreur_normalisation_accents", "Échec", str(e)) - - return texte_nettoye.strip() - - def _detecter_role(self, message: Dict[str, Any]) -> str: - """ - DĂ©tecte si un message provient du client ou du support. - - Args: - message: Dictionnaire contenant les informations du message - - Returns: - "Client" ou "Support" - """ - # VĂ©rifier le champ 'role' s'il existe dĂ©jĂ  - if "role" in message and message["role"] in ["Client", "Support"]: - return message["role"] - - # Indices de support dans l'email - domaines_support = ["@cbao.fr", "@odoo.com", "support@", "ticket.support"] - indices_nom_support = ["support", "cbao", "technique", "odoo"] - - email = message.get("email_from", "").lower() - # Nettoyer le format "Nom " - if "<" in email and ">" in email: - match = re.search(r'<([^>]+)>', email) - if match: - email = match.group(1).lower() - - # VĂ©rifier le domaine email - if any(domaine in email for domaine in domaines_support): - return "Support" - - # VĂ©rifier le nom d'auteur - auteur = "" - if "author_id" in message and isinstance(message["author_id"], list) and len(message["author_id"]) > 1: - auteur = str(message["author_id"][1]).lower() - elif "auteur" in message: - auteur = str(message["auteur"]).lower() - - if any(indice in auteur for indice in indices_nom_support): - return "Support" - - # Par dĂ©faut, considĂ©rer comme client - return "Client" - - def _analyser_messages_llm(self, messages: List[Dict[str, Any]]) -> Dict[str, Any]: - """ - Utilise le LLM pour analyser les messages et en extraire les questions/rĂ©ponses. - - Args: - messages: Liste des messages Ă  analyser - - Returns: - Analyse des messages et paires de questions/rĂ©ponses - """ - self.ajouter_historique("analyse_messages_llm", f"{len(messages)} messages", "Analyse en cours...") - - # VĂ©rifier s'il y a des messages Ă  analyser - if len(messages) == 0: - self.ajouter_historique("analyse_messages_llm_erreur", "Aucun message", "La liste des messages est vide") - return { - "success": False, - "error": "Aucun message Ă  analyser", - "messages_analyses": [], - "paires_qr": [] - } - - # VĂ©rifier si nous n'avons qu'un seul message (probablement le message du système) - if len(messages) == 1: - message_unique = messages[0] - role = message_unique.get("role", "") - - # Si c'est un message système, nous n'avons pas de vraie conversation - if role == "system": - self.ajouter_historique("analyse_messages_llm_erreur", "Un seul message système", - "Pas de conversation Ă  analyser") - return { - "success": True, - "messages_analyses": [], - "paires_qr": [] - } - - try: - # PrĂ©paration des messages pour le LLM - messages_for_llm = [] - for i, msg in enumerate(messages): - # Inclure uniquement les messages de type Client ou Support - role = msg.get("role", "") - if role not in ["Client", "Support"]: - continue - - # Formater le message pour le LLM - messages_for_llm.append({ - "numero": i + 1, - "role": role, - "date": msg.get("date", ""), - "contenu": msg.get("body", "") - }) - - # S'il n'y a aucun message Client ou Support - if not messages_for_llm: - self.ajouter_historique("analyse_messages_llm_erreur", "Aucun message pertinent", - "Pas de message Client ou Support Ă  analyser") - return { - "success": True, - "messages_analyses": [], - "paires_qr": [] - } - - # Utiliser la nouvelle mĂ©thode analyze_messages_json de Mistral - resultat = self.llm.analyze_messages_json(messages_for_llm) - - if "error" in resultat: - self.ajouter_historique("analyse_messages_llm_erreur", "Erreur API", resultat["error"]) - return { - "success": False, - "error": resultat["error"], - "messages_analyses": [], - "paires_qr": [] - } - - contenu = resultat.get("content", "") - self.ajouter_historique("analyse_messages_llm_resultat", "Analyse complĂ©tĂ©e", contenu[:200] + "...") - - # Traiter la rĂ©ponse pour extraire les messages analysĂ©s - messages_analyses = [] - pattern_messages = r"MESSAGE (\d+):\s*- RĂ´le: (Client|Support)\s*- Type: (Question|RĂ©ponse|Information)\s*- Contenu essentiel: (.*?)(?=MESSAGE \d+:|PAIRE \d+:|$)" - for match in re.finditer(pattern_messages, contenu, re.DOTALL): - num = int(match.group(1)) - role = match.group(2) - type_msg = match.group(3) - contenu_essentiel = match.group(4).strip() - - # Trouver le message correspondant - msg_idx = num - 1 - msg_id = "" - msg_date = "" - - if 0 <= msg_idx < len(messages_for_llm): - original_idx = messages_for_llm[msg_idx]["numero"] - 1 - if 0 <= original_idx < len(messages): - msg_id = messages[original_idx].get("id", "") or messages[original_idx].get("ID", "") - msg_date = messages[original_idx].get("date", "") - - messages_analyses.append({ - "id": msg_id, - "date": msg_date, - "role": role, - "type": type_msg, - "contenu": contenu_essentiel - }) - - # Extraire les paires QR - paires_qr = [] - pattern_paires = r"PAIRE (\d+):\s*- Question \((Client|Support)\): (.*?)(?:\s*- RĂ©ponse \((Client|Support)\): (.*?))?(?=PAIRE \d+:|$)" - for match in re.finditer(pattern_paires, contenu, re.DOTALL): - num = match.group(1) - q_role = match.group(2) - question = match.group(3).strip() - r_role = match.group(4) if match.group(4) else "" - reponse = match.group(5).strip() if match.group(5) else "" - - paires_qr.append({ - "numero": num, - "question": { - "role": q_role, - "contenu": question - }, - "reponse": { - "role": r_role, - "contenu": reponse - } if reponse else None - }) - - # Ne pas gĂ©nĂ©rer de paires artificielles si le LLM n'en a pas dĂ©tectĂ© - if not paires_qr: - self.ajouter_historique("analyse_paires_qr", "Aucune paire", "Le LLM n'a dĂ©tectĂ© aucune paire question/rĂ©ponse") - - return { - "success": True, - "messages_analyses": messages_analyses, - "paires_qr": paires_qr - } - - except Exception as e: - self.ajouter_historique("analyse_messages_llm_erreur", f"{len(messages)} messages", str(e)) - return { - "success": False, - "error": str(e), - "messages_analyses": [], - "paires_qr": [] - } - - def _generer_tableau_markdown(self, paires_qr: List[Dict[str, Any]]) -> str: - """ - GĂ©nère un tableau Markdown avec les questions et rĂ©ponses. - - Args: - paires_qr: Liste de paires question/rĂ©ponse - - Returns: - Tableau Markdown formatĂ© - """ - # CrĂ©er le tableau - markdown = ["# Analyse des Questions et RĂ©ponses\n"] - markdown.append("| Question | RĂ©ponse |") - markdown.append("|---------|---------|") - - for paire in paires_qr: - question = paire.get("question", {}) - reponse = paire.get("reponse", {}) - - q_role = question.get("role", "Client") - q_contenu = question.get("contenu", "") - - # Normaliser le contenu des questions pour corriger les accents - q_contenu = normaliser_accents(q_contenu) - - if reponse: - r_role = reponse.get("role", "Support") - r_contenu = reponse.get("contenu", "") - - # Normaliser le contenu des rĂ©ponses pour corriger les accents - r_contenu = normaliser_accents(r_contenu) - - markdown.append(f"| **{q_role}**: {q_contenu} | **{r_role}**: {r_contenu} |") - else: - markdown.append(f"| **{q_role}**: {q_contenu} | *Pas de rĂ©ponse* |") - - # Ajouter les informations sur les paramètres LLM utilisĂ©s - markdown.append("\n## Paramètres LLM utilisĂ©s\n") - params = self.generer_rapport_parametres() - markdown.append(f"- **Type de LLM**: {params['llm_type']}") - markdown.append(f"- **Modèle**: {params['parametres'].get('model', 'Non spĂ©cifiĂ©')}") - markdown.append(f"- **TempĂ©rature**: {params['parametres'].get('temperature', 'Non spĂ©cifiĂ©e')}") - markdown.append(f"- **Tokens max**: {params['parametres'].get('max_tokens', 'Non spĂ©cifiĂ©')}") - - if params['parametres_modifies']: - markdown.append("\n**Paramètres modifiĂ©s durant l'analyse:**") - for param, valeur in params['parametres_modifies'].items(): - if param != 'system_prompt': # Exclure le system_prompt car trop long - markdown.append(f"- **{param}**: {valeur}") - - # Normaliser tout le contenu markdown final pour s'assurer que tous les accents sont corrects - return normaliser_accents("\n".join(markdown)) - - def executer(self, messages_data: List[Dict[str, Any]], output_path: Optional[str] = None) -> Dict[str, Any]: - """ - Analyse les messages pour extraire les questions et rĂ©ponses. - - Args: - messages_data: Liste des messages du ticket - output_path: Chemin oĂą sauvegarder le tableau Markdown (optionnel) - - Returns: - RĂ©sultats de l'analyse avec le tableau Markdown - """ - self.ajouter_historique("debut_execution", f"{len(messages_data)} messages", "DĂ©but de l'analyse") - - try: - # PrĂ©paration des messages - messages_prepares = [] - for msg in messages_data: - # Nettoyer le contenu - contenu = msg.get("body", "") or msg.get("contenu", "") - contenu_nettoye = self._nettoyer_contenu(contenu) - - # DĂ©tecter le rĂ´le - role = self._detecter_role(msg) - - # Ajouter le message prĂ©parĂ© si non vide après nettoyage - if contenu_nettoye.strip(): - messages_prepares.append({ - "id": msg.get("id", "") or msg.get("ID", ""), - "date": msg.get("date", ""), - "author_id": msg.get("author_id", []), - "email_from": msg.get("email_from", ""), - "role": role, - "body": contenu_nettoye - }) - - # Trier par date si disponible - messages_prepares.sort(key=lambda x: x.get("date", "")) - - # Analyser avec le LLM - resultats_analyse = self._analyser_messages_llm(messages_prepares) - - # GĂ©nĂ©rer le tableau Markdown avec normalisation des accents - tableau_md = self._generer_tableau_markdown(resultats_analyse.get("paires_qr", [])) - - # Dernière vĂ©rification pour s'assurer que les accents sont normalisĂ©s - tableau_md = normaliser_accents(tableau_md) - - # Sauvegarder le tableau si un chemin est fourni - if output_path: - try: - # CrĂ©er le dossier parent si nĂ©cessaire - os.makedirs(os.path.dirname(output_path), exist_ok=True) - - with open(output_path, 'w', encoding='utf-8') as f: - f.write(tableau_md) - - self.ajouter_historique("sauvegarde_tableau", output_path, "Tableau sauvegardĂ©") - except Exception as e: - self.ajouter_historique("erreur_sauvegarde", output_path, str(e)) - - # PrĂ©parer le rĂ©sultat - resultat = { - "success": resultats_analyse.get("success", False), - "messages_analyses": resultats_analyse.get("messages_analyses", []), - "paires_qr": resultats_analyse.get("paires_qr", []), - "nb_questions": len(resultats_analyse.get("paires_qr", [])), - "nb_reponses": sum(1 for p in resultats_analyse.get("paires_qr", []) if p.get("reponse")), - "tableau_md": tableau_md, - "parametres_llm": self.generer_rapport_parametres() - } - - self.ajouter_historique("fin_execution", "Analyse terminĂ©e", - f"{resultat['nb_questions']} questions, {resultat['nb_reponses']} rĂ©ponses") - - return resultat - - except Exception as e: - erreur = f"Erreur lors de l'analyse: {str(e)}" - self.ajouter_historique("erreur_execution", "Exception", erreur) - return { - "success": False, - "error": erreur - } \ No newline at end of file diff --git a/config.json b/config.json deleted file mode 100644 index f65b526..0000000 --- a/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "odoo": { - "url": "https://odoo.cbao.fr", - "db": "production_cbao", - "username": "fernand@cbao.fr", - "api_key": "Lestat66!" - }, - "llm": { - "api_key": "your_mistral_api_key" - }, - "output_dir": "output" -} \ No newline at end of file diff --git a/config.json.example b/config.json.example deleted file mode 100644 index 0baee2f..0000000 --- a/config.json.example +++ /dev/null @@ -1,12 +0,0 @@ -{ - "odoo": { - "url": "https://example.odoo.com", - "db": "database_name", - "username": "user@example.com", - "api_key": "your_odoo_api_key_or_password" - }, - "llm": { - "api_key": "your_mistral_api_key" - }, - "output_dir": "output" -} \ No newline at end of file diff --git a/extract_ticket.log b/extract_ticket.log deleted file mode 100644 index bc76c84..0000000 --- a/extract_ticket.log +++ /dev/null @@ -1,4 +0,0 @@ -2025-04-02 11:39:56,293 - extract_ticket - INFO - PrĂ©traitement du ticket: output/ticket_T0167 -> output_processed/ticket_T0167 -2025-04-02 11:39:56,296 - extract_ticket - INFO - Ticket info prĂ©traitĂ© et sauvegardĂ©: output_processed/ticket_T0167/ticket_info.json -2025-04-02 11:39:56,297 - extract_ticket - INFO - Messages prĂ©traitĂ©s et sauvegardĂ©s: output_processed/ticket_T0167/messages.json (2 messages) -2025-04-02 11:39:56,297 - extract_ticket - INFO - Rapport de prĂ©traitement sauvegardĂ©: output_processed/ticket_T0167/pretraitement_rapport.json diff --git a/filter_images.log b/filter_images.log deleted file mode 100644 index 5cba154..0000000 --- a/filter_images.log +++ /dev/null @@ -1 +0,0 @@ -2025-04-02 11:41:31,283 - filter_images - ERROR - Module LLM non trouvĂ©. Veuillez vous assurer que le rĂ©pertoire parent est dans PYTHONPATH. diff --git a/llm-ticket3.code-workspace b/llm-ticket3.code-workspace deleted file mode 100644 index 38d52e0..0000000 --- a/llm-ticket3.code-workspace +++ /dev/null @@ -1,14 +0,0 @@ -{ - "folders": [ - { - "path": "." - }, - { - "path": "../odoo_toolkit" - }, - { - "path": "../llm-ticket2" - } - ], - "settings": {} -} \ No newline at end of file diff --git a/llm/__init__.py b/llm/__init__.py deleted file mode 100644 index 2d072ef..0000000 --- a/llm/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from .llm_base import LLM -from .mistral import Mistral -from .pixtral import Pixtral - -__all__ = ['LLM', 'Mistral', 'Pixtral'] \ No newline at end of file diff --git a/llm/__pycache__/__init__.cpython-312.pyc b/llm/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index d04d5bd80c710fb22ae5aaa544039d13ceb25ba9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 299 zcmX@j%ge<81i|lKr>_Olk3k$5V1hC}8vq&88B!Qh7;_kM8KW2(L2RZRrd;MIW-yyM zhb5Oaij|Qeogsx~5n~ivC95XeOGcnJO~zZyK0dxcirqJ}xTGjC2gD4>tN=5ai3L&9$4uq77_jd0tz9d4>Fw(wxZ|2RL_ulv3 z&UejbgTQ$6_uo3-ScLq7!gzpOj^R2?ha?~_3A8|uv{-lb*l-OEWg{|U%e7+Lwd0yw z(}+&4kia}3fyMQEMrFdScWtMZUj?agJq_}R)1cpLhe;?UOB9V5^&=)Fr)*m)!9oQJ zoNhB%$l?+H>X@%$u6EMEF$(kD&{wdTbc_0X znF`Z{MSkT>MQ29BFaze0aN=qZp&n?i5i|mWo7{RCcG^0`V!1Z2K|EGq^E$WqOj|Ga z%%FB)-WwTm8=wQb&(O1jnNxbRUEP^242UAX31=G=#>P|8Po<|7CW?zT^Evg?IL?z% zT2z|LXXFMgZWT3_h2Adj`ufO2oRCLQh7`ylxvkwM9&ptNP}0T{xM}2HfK+;jHaC+{ zg)9mIl?YstiY4F?1VY&!_bIyNNBtgMdw+9za%jS=iH=;INN8{5;3|Y)ovOfQzTfW! zTu_!%$;Dn+T{1aZkS#|SShz(~cBSI6mx(ma6qJK0dDJfVB!)`qqotLdH0CSqj$rb# z&sL%+zN|ujm#eps$Irt;Th5?VJP&G8dEWjU7TH*O4lK#DKt3abGi2ey9rN?KpI(9K z$NJ(BmPuh(4ivWFDi_IA%28n!zM%=^kaRUi&o4lhC-GeA_mcjR;AH|uzn7&6WVnBq zW=yD1(4dtkw7TG5rL|IBr8oF3?4uS>6j&X15~CfwuO}FG#l#83V`*vk6NV_!s%0dV zd6oe-F_>VX;BrcRB79f|{RFt!fN(*A=b&n#fRj8S@khTZSgyvCkgcDFYz=-VT>uG7zO(^_8l?%y{{^VWw?hl;@HkB99v9Hjt;!~p z0IMz%lUyTCV}LiI1w~$_S&sgbtwx9Hva z(b+GXLjvsJ9I?+0^jWKUWDE#Q#}|*~{f*;WUoSsIacGS92a6>)S82lZ)kgyY(|z?| zssPn_t$RsNtWTh5Gl73RWV+rGeRE+Z*y)y=}Bb1EW?xAJ~EqDS?& vt5m%sUI!I?2;^%(28O0-Cv{yj|Ed%1;?LyL59HDxrlU3QyzwW2sdVCRuXrcf diff --git a/llm/__pycache__/mistral.cpython-312.pyc b/llm/__pycache__/mistral.cpython-312.pyc deleted file mode 100644 index 87b3e7f193370044f7aa9e71be2ebf4474dfc7c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10720 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 Z?aZT{zd<#3;lo72nhE|E;eQ$1{{p?y=cxby diff --git a/llm/__pycache__/pixtral.cpython-312.pyc b/llm/__pycache__/pixtral.cpython-312.pyc deleted file mode 100644 index 559f1b28de9109eba2d87890b922479bd26fbb06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10941 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 Dict[str, Any]: - """ - GĂ©nère une rĂ©ponse Ă  partir d'un prompt. - - Args: - prompt: Texte d'entrĂ©e pour la gĂ©nĂ©ration - **kwargs: Options supplĂ©mentaires - - Returns: - Dictionnaire contenant la rĂ©ponse et les mĂ©tadonnĂ©es - """ - pass - - @abstractmethod - def analyze_image(self, image_path: str, prompt: str, **kwargs) -> Dict[str, Any]: - """ - Analyse une image selon un prompt. - - Args: - image_path: Chemin vers l'image Ă  analyser - prompt: Instructions pour l'analyse - **kwargs: Options supplĂ©mentaires - - Returns: - Dictionnaire contenant l'analyse et les mĂ©tadonnĂ©es - """ - pass \ No newline at end of file diff --git a/llm/mistral.py b/llm/mistral.py deleted file mode 100644 index 8c1b130..0000000 --- a/llm/mistral.py +++ /dev/null @@ -1,243 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Module implĂ©mentant la classe Mistral pour interagir avec l'API Mistral AI. -""" - -import os -import requests -import json -from typing import Dict, List, Any, Optional - -from .llm_base import LLM - -class Mistral(LLM): - """ - ImplĂ©mentation de l'interface LLM pour Mistral AI. - """ - API_URL = "https://api.mistral.ai/v1/chat/completions" - DEFAULT_MODEL = "mistral-medium" - - def __init__(self, api_key: Optional[str] = None): - """ - Initialise le client Mistral. - - Args: - api_key: ClĂ© API Mistral (si None, utilise la variable d'environnement MISTRAL_API_KEY) - """ - api_key = api_key or os.environ.get("MISTRAL_API_KEY") - super().__init__(api_key) - - # Configuration par dĂ©faut - self.model = self.DEFAULT_MODEL - self.temperature = 0.7 - self.max_tokens = 2000 - self.top_p = 1.0 - - # Prompt système par dĂ©faut - self.system_prompt = ( - "Vous ĂŞtes un expert en support technique pour les logiciels spĂ©cialisĂ©s. " - "Analysez prĂ©cisĂ©ment les problèmes techniques dĂ©crits." - ) - - # État d'initialisation - self.initialized = True - self.headers = None - - def initialize(self) -> None: - """ - Initialise la connexion Ă  l'API. - """ - if not self.api_key: - print("Mode simulation: Aucune clĂ© API nĂ©cessaire.") - - self.headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {self.api_key}" - } - - self.initialized = True - - def validate_and_parse_json(self, messages_data: Any) -> List[Dict[str, Any]]: - """ - Valide et analyse les donnĂ©es JSON. - - Args: - messages_data: DonnĂ©es JSON en string ou dĂ©jĂ  dĂ©codĂ©es - - Returns: - Liste d'objets messages validĂ©s - """ - if isinstance(messages_data, str): - try: - messages = json.loads(messages_data) - except json.JSONDecodeError: - return [{"error": "Format JSON invalide", "content": messages_data}] - else: - messages = messages_data - - if not isinstance(messages, list): - return [{"error": "Le format attendu est une liste de messages", "content": str(messages)}] - - return messages - - def generate_response(self, prompt: str, **kwargs) -> Dict[str, Any]: - """ - GĂ©nère une rĂ©ponse textuelle Ă  partir d'un prompt. - - Args: - prompt: Texte d'entrĂ©e pour la gĂ©nĂ©ration - **kwargs: Options supplĂ©mentaires - - Returns: - Dictionnaire contenant la rĂ©ponse et les mĂ©tadonnĂ©es - """ - print("Mode simulation: GĂ©nĂ©ration de rĂ©ponse textuelle") - - # Simulation d'une rĂ©ponse - response = { - "content": f"Je suis un modèle simulĂ©. Voici ma rĂ©ponse Ă  votre prompt: {prompt[:100]}...", - "model": self.model, - "usage": { - "prompt_tokens": len(prompt) // 4, - "completion_tokens": 200, - "total_tokens": len(prompt) // 4 + 200 - } - } - - return response - - def analyze_messages_json(self, messages_json: Any, **kwargs) -> Dict[str, Any]: - """ - Analyse les messages fournis au format JSON pour extraire les questions et rĂ©ponses. - - Args: - messages_json: Messages au format JSON (liste d'objets ou chaĂ®ne JSON) - **kwargs: Options supplĂ©mentaires - - Returns: - Analyse des messages avec identification des questions et rĂ©ponses - """ - print("Mode simulation: Analyse de messages JSON") - - # Valider et analyser le JSON - messages = self.validate_and_parse_json(messages_json) - - if any(msg.get("error") for msg in messages): - error_msg = next((msg.get("error") for msg in messages if msg.get("error")), "Erreur de format JSON") - return {"error": error_msg, "content": ""} - - # Extraire les informations du ticket et de contexte - ticket_info = next((msg for msg in messages if msg.get("id") == "ticket_info"), {}) - ticket_code = ticket_info.get("code", "Inconnu") - ticket_name = ticket_info.get("name", "Ticket sans titre") - ticket_desc = ticket_info.get("description", "") - - # SĂ©parer les messages par rĂ´le - context_msgs = [msg for msg in messages if msg.get("role") == "system" or msg.get("type") == "contexte"] - client_msgs = [msg for msg in messages if msg.get("role") == "Client"] - support_msgs = [msg for msg in messages if msg.get("role") == "Support"] - other_msgs = [msg for msg in messages if msg.get("role") not in ["system", "Client", "Support"] and msg.get("type") != "contexte"] - - # Organisation des messages par ordre chronologique pour analyse - all_content_msgs = client_msgs + support_msgs + other_msgs - # Trier par date si possible - sorted_msgs = sorted(all_content_msgs, key=lambda x: x.get("date", "0"), reverse=False) - - # PrĂ©parer l'analyse des messages - message_analyses = [] - for i, msg in enumerate(sorted_msgs): - role = msg.get("role", "Inconnu") - msg_type = msg.get("type", "Information" if role == "Support" else "Question") - body = msg.get("body", "").strip() - - if body: - message_analyses.append({ - "numero": i + 1, - "role": role, - "type": msg_type, - "contenu": body[:500] # Limiter la longueur du contenu - }) - - # Extraire les paires question-rĂ©ponse - pairs_qr = [] - current_question = None - - for msg in sorted_msgs: - role = msg.get("role", "Inconnu") - body = msg.get("body", "").strip() - - if not body: - continue - - if role == "Client" or (role not in ["Support", "system"] and not current_question): - # Nouveau client message = nouvelle question potentielle - current_question = { - "role": role, - "contenu": body - } - elif role == "Support" and current_question: - # Message de support après une question = rĂ©ponse potentielle - pairs_qr.append({ - "numero": len(pairs_qr) + 1, - "question": current_question, - "reponse": { - "role": role, - "contenu": body - } - }) - current_question = None - - # Ajouter les questions sans rĂ©ponse - if current_question: - pairs_qr.append({ - "numero": len(pairs_qr) + 1, - "question": current_question, - "reponse": None - }) - - # GĂ©nĂ©rer le rĂ©sultat formatĂ© - result = f"ANALYSE DU TICKET {ticket_code}: {ticket_name}\n\n" - - # Ajouter les analyses de messages - for i, msg in enumerate(message_analyses): - result += f"MESSAGE {msg['numero']}:\n" - result += f"- RĂ´le: {msg['role']}\n" - result += f"- Type: {msg['type']}\n" - result += f"- Contenu essentiel: {msg['contenu']}\n\n" - - # Ajouter les paires question-rĂ©ponse - for pair in pairs_qr: - result += f"PAIRE {pair['numero']}:\n" - result += f"- Question ({pair['question']['role']}): {pair['question']['contenu']}\n" - if pair['reponse']: - result += f"- RĂ©ponse ({pair['reponse']['role']}): {pair['reponse']['contenu']}\n\n" - else: - result += "- RĂ©ponse: Aucune rĂ©ponse trouvĂ©e\n\n" - - return { - "content": result, - "model": self.model, - "usage": { - "prompt_tokens": sum(len(msg.get("body", "")) // 4 for msg in messages), - "completion_tokens": len(result) // 2, - "total_tokens": sum(len(msg.get("body", "")) // 4 for msg in messages) + len(result) // 2 - } - } - - def analyze_image(self, image_path: str, prompt: str, **kwargs) -> Dict[str, Any]: - """ - Analyse une image (non supportĂ© par Mistral standard). - - Args: - image_path: Chemin vers l'image Ă  analyser - prompt: Instructions pour l'analyse - **kwargs: Options supplĂ©mentaires - - Returns: - Dictionnaire d'erreur (fonctionnalitĂ© non supportĂ©e) - """ - return { - "error": "L'analyse d'images n'est pas supportĂ©e par Mistral. Utilisez Pixtral." - } \ No newline at end of file diff --git a/llm/pixtral.py b/llm/pixtral.py deleted file mode 100644 index 42b75e9..0000000 --- a/llm/pixtral.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Module implĂ©mentant la classe Pixtral pour l'analyse d'images via l'API Mistral AI. -""" - -import os -import base64 -import requests -import json -from typing import Dict, Any, Optional, List - -from .llm_base import LLM - -class Pixtral(LLM): - """ - ImplĂ©mentation de l'interface LLM pour Pixtral (Mistral AI avec vision). - """ - API_URL = "https://api.mistral.ai/v1/chat/completions" - DEFAULT_MODEL = "pixtral-12b-2409" - - def __init__(self, api_key: Optional[str] = None): - """ - Initialise le client Pixtral. - - Args: - api_key: ClĂ© API Mistral (si None, utilise la variable d'environnement MISTRAL_API_KEY) - """ - api_key = api_key or os.environ.get("MISTRAL_API_KEY") - super().__init__(api_key) - - # Configuration par dĂ©faut - self.model = self.DEFAULT_MODEL - self.temperature = 0.3 - self.max_tokens = 1024 - self.top_p = 1.0 - - # Prompt système par dĂ©faut - self.system_prompt = ( - "Vous ĂŞtes un expert en analyse d'images techniques. " - "DĂ©crivez prĂ©cisĂ©ment ce que vous voyez et identifiez les problèmes visibles." - ) - - # État d'initialisation - self.initialized = True - self.headers = None - - def initialize(self) -> None: - """ - Initialise la connexion Ă  l'API. - """ - if not self.api_key: - print("Mode simulation: Aucune clĂ© API nĂ©cessaire.") - - self.headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {self.api_key}" - } - - self.initialized = True - - def _encode_image(self, image_path: str) -> str: - """ - Encode une image en base64 pour l'API. - - Args: - image_path: Chemin vers l'image - - Returns: - Image encodĂ©e en base64 avec le bon format URI - """ - if not os.path.isfile(image_path): - raise FileNotFoundError(f"Image non trouvĂ©e: {image_path}") - - try: - with open(image_path, "rb") as image_file: - encoded_string = base64.b64encode(image_file.read()).decode("utf-8") - - # DĂ©terminer le type MIME - file_extension = os.path.splitext(image_path)[1].lower() - if file_extension in ['.jpg', '.jpeg']: - mime_type = 'image/jpeg' - elif file_extension == '.png': - mime_type = 'image/png' - elif file_extension == '.gif': - mime_type = 'image/gif' - elif file_extension == '.webp': - mime_type = 'image/webp' - else: - mime_type = 'image/jpeg' # Par dĂ©faut - - return f"data:{mime_type};base64,{encoded_string}" - except Exception as e: - raise IOError(f"Erreur lors de l'encodage de l'image {image_path}: {str(e)}") - - def generate_response(self, prompt: str, **kwargs) -> Dict[str, Any]: - """ - GĂ©nère une rĂ©ponse textuelle Ă  partir d'un prompt. - - Args: - prompt: Texte d'entrĂ©e pour la gĂ©nĂ©ration - **kwargs: Options supplĂ©mentaires - - Returns: - Dictionnaire contenant la rĂ©ponse et les mĂ©tadonnĂ©es - """ - print("Mode simulation: GĂ©nĂ©ration de rĂ©ponse textuelle") - - # Simulation d'une rĂ©ponse - response = { - "content": f"Je suis un modèle simulĂ©. Voici ma rĂ©ponse Ă  votre prompt: {prompt[:50]}...", - "model": self.model, - "usage": { - "prompt_tokens": len(prompt) // 4, - "completion_tokens": 100, - "total_tokens": len(prompt) // 4 + 100 - } - } - - return response - - def analyze_image(self, image_path: str, prompt: str, contexte: str = "", **kwargs) -> Dict[str, Any]: - """ - Analyse une image selon un prompt et un contexte optionnel. - - Args: - image_path: Chemin vers l'image Ă  analyser - prompt: Instructions pour l'analyse - contexte: Contexte du ticket pour contextualiser l'analyse (optionnel) - **kwargs: Options supplĂ©mentaires - - Returns: - Dictionnaire contenant l'analyse et les mĂ©tadonnĂ©es - """ - if not os.path.exists(image_path): - return { - "error": f"Image introuvable: {image_path}", - "content": "", - "model": self.model - } - - print(f"Mode simulation: Analyse d'image {os.path.basename(image_path)}") - - # VĂ©rifier le type de fichier - try: - file_extension = os.path.splitext(image_path)[1].lower() - file_size = os.path.getsize(image_path) - if file_extension not in ['.jpg', '.jpeg', '.png', '.gif', '.webp']: - return { - "error": f"Format d'image non supportĂ©: {file_extension}", - "content": "", - "model": self.model - } - - if file_size > 10 * 1024 * 1024: # 10 MB - return { - "error": f"Image trop volumineuse ({file_size/1024/1024:.2f} MB), max 10 MB", - "content": "", - "model": self.model - } - except Exception as e: - return { - "error": f"Erreur lors de la vĂ©rification de l'image: {str(e)}", - "content": "", - "model": self.model - } - - # Analyser le nom du fichier et le contexte pour la simulation - filename = os.path.basename(image_path).lower() - is_logo = any(substr in filename for substr in ["logo", "signature", "icon", "avatar", "image003"]) - is_screenshot = any(substr in filename for substr in ["screen", "capture", "scr", "interface", "error", "bug", "image004", "image"]) - is_diagram = any(substr in filename for substr in ["diagram", "flow", "schema", "archi"]) - - # Si le contexte spĂ©cifie des problèmes techniques, favoriser la pertinence des captures d'Ă©cran - ticket_has_technical_issue = False - if contexte: - technical_keywords = ["problème", "erreur", "bug", "dysfonctionnement", "ne fonctionne pas", "modification"] - ticket_has_technical_issue = any(kw in contexte.lower() for kw in technical_keywords) - - # Simuler une rĂ©ponse d'analyse d'image - if is_logo or (not is_screenshot and not is_diagram): - # Simuler une image non pertinente - content = json.dumps({ - "pertinente": False, - "type_image": "logo" if is_logo else "autre", - "description": "Cette image semble ĂŞtre un logo, une signature ou un Ă©lĂ©ment graphique dĂ©coratif, et n'est pas pertinente dans un contexte technique.", - "confiance": 90, - "justification": "L'image ne contient pas d'Ă©lĂ©ments techniques utiles pour rĂ©soudre un problème." - }, indent=2) - else: - # Simuler une image pertinente (capture d'Ă©cran ou diagramme) - image_type = "capture_ecran" if is_screenshot else "schema" if is_diagram else "autre" - description = "" - - if is_screenshot: - description = "Capture d'Ă©cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage." - if ticket_has_technical_issue and "image004" in filename: - description = "Capture d'Ă©cran montrant l'interface de gestion des centrales d'enrobage. On peut voir un formulaire avec le champ de nom et une flèche Ă  droite qui permet de modifier certaines propriĂ©tĂ©s." - elif is_diagram: - description = "SchĂ©ma technique montrant l'architecture ou le flux de donnĂ©es du système." - else: - description = "Image technique liĂ©e au contexte du ticket." - - content = json.dumps({ - "pertinente": True, - "type_image": image_type, - "description": description, - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalitĂ©s techniques liĂ©es au problème dĂ©crit dans le ticket." - }, indent=2) - - return { - "content": content, - "model": self.model, - "usage": { - "prompt_tokens": len(prompt) // 4 + (len(contexte) // 8 if contexte else 0), - "completion_tokens": 150, - "total_tokens": len(prompt) // 4 + (len(contexte) // 8 if contexte else 0) + 150 - }, - "image_analyzed": os.path.basename(image_path) - } - - def analyze_images_batch(self, image_paths: List[str], prompt: str, contexte: str = "", **kwargs) -> List[Dict[str, Any]]: - """ - Analyse un lot d'images en une seule fois. - - Args: - image_paths: Liste des chemins vers les images Ă  analyser - prompt: Instructions pour l'analyse - contexte: Contexte du ticket (optionnel) - **kwargs: Options supplĂ©mentaires - - Returns: - Liste de dictionnaires contenant les analyses - """ - results = [] - for image_path in image_paths: - result = self.analyze_image(image_path, prompt, contexte, **kwargs) - results.append({ - "image_path": image_path, - "result": result - }) - - return results \ No newline at end of file diff --git a/main.py b/main.py deleted file mode 100644 index e5eb3fa..0000000 --- a/main.py +++ /dev/null @@ -1,400 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script principal pour l'analyse de tickets de support. -Ce script coordonne l'extraction de donnĂ©es depuis Odoo et l'analyse avec les agents LLM. -""" - -import os -import json -import argparse -import subprocess -import shutil -import re -from typing import Dict, List, Any, Optional - -from utils import TicketAnalyzer, TicketManager -from post_process import transformer_messages, corriger_json_accents, corriger_markdown_accents, reparer_ticket - -def charger_config(config_path: str) -> Dict[str, Any]: - """ - Charge la configuration depuis un fichier JSON. - - Args: - config_path: Chemin vers le fichier de configuration - - Returns: - Dictionnaire de configuration - """ - try: - with open(config_path, 'r', encoding='utf-8') as f: - config = json.load(f) - return config - except Exception as e: - print(f"Erreur lors du chargement de la configuration: {e}") - # Configuration par dĂ©faut minimale - return { - "odoo": { - "url": "https://example.odoo.com", - "db": "db_name", - "username": "user@example.com", - "api_key": "your_api_key" - }, - "llm": { - "api_key": "your_mistral_api_key" - }, - "output_dir": "output" - } - -def extraire_ticket(config: Dict[str, Any], ticket_code: str, output_dir: str) -> Dict[str, Any]: - """ - Extrait les donnĂ©es d'un ticket depuis Odoo. - - Args: - config: Configuration avec les paramètres de connexion - ticket_code: Code du ticket Ă  extraire - output_dir: RĂ©pertoire oĂą sauvegarder les donnĂ©es - - Returns: - DonnĂ©es du ticket extraites - """ - # CrĂ©er le gestionnaire de tickets - manager = TicketManager( - url=config["odoo"]["url"], - db=config["odoo"]["db"], - username=config["odoo"]["username"], - api_key=config["odoo"]["api_key"] - ) - - # RĂ©cupĂ©rer le ticket par son code - ticket = manager.get_ticket_by_code(ticket_code) - if not ticket: - print(f"Ticket {ticket_code} non trouvĂ©") - return {} - - # Extraire toutes les donnĂ©es du ticket - ticket_dir = os.path.join(output_dir, f"ticket_{ticket_code}") - ticket_data = manager.extract_ticket_data(ticket["id"], ticket_dir) - - # Post-traiter immĂ©diatement les messages - post_traiter_messages(ticket_dir) - - return ticket_data - -def post_traiter_messages(ticket_dir: str) -> None: - """ - Post-traite les messages du ticket pour une meilleure analyse. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es du ticket - """ - messages_file = os.path.join(ticket_dir, "messages.json") - - # VĂ©rifier que le fichier existe - if not os.path.exists(messages_file): - print(f"AVERTISSEMENT: Fichier messages.json introuvable dans {ticket_dir}") - return - - print(f"Post-traitement des messages du ticket...") - - # CrĂ©er une sauvegarde avant transformation - backup_file = os.path.join(ticket_dir, "messages.json.backup") - if not os.path.exists(backup_file): - shutil.copy2(messages_file, backup_file) - print(f"Sauvegarde créée: {backup_file}") - - # Transformer les messages pour un format optimal - transformer_messages(messages_file) - - # VĂ©rifier que la transformation a rĂ©ussi - try: - with open(messages_file, 'r', encoding='utf-8') as f: - messages = json.load(f) - print(f"Post-traitement terminĂ©, {len(messages)} messages formatĂ©s.") - except Exception as e: - print(f"ERREUR: Échec du post-traitement: {e}") - # Restaurer la sauvegarde si nĂ©cessaire - if os.path.exists(backup_file): - shutil.copy2(backup_file, messages_file) - print("Restauration de la sauvegarde des messages.") - -def preparer_donnees_ticket(ticket_dir: str) -> Dict[str, Any]: - """ - PrĂ©pare les donnĂ©es du ticket pour l'analyse Ă  partir des fichiers stockĂ©s. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es du ticket - - Returns: - Dictionnaire des donnĂ©es du ticket prĂŞtes pour l'analyse - """ - # Chemins des fichiers sources - ticket_file = os.path.join(ticket_dir, "ticket_info.json") - messages_file = os.path.join(ticket_dir, "messages.json") - attachments_file = os.path.join(ticket_dir, "attachments_info.json") - attachments_dir = os.path.join(ticket_dir, "attachments") - - # VĂ©rifier que les fichiers nĂ©cessaires existent - if not all(os.path.exists(f) for f in [ticket_file, messages_file, attachments_file]): - missing = [f for f in [ticket_file, messages_file, attachments_file] if not os.path.exists(f)] - raise FileNotFoundError(f"Fichiers manquants: {', '.join(missing)}") - - # Charger les donnĂ©es - try: - with open(ticket_file, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - - with open(messages_file, 'r', encoding='utf-8') as f: - messages = json.load(f) - - with open(attachments_file, 'r', encoding='utf-8') as f: - attachments = json.load(f) - - # VĂ©rifier et corriger les chemins des pièces jointes - for attachment in attachments: - if "file_path" in attachment: - # S'assurer que le chemin est absolu - if not os.path.isabs(attachment["file_path"]): - attachment["file_path"] = os.path.join(attachments_dir, os.path.basename(attachment["file_path"])) - - # VĂ©rifier que le fichier existe - if not os.path.exists(attachment["file_path"]): - print(f"AVERTISSEMENT: Pièce jointe introuvable: {attachment['file_path']}") - - return { - "ticket": ticket_info, - "messages": messages, - "attachments": attachments, - "files": { - "ticket_info": ticket_file, - "messages": messages_file, - "attachments_info": attachments_file, - "attachments_dir": attachments_dir - } - } - - except Exception as e: - raise ValueError(f"Erreur lors du chargement des donnĂ©es du ticket: {e}") - -def analyser_ticket(ticket_data: Dict[str, Any], config: Dict[str, Any], output_dir: str, llm_params: Optional[Dict[str, Any]] = None) -> Dict[str, str]: - """ - Analyse un ticket avec les agents LLM. - - Args: - ticket_data: DonnĂ©es du ticket extraites - config: Configuration avec les clĂ©s API - output_dir: RĂ©pertoire oĂą sauvegarder les rĂ©sultats - llm_params: Paramètres LLM globaux Ă  appliquer - - Returns: - Chemins des fichiers gĂ©nĂ©rĂ©s - """ - # CrĂ©er l'analyseur de tickets - analyzer = TicketAnalyzer(api_key=config["llm"]["api_key"], llm_params=llm_params) - - # PrĂ©parer le contexte pour l'analyse des images - ticket_info = ticket_data.get("ticket", {}) - contexte = f""" - TICKET: {ticket_info.get('code', 'Inconnu')} - {ticket_info.get('name', 'Sans titre')} - - DESCRIPTION: - {ticket_info.get('description', 'Aucune description')} - """ - - # RĂ©cupĂ©rer les chemins des pièces jointes (images) - attachments = ticket_data.get("attachments", []) - image_paths = [] - - # VĂ©rification des doublons par nom de fichier - image_noms = set() - - for attachment in attachments: - chemin = attachment.get("file_path") - nom_fichier = os.path.basename(chemin) if chemin else "" - - if not chemin or not os.path.exists(chemin): - continue - - mimetype = attachment.get("mimetype", "") - - # VĂ©rifier que c'est une image et qu'on ne l'a pas dĂ©jĂ  incluse - if mimetype.startswith("image/") and nom_fichier not in image_noms: - image_paths.append(chemin) - image_noms.add(nom_fichier) - print(f"Image ajoutĂ©e pour analyse: {nom_fichier}") - - # Filtrer les images pertinentes - print(f"Filtrage de {len(image_paths)} images...") - images_pertinentes = analyzer.filtrer_images(image_paths) - print(f"Images pertinentes: {len(images_pertinentes)}/{len(image_paths)}") - - # Imprimer les dĂ©tails pour le dĂ©bogage - for i, img in enumerate(image_paths): - est_pertinente = img in images_pertinentes - print(f" Image {i+1}: {os.path.basename(img)} - {'Pertinente' if est_pertinente else 'Non pertinente'}") - - # Analyser les images pertinentes - print("Analyse des images pertinentes...") - resultats_images = analyzer.analyser_images(images_pertinentes, contexte) - print(f"Analyses d'images terminĂ©es: {len(resultats_images)}") - - # Extraire les questions et rĂ©ponses - print("Extraction des questions et rĂ©ponses...") - messages = ticket_data.get("messages", []) - - # VĂ©rifier que les messages sont traitĂ©s et ne contiennent pas de balises HTML - for msg in messages: - body = msg.get("body", "") - if isinstance(body, str) and re.search(r'<[a-z]+[^>]*>', body, re.IGNORECASE): - print(f"AVERTISSEMENT: Message {msg.get('id', 'inconnu')} contient du HTML non traitĂ©") - - qr_path = os.path.join(output_dir, "questions_reponses.md") - resultats_qr = analyzer.extraire_questions_reponses(messages, qr_path) - print(f"Questions extraites: {resultats_qr.get('nb_questions', 0)}") - print(f"RĂ©ponses extraites: {resultats_qr.get('nb_reponses', 0)}") - - # GĂ©nĂ©rer le rapport final - print("GĂ©nĂ©ration du rapport final...") - rapport_dir = os.path.join(output_dir, "rapport") - fichiers = analyzer.generer_rapport(rapport_dir) - print(f"Rapport gĂ©nĂ©rĂ©: {rapport_dir}") - - # Corriger les problèmes d'accents dans les fichiers JSON - corriger_accents_fichiers(rapport_dir) - - return fichiers - -def corriger_accents_fichiers(dir_path: str) -> None: - """ - Corrige les problèmes d'accents dans tous les fichiers JSON et Markdown d'un rĂ©pertoire. - - Args: - dir_path: Chemin du rĂ©pertoire contenant les fichiers Ă  corriger - """ - print("Correction des problèmes d'accents dans les fichiers...") - - if not os.path.exists(dir_path): - print(f"RĂ©pertoire non trouvĂ©: {dir_path}") - return - - for root, _, files in os.walk(dir_path): - for file in files: - # Corriger les fichiers JSON - if file.endswith(".json"): - json_file = os.path.join(root, file) - corriger_json_accents(json_file) - - # Corriger les fichiers Markdown - elif file.endswith(".md"): - md_file = os.path.join(root, file) - corriger_markdown_accents(md_file) - - # Corriger Ă©galement les fichiers Markdown du rĂ©pertoire de ticket - ticket_dir = os.path.dirname(dir_path) - for file in os.listdir(ticket_dir): - if file.endswith(".md"): - md_file = os.path.join(ticket_dir, file) - corriger_markdown_accents(md_file) - - print("Correction des accents terminĂ©e.") - -def main(): - """ - Fonction principale du script. - """ - # Parser les arguments de la ligne de commande - parser = argparse.ArgumentParser(description="Analyse de tickets de support") - parser.add_argument("ticket_code", help="Code du ticket Ă  analyser") - parser.add_argument("--config", "-c", default="config.json", help="Chemin vers le fichier de configuration") - parser.add_argument("--output", "-o", default="output", help="RĂ©pertoire de sortie") - parser.add_argument("--skip-extraction", "-s", action="store_true", help="Ignorer l'extraction du ticket (utiliser les donnĂ©es existantes)") - parser.add_argument("--fix-accents", "-f", action="store_true", help="Corriger les problèmes d'accents dans les fichiers existants") - parser.add_argument("--llm-params", "-p", type=str, help="Paramètres LLM au format JSON (ex: '{\"temperature\": 0.5}')") - parser.add_argument("--reprocess", "-r", action="store_true", help="Forcer le retraitement des messages mĂŞme si l'extraction est ignorĂ©e") - parser.add_argument("--repair", action="store_true", help="RĂ©parer un ticket corrompu avant analyse") - args = parser.parse_args() - - # Charger la configuration - config = charger_config(args.config) - - # Charger les paramètres LLM supplĂ©mentaires si spĂ©cifiĂ©s - llm_params = {} - if args.llm_params: - try: - llm_params = json.loads(args.llm_params) - print(f"Paramètres LLM personnalisĂ©s: {llm_params}") - except json.JSONDecodeError as e: - print(f"Erreur lors du parsing des paramètres LLM: {e}") - - # CrĂ©er le rĂ©pertoire de sortie - os.makedirs(args.output, exist_ok=True) - - # Construire le chemin du rĂ©pertoire du ticket - ticket_dir = os.path.join(args.output, f"ticket_{args.ticket_code}") - - # RĂ©parer le ticket si demandĂ© - if args.repair: - if os.path.exists(ticket_dir): - print(f"RĂ©paration du ticket {args.ticket_code}...") - success = reparer_ticket(ticket_dir) - if not success: - print("ERREUR: La rĂ©paration du ticket a Ă©chouĂ©. Impossible de continuer.") - return - print(f"RĂ©paration terminĂ©e, poursuite de l'analyse...") - else: - print(f"Impossible de rĂ©parer: rĂ©pertoire du ticket {args.ticket_code} introuvable.") - if not args.skip_extraction: - print("Le ticket sera extrait depuis Odoo.") - else: - print("ERREUR: Impossible de continuer sans extraction.") - return - - # Si l'option de correction des accents est activĂ©e uniquement - if args.fix_accents and not args.skip_extraction and not args.repair: - rapport_dir = os.path.join(ticket_dir, "rapport") - if os.path.exists(rapport_dir): - corriger_accents_fichiers(rapport_dir) - return - - # Extraction ou chargement des donnĂ©es du ticket - try: - if not args.skip_extraction: - # Extraire les donnĂ©es du ticket - print(f"Extraction du ticket {args.ticket_code}...") - ticket_data = extraire_ticket(config, args.ticket_code, args.output) - if not ticket_data: - print("Impossible de continuer sans donnĂ©es de ticket.") - return - else: - # Si on ignore l'extraction mais qu'on veut retraiter - if args.reprocess: - print(f"Retraitement forcĂ© des messages du ticket {args.ticket_code}...") - post_traiter_messages(ticket_dir) - - # Charger les donnĂ©es existantes - print(f"Chargement des donnĂ©es du ticket {args.ticket_code}...") - ticket_data = preparer_donnees_ticket(ticket_dir) - print("DonnĂ©es chargĂ©es avec succès.") - - # Analyser le ticket - print(f"Analyse du ticket {args.ticket_code}...") - fichiers = analyser_ticket(ticket_data, config, ticket_dir, llm_params) - - print("\nAnalyse terminĂ©e!") - print(f"Rapport JSON: {fichiers['json']}") - print(f"Rapport Markdown: {fichiers['markdown']}") - - except FileNotFoundError as e: - print(f"ERREUR: {e}") - print("Utilisez l'extraction ou assurez-vous que tous les fichiers nĂ©cessaires existent.") - print("Ou bien utilisez l'option --repair pour rĂ©parer le ticket.") - except ValueError as e: - print(f"ERREUR: {e}") - print("Vous pouvez essayer l'option --repair pour rĂ©parer le ticket.") - except Exception as e: - print(f"ERREUR inattendue: {e}") - print("Vous pouvez essayer l'option --repair pour rĂ©parer le ticket.") - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/output/ticket_T0140/attachments/31975_ecran - 2020-04-07T120505.164.png b/output/ticket_T0140/attachments/31975_ecran - 2020-04-07T120505.164.png deleted file mode 100644 index 9411fc8f3f51c649b1345fa9942089c45358ea11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99024 zcmZs?1y~hb_dbjwAl;oFN*V-dMCnGlyIZFy3`>F)0CZs|O9=YP=Wd7t0)UEgqd z=A4;5JJz1P_PXzT8TeI77!eK+4gvxKQB*`g76JlB7Xkt@{_ShvinBNt7&t-O$x6vV z{C@e9PCAQ&fFOYo75F0WlybQ2>V`j^$opiZzk?)d9)Q$~^Lss^31gOqxj5SSyCyAXZx+s-p{%S#z0r*<<{^eOH=sBF9wZtD zXyY1YiWFQ3BDBMj2RYKM4&8#pPfsEh-(USx$ScNvxwhqAW=CZY>z-IsRFRSKlP1SQ zgCV;vAIlQX;1Su!@ zhgLBXt{f|yp|C|+Z?HcalBwaWwH8G0_<6X}Ycjpq_0REHmP8Wa%T4L%SxNFJGubfB zc^9Mi;kVyZ8>bXBQva5M2*Az`oP52p^&{sPod6;G2-nDi|zvQOx z{`x%en!#xR`)t7kxAiWiRit~)zv-G@TU`Vl@}G(%Sh+2A;yofL{76EADgE-yj81ZF zKX^>^BRd5IJU5CP_Z8l)e!A0#W8Pe2)1sE3GgMzYAO5!&(MtCA_C88%77HwvI!n$w zsps3n(H6Y6+e3w=Eu5A*ZDd|7OmA#m0|PjCB2I4^Ta7uHf4>7ww_9%i@Hpmq>E2hx z-2F{wPM*)RL)uFjm4Wql`+DFO$_0aDF=fztL18$Q)jJSqr@zxb$;GF4UeIh7L!YW@ zCW>&|SC7m>+`4rjg%X)~pK3|I2)Nha-=s5M*EWsY?N{2Oddb(*=gY4w!N zM8B8~58S;%k=kmBMx!73PXCHvGHWafs*;w5r)*^|NpK;r&>*XY?xWg!zYpb8Xtg(m zU#+C2yHezimpUYqmHS;`Lu>Rcj&;hbtudEw4?*Daur}dd`zkZ+*fQH-RixD4a6Z>N z-1Ff9S=ABrI_CX}+1^U(~^ zjZka{1urIWr>7@z*7tZ@Gm#m7RWN53Nv3>c3r=a4>c?`3R9sr;R#}ayri}pUiVHDH zj+$6ef}_Y)O>4O@HIbG}n@T8x11jL)x->?HM<_r{z5QsY<>EoVmXAX6C1|U==vwjw z1m@>$Nt*=Y3?7dK7rs|T7Jct1%0*ZAQOrKR-(0)H2^KODnYp#CtX$-Bqr1NY75@CX zxMDLQD$tc`JU}f!1Z9YcVd@&g+qo$=-$sGCvvf0L4gF`VBCbyor-{r)5u|=Ho#wi4 zJL;N;DuNT$3{Mf51RlJ&&avYsy^>okIW^dR;GUfn?x3K?Y6=Kk%zw?UsS9(k&=FNU zi8BXB(Sq`tn}yZb2ac_{z~F4U{s9o(^kOQM%9(`Rt_S}U1x zd3y3)>MB7^NOa~bob&#n{S^ygfn`ubgEu3W5|t__vwnVlMAJy3vaAwrhPI%zF|lnfceM!>G(Sm&Qu3Lptz6N7VabvG~j}`bBxZj>;?kY033TtO;3H z*O>~*V9wW-A((O7Z&|R?F<-OymxwEOSM#~yR|W@FBrQA+;@z0ZjH&4b)c`$(@_FEVrT^tbh@$Dnj_8Ap5SpEqe+x^4Pxquvw!V`-P%}R%q zgcq7gyaie`-#Ql1O|ys9V{F?(DQD38q|doZ=qZ$nb5?IvR^kEz3VF9_RR_@o6S(oj z6W>#FDwN+IK2Ul4j zokB*5>AM(zt{;431j)pX7G*~nUqm%u6+#9poJnMKwIE5ZBB1WyT4OhjW>VG8!iRs(`RpX4lhT*qmsQsJ<{H01%kBD;s=ybkP`bX%TrAZ_6FDp;E%%}Y zl`4nHT-x>h!tmSpyHAeSB~Nzawb*a%H(H1#?AJcWk8ew1cw;@^7j^96 z%9109THTmJw?fI@vE)3GIE2ZH@JRCb0?y>7@%`p+Sm9Gh1!I&0)IYY)PQs{nBxoc1 z0XTOZb z7jLN?JmM0Vay5;{#PD8Ro1P@Ft?*?=Q(U-PQ7}rfaH(mg1yuOP@_pyq8^;>3?V8f` z45%{OavsD9D=hQAbp#*UM_IwSDSpYQ$`LqaP))kxh^Qmq~L0NoYQ&M;b6PTm)*3

AvM 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%0A=WB= z=tf0;D<3qz*+A>S0P-t{1T34}p*07gD5>VPcBd<~mJWjg3dp7JCiAbl>`vW``pB{B z1!Z4TxIiA<}g24?*pt?Kjf$)?(N#;8V6N?I{P; zt0zJ*i0y_v1b+&%BoELeBzzb=LBM{Pp~R zM<~fX0t6}Fg!VV^YVUj%2V*hnFbAbY5+}TM@~FiC@7O;9-79&KhYjHWcC$3FGQ0Aj z6Jbr4=HX9WpT?0Ikf>W`>`g#l5kK!3&#j>zGj|O2OA37COV)<>wn1Ox;&WoKq!0m4IupLwr^~%zdP2B_vSkJKxt|wH zW-gmB68AMJxUb=*Agy&n?GY|O`Z~Hw!n+qmd5+sCpvru^8P*V$2m(P9Mo?s%=RlK< z0Dml8)4L12zo9qHxkBViy=n3$tl&u4;Skr)Bwg;Xl3j4BKm;Qt%|$C5czV;yMH-bp z)Xy$PQr+g~S@jo>m&l7W;PX?X+b6o#qt>|Alg=o>d36O|1ay+_n;-aQ>JREZ5wN|s z;E8gzo;i%{j)7JzQ!y&&)a+{Li1zT?>ku4AA2lxK+ z1j-dB$^#PQfz{C}tb@r6B>AO<1{0CP`rQ(IJ+J>}>+PA0jCF>TgyrM@WYw*w-PmmR zDJSKX10@j%#*T~6?f2vrZUZ>mrvcsP zC~pXi)aQ?$SUmNYv;n}rUoyU(id-)};k%K{5jJ#XD}mU}3oG_2Cy5 zsM5C1&!gBo7P^>yUo5@{v@>TTe~2FIy1t94>FvYko`0&weMW`oDW=8Q>me2Q8?_=t zFgF0EsbuXv*1maHyG=y5n4e!1D~Yx(wSQ|^iV=rY$$Z+Od;D~n!Bwo;1GS<0d~QL< zFIXG2@ls>bZ&36Q+Y;8FS%TzmVyMp<0?@rKHdA)G2D-HM=F(&IJka!>Tg?+O#ZB@k zL}gY(`x$(J@D>4rB+2@|r=n4CyreXrwLpChcrw@en#%nzS9ye?=Huf_)OgaFIwpBv z9C1%?x}y#40&mq9EY9oZj8~`foFsB(ul?!uE=Ge> z78z6h=Gm^=DOAP{)(c1!M&_l^RX`$&Bpg=`&3j}tca1!W0uYMs!LF*QXT`yAuhmCc zq06Wub882x8I9IzeIEH+M3rf@>K*Wk)s``xh{3TP+okl-+qviAuiY#OqLtln(yRKH zQNMp#BZur_7_&gPhquM$aBh>X^lqFAZ1Qi82CW#|9E`Na7=aB^u(2IV?U#b(0Bw=1 zc?;-5-`s*2X;*SdX`$Wea&Ti~;}-^-spimQTW06H@?utN_^xObH4b-j0kiYExG*qk za&TArumiu34%2UR8ven<%T{S-Fd@j}NX_9j{5zvg-y)$lTWJKYdcUH5o?zkJ- zJ~U~!wD1-oFxhlv52x5;`<^EGS?)3i>@lUK6Mm8=XLy3{DF*upF`_OS!sJ7|Yj))? zkqD%sP=N35ImfxC_7HZ&8|U}EcfzNCy#aIcz6NT(SHImNfBPK`@a>h8G;(ZsA%3|> z7KdB_&O2vR4g0u}*NpVw@0e^CHMc+H$(%7B0ec`s!1Gmvc8Y2t;lM};b|tLmmZA4r z0j3ZyUnTI24$oQn+3v!=g!ndLRfcPj&HTC%;Mv#RFu0CWS21Whoi9Cb9a^Rb?Gw=` zH!Los^li1U_vRaGt6jq{X2q5#VSb;y8teF+=*DKtHbX4yx%q&)NkNzWMl&jxm2__H z;oTv}`Qf*P<@x!&R$oI^ZFY|ap3fNoZ+x7io|ce^jDkWsIqQO{hPygik32ax!e(XZ zaE+hlT!$fX3Sp7XP_8YGdsDV1)diAJF( zYr!4@qgdtu0_QU_N>8!6d%FMg4m7Ryo4!lUd7D!Lx&q@iE9O_sp~l^qVH|k`Bh!*ze~~NY|WAoS)=}H)!cSWxB8( zK}}eXo}p^-U(y3z1LvO{?lS!KdV!Zau8l|{eDNEayZV~3PZa$t<^p##8m#+q6fORb zsGa>a+^I9z1MXx3o1}?!1uI6fCVveC-W2%=M$9V&@_TQ7fU5}2V(xIhbeSeey}Fng zM#YNFq2Cm2E|01U(70tP^hNSFqE*rdjuZvR zc=LXg@Aa_1vPwm}Nv=}B7hB|;*d}>w&q(3J4&!sDez26t=iQFJz}!tyrIQEV=+HJM6aQ{{YFk!c-Hc zly-J!buxF*xEE&3QswZ-h$6iDsT*`}U9FnTxkp9FegjYVZgv@f<5Q*p#Ml#97pVfo zJ~BRI3b@Nl`sNPZK8kE&Hj9%>kxTeW;J0`Vp*diIrN3KtgZ<2}5oz@vN@ zdq-qSXG8WT*dnmYL z%e+R0(vt4q{^0mVR11~AJJh1y7p{-Yd7~Cea5Q!SGYXwbv^p!(FE+7LVDsCZ<2qQKdaX-3Wm$` zFQGDX_{@YMkX{AQg)q7fmXLV!%(!)55~t<(vzT`<-Y{?U9ZkNT<>GBa)wC0>nA+?^ zTI=rCFv`fw^c|w>q(RI@i)jfouEuec!%J+4f|!v__)W!v#cz|LF)7oq{R< z(#c|TdlR&va(ROmf>RfHUYxKH!|puLliC^8GqyZ~5k!Rv7pn+y@COjB7aUQc$f7Sa z7hJFx-`-F%k{ef0s|6teWtS_Rsj9aTtO;K<%^;F4?<kHv_*fby#?Bq zx8*gO-hyi3|6>$;8b9qfEw?(c8Dd2|y*hnmF{!&n8 zaqOFbZnOFPf+#=E6d>dk_9*-}f%C)Mn|O6cjOez8@QtH4hmElyTIJ&3^1)o zp6UOIk=M+el9A{%U^>l9dUm7)h~ROnLWlILO3;x@h6GUv1jL-_Vn&k)0dX?vFQFtz z0CnNY=VI~IF#a-x{A&90DU2u=@(XD)#y7GH^W=@iok+kOg$*2VAkupnc3KL0s2G4L zQNgjP?kz-ttfic7fSg4j&-=Oc_wW)bcD$SiIQ^^o{7h z0nL)E2?Lvqj>{gu32qjJ7VRH7`;qw9*z+vtD1%Dn$<+T(uD8N|QmA%f<%cnp6vU-F zHd;x?pGW@T!n8e9GH6~|Q zmgM1u&@2Pjqz5)4hBeHjnBAlA62xVwAQXk7HyxG4w?N6R4hO!edksLvg+Snnl||CU zGjnjMjFd~55|UmyXa_}tG{yiBeq6jfSPTklapz~FY&o!;T+8%pe$wwiB>Gn@Qb*&- z5L0`&dYGDt{3+04e&dt}o*-#2_4>->p3jiu9#i%8$v0`6!#HY+f{^+GQPM0Xp=CGy8Vwn){Zd7l1y!xnp zXRN}Z^-_&;$`V9hAa23ZM3S%xC+;6(m-hkE@q@kxZ*#;Y-L8`bm;OHn+j%!77juY^ z`!OlC1<9BKT;BD10GV`Z)A+c>Ae236u}K5`)o=dn11ELxzgB#*ty`rnF!GqhiWZxW zpzoK~YaJMyWEnW^H>8FZ;6sQ_{x04HZV_rs3U&Wd+0eM%sguNZCH1CR(k|bsKmApF z>WeXQpHxzaj5yO{`${l*{lHJ?o|P9yVc!+I8_@tV4v`CnhREDxfo3vzY)?v<8Y^V< zU`7z~O-3Z!n%y$65ez%d%gwXn)CznVNv|*+xoQ$~<@IqtH9O%&i3ixVLL{m-PdatF*;OpCqOxeA8>H=+L$zy>IVxu+ zf5Mu>5S4VVgqxdNpz&6N7bVKx+8a0HcSf4_6mE z-->v4j_R6>4?=26RqGV68?b=^f%7ijQTO`UD1)=PwE6Tz_KMlfulHb{_b-R#O5F25 zk1)t?(tq9L#h(_YlKrX$SiA{j9{^Qp@8QygC%tE~+Fv@YYTG z8vijarI8epajRSM_?vCoU6kq$qRfds3=vm8{PHKKNvYzv-o&l!2#7z(KD=UKiLwvG zRJAY9E#-y>R_l}7kFnw1Th47C0g<_l@>mloX5dvnb|BS8=by4zA>AjfT?`XBF8b5A}aXFv`ISOwNBh05$g%GnYeu z&Xm9PZoFpu%>cE@BgqZ9o06}cF4&N|BtkX@w?MY+K)i|V)f;S!`1MNvLf3^``AY?5 zmAANf*&NZpKfx2oJieXU_RB&m03GarV}lnD<>C;dK9`H%3Wb-U#A8o$8t zhimwjmKHMqrCC6}KK(m;53jYWu{S+6nzUcjVIMPm$?)>!(YwRG=eer2w#oLL^MjU? z^hh%1-+m{aJ~=Rdp8|0BEA3#uVxw{v=aOdEk{O(@{;R8mlL;kPXt945lYWOW(`v{u`v=@Gg`e2+=R4=3gEpmAT|02BeW_B)HEQECHrO& zP17}DcTd{yo%GAN)qk~TAzGbx4uN2V0OQrPUF@OpJVNLQEYt$xsldJxfu&6ZWc{u!xgmDax@2fv(~+vA*o9u89Ph&nMx93Zb24#J(SKu*n6XNSG^=JaKxz2ZtJuV9MAMQ%w;)M#2{42AkZ>~(-) zfU*lX?gnSQ==26c3(UpAn&WV2?o#9~nAW@??M_+1V&Wls!aiUTB+ni%J}ig`n*oCT z-!cgQk+pxpBU^6Ah`p6vyQY-maFQC)Ip5O4H%XypJ2wCrdQk50*vNXNYrLl~(=V@R zlV=RaY!8w{fBD20DvmkJPeZ=^>--PMB&}o-0NPsZ5sJ=L0tkk- zM+9J4r%pT5%wF_6G6DVH5=|~s-c4g76#E1Qfb~v#3?*9DC20@@=1%y(V(#J>d6=1_ zB;ltfbk0_65|YoZ42iF~9BL~Tw{$rj=2Zd<*enfLpW-MiWl>XuJ~jaL0K{mM1*Vf= z8+-6Ga>buZzA12Ky)>2m_Lu4k`zz1X9O%^F$1|+6$>rIR7crR#KUnmzM zLfJh+1jSss&EMc9aLIlLn+PD?zy<%l>F_Fe9MKS>E`pZlTok`t615-ht0u0$t{#Jw zZ*ThY>eId9sgo-zYd(ESqWl!;L*iWG?_%iAkX%9>vzNq-EZ~k zo8dh^fDP&Q`F~P!Vab8w*P%oI_T<2^zwMhfDzy#n|Z&TU2@3` zANGjjxIqm@Qjp{!^Y#3S*I|NY=Wpmo+Hc4UD20`?3F06mNl(b)a<~}npQLkB1((j) zr6bQc2$Ht6`>iH)Ia3qq?vB{Jq?C4~>7E=sd02I(!-X^AV*Vb-GHFXJllu*6X<^+x zfe@^D0dN_Xqi?;T@EYEJwQHiWW&ck$uWEsG-I3TCXy9%jY}Z`Vh%LZsk77LW;|Ad z3riCxzHE6qw6cV(=0quvp?hu)W{8gkQ;kOUnmQu*+M9Fy5tZd56vAP9Xc} zA~QiBB6;lh)FTKaQ)xdl5wW&2b4If?au*>8yLiEB+ z#S?24*}oTfvL1b-o%8aGwdpT@jv4s}XINu?SdNZjdI;Pqh!f_1{xsPVRkhxntC>J1 z0NHR9+>d5DLzt+9h<#)1SS%*q)Yh^KBE}*ORSbRu|EIX~jA|;~`Z$Us%21^kgET<` zB4Plg2@y~Np$P#&iU=rOBtYl^8LIRyAOsCui3 zDEk+{(?$%O$R$1?5D3vc*gz^9iSd=r)S0U7b7c&(n+d}KJ5j>S1?sw5spqMM(&R6= z`+tEJo*r|80i&BY1`)Eto(PAW!-TnW$8=eiT!(u1?+7 zeFWjg6hr2-y#z#fT61+b z)1~q5km>DzZaLPM>;qa6fZU+XK>%5ckCJzkM_aT2MDV8)CoAUf)2Pt2758V{5YR!l zIwX#M{vqW@_n`OxNv9xV^eOut3auyufsh%c?NoILoOubD{e+p?hk5p1=ZIj+aDbLi zxQeK7y%m4o_f zE73biK%I(GLJ687ipo_?y_oNQBPTQc017}Zlq=KGP8?0E=l8}k0l{&T+x8^jE9&{( zG{N%d<~fu|d{blH(Y-YTJdj&gjP|%Ys10yE`}sDeHvvD$auE=;70nQWmO@N(B+C_v zodH%CjW z$~e3DDltFy5zGmXgEoQ^Ch`R-X#7@ z2ys9xC8Q3`a;Du91HPxXCuym;&Fp-b^x-A&SpQrjn|)UarR&UCb@BBG`Qh#MFL(6M zmS?_?amRiN_ewEel5Xwhr9|e_j{Zf1f{cr*xlMwmrd)^{LoKkLzab}^09h@tE^qg^ z<3a^YNdIK8)D8bb4!|Q5ALX`>HXM%U zceI632m_VUe>NZe_nDJfcAxy{6=E}o?2lXt*xPS*^XIi@4DHeJ*NZ&aABu^3=K^6f zcMxWP8~DY#)gKmUOfq3}?DMD8+*HaO|NJ!5rH(LR>C06DqByIusMnZMlv?#ufr9W} z+LS^5?o*BAS7aD z>D6ljn0doP6U0K8L^Md7o$x4fA``HF#e!&+-zy5YD-iql{yB@y?vu;>9`S{Ni?jp- z2`>SImBYs8zcEJ7Av9}7b8B=u z9;df?f5(-I>x3@5DKhdG!!53eSVUGGJLom4*a)x7wrX5QMwShb61`u*D|W(J6*s@< zuyKWQB=MWs$2Q?YOfW(sqh75BwOBa2!!qYKR?S7#wke^;oLKxsV*uZ=D;1b;{a{ZM<>m$T0Vqnp)#1EJnk5A?)C|5tV2O z3tl{S20sG^iz_LLsZPw0H)9Z|kO9BFUJ7oWQrGi(Vn=8Z_{?=EBry5@$T$8*B=+Y5V4d^%}lhnxI?{x-MtWr;US6D3J6x3(vyC^L%V$*ERgYx0mKmbLz~M zf9#0Dt+uI_@K%p^32`Jn+T8|eFOTBZAfa2Wo43!c7r_n7aHUJ8sO0=jc$8|1s3S)a zN{P)lQ%Xedi14nJ+u6Qum)TXCsH&t;OH{g9(6Zr?71LCBP{qfw^-`XY>$9BX)gJtq z!=SQZ%;;`rl{njMe34_KOjPD%YRB;r|EGL3SeN@c!>Nn{KLA_&X>7G@7AjxU%-s_) zkbzfxidt8A8F(@mOqVyF^ken!TS`Ltc3do3w~a=8}QE;>~j@Jx<=^TJIf1!^#`T0d&oj-OI`eM8HvxW&r zFEQP7BW(2F}7$U~~vjQ;Z;HO?jX?qLHF%=yWwkr%i!!`B|m^yZhn^-cF5LDDz znzwUtMfV=mkQYX};;{p6GU$T_OY=`(-5FuW+?jya1iO^TK)s zGRjk1EIxw z>~(nuzrjMz^yr|RrTZykC;3g;6zU+&Wq0@ykGAKFajlIF|4!tvWRAH`T4U%Etv{ulX^whef%Rxb?p@TU%c$v=Mekq3J30~gv z0<2Ys6}G)%n|W-Clj;PWncOW>t(`1tfowD%=&QS>T6R7)3v0e;)0w9YdGLjz zZ$(ZM_JP=~I4F3cCvKK$rHP$c%=b@EDo~p2#&EPJY{16R@+Mi!OQpA*=1aEXord0) z^3A02%4e0SB-zl}l(Lb{Gc?hW^U<4@+D@IE+a`puB&pEs<2eRSfCtWBs;(gHP6@6x z0alZ?Zv2XXn;P_}q=NC>aq209wDjruPF)GKri1kJ@`8JHe4&N8u@;{*I}^tMYtUGv zrX+lXnA5Bw@w}(xo}$8sM>Tx>DK=c8)?}90%D9CvPj#NY(-@UEJ0-eo#RJa@ZTxo$ zbGY`i%bdf{w#SfY<9jMI@3Z+V!`RHG8XJ#P1jTqw=Uyd0&25wPn3H|>^qyB+R`3it z&CqWb=i`7R#9)2Qj9Bp*r3|h%$&?;dKha=80(}zWO$zPWIcju9lkh>#!aDo>~^)_hJwX;mt+7=bhyjA4DXd@5>b;+9O(w9o1!~UD-8~4_4NM=aGhc!;B*=K>SEQeN7ethzNUygRFMLe4)`gO;xiIqG+_K=ES^1fZ1HehY{Cx|y z4~WH=7Y2=#+)M3ZiSugQI;8L$x2}Ux+Qu4khJKC#rG-}gom*Vt-S(qzK%$+gS;4;U z5U`Yh&Vpf%-@d8UHftTS`nqIXyF>EUrK0EhCEHt+n})wy;;Z=YpF(qZ6(Y*6m3ir! zdMieE1?3K@)!;f3>Lz5~4%(w0hwQ)5rML1)cT1qJ^}upmU0zAH0f%_hRSsy@RjpX> z`oUNIwEba2C(hStB@do|b@Yl!U}0~|*~$K3>aC!KjiA#;R|@Rp(@`^IH=x7|(|)2f zq&k8RL0)Mmu7zz4nF&<&Wf;g6T@?~ zxEEFxE3Q#pHWweNH#YbEB=mAhW8n2R1@#P8p|MSBr|7d|>@;RY+A^9=>jg3W#=M)K zO;>pNbsqP}%QWdq#CXH}xNPPtAG#kunT%Av7HaNVET0Op#*n{Gy^G|U4{EU+qBevH zX`WEiDHSj~l!P-CRmVri9#p)?CwDPmGFb}SliQ`SzT!4JUpSiZdeHCYKb zjdh*8)bfaO;wwr`J|Osd0e5?ZplErr^^zKb`rz$`?c1x;qP0kkxEXFmk71aE;8(es zuUyAKxmm89f`KyE8CdNr8F>(bVv1vTS88A9Z})BBm|vAGq7+w*J(XhQL)9mAtUCJ} z{XSD>?q>GvEHL;m`)o6dW8AL>MtdcM~}KslRDQQMotxztFssFA5-O;3LGdM#!bYk z(;TFs--5=%zA82iC?#BeQ$edL;C4Problème sur numérotation de lots qui s'effectue par unité !

Serait-il possible de remédier à cela ?

Tél : 06.20.90.27.57

Plage horaire : 9h / 17h

Réf. GestCom : D006435

Origine : Logiciel

", - "date_create": "2020-04-07 13:15:23", - "role": "system", - "type": "contexte", - "body": "TICKET T0140: Problème sur numérotation de lots de béton qui s'effectue par unité !.\n\nDESCRIPTION:

Problème sur numérotation de lots qui s'effectue par unité !

Serait-il possible de remédier à cela ?

Tél : 06.20.90.27.57

Plage horaire : 9h / 17h

Réf. GestCom : D006435

Origine : Logiciel

" - }, - { - "id": "11136", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-10 15:15:54", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0140] Problème sur numérotation de lots de béton qui s'effectue par unité !", - "body": "Bonjour, Oui en effet l'ordre de tri d'affichage par défaut du tableau est par ordre alphabétique car certains de nos clients préfèrent utiliser une numérotation par lettre (A, B, C, D,..) pour identifier les numéros de lot. Si vous souhaitez identifier vos lots par numéro il vous suffit alors de mettre deux ou trois 0 devant chaque numéro de lot (ex: 0001, 0002, 0003,0004,...) Je reste à votre disposition pour toute explication ou demande supplémentaire. L'objectif du" - } -] \ No newline at end of file diff --git a/output/ticket_T0140/messages.json.backup b/output/ticket_T0140/messages.json.backup deleted file mode 100644 index 53a00b5..0000000 --- a/output/ticket_T0140/messages.json.backup +++ /dev/null @@ -1,59 +0,0 @@ -[ - { - "id": 11137, - "body": "", - "date": "2020-04-10 15:15:58", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11072, - "[T0140] Problème sur numérotation de lots de béton qui s'effectue par unité !" - ] - }, - { - "id": 11136, - "body": "

Bonjour,

Oui en effet l'ordre de tri d'affichage par défaut du tableau est par ordre alphabétique car certains de nos clients préfèrent utiliser une numérotation par lettre (A, B, C, D,..) pour identifier les numéros de lot. Si vous souhaitez identifier vos lots par numéro il vous suffit alors de mettre deux ou trois 0 devant chaque numéro de lot (ex: 0001, 0002, 0003,0004,...)
Je reste à votre disposition pour toute explication ou demande supplémentaire.
L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.
Cordialement.

", - "date": "2020-04-10 15:15:54", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0140] Problème sur numérotation de lots de béton qui s'effectue par unité !", - "parent_id": [ - 11072, - "[T0140] Problème sur numérotation de lots de béton qui s'effectue par unité !" - ] - }, - { - "id": 11088, - "body": "", - "date": "2020-04-09 09:49:57", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11072, - "[T0140] Problème sur numérotation de lots de béton qui s'effectue par unité !" - ] - }, - { - "id": 11072, - "body": "", - "date": "2020-04-07 13:15:23", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": false - } -] \ No newline at end of file diff --git a/output/ticket_T0140/questions_reponses.md b/output/ticket_T0140/questions_reponses.md deleted file mode 100644 index 1774812..0000000 --- a/output/ticket_T0140/questions_reponses.md +++ /dev/null @@ -1,15 +0,0 @@ -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 \ No newline at end of file diff --git a/output/ticket_T0140/rapport/ticket_analysis.json b/output/ticket_T0140/rapport/ticket_analysis.json deleted file mode 100644 index 199e599..0000000 --- a/output/ticket_T0140/rapport/ticket_analysis.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "entries": [ - { - "timestamp": "2025-04-01 17:31:17", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T0140/attachments/31975_ecran - 2020-04-07T120505.164.png", - "response": { - "pertinente": false, - "type_image": "autre", - "description": "Cette image semble être un logo, une signature ou un élément graphique décoratif, et n'est pas pertinente dans un contexte technique.", - "confiance": 90, - "justification": "L'image ne contient pas d'éléments techniques utiles pour résoudre un problème.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:31:17", - "action": "extract_questions_reponses", - "agent": "AgentQuestionReponse", - "llm": { - "model": "mistral-medium" - }, - "parametres_llm": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "response": { - "success": true, - "messages_analyses": [ - { - "id": 11136, - "date": "2020-04-10 15:15:54", - "role": "Support", - "type": "Information", - "contenu": "Bonjour, Oui en effet l'ordre de tri d'affichage par défaut du tableau est par ordre alphabétique car certains de nos clients préfèrent utiliser une numérotation par lettre (A, B, C, D,..) pour identifier les numéros de lot. Si vous souhaitez identifier vos lots par numéro il vous suffit alors de mettre deux ou trois 0 devant chaque numéro de lot (ex: 0001, 0002, 0003,0004,...) Je reste à votre disposition pour toute explication ou demande supplémentaire. L'objectif du" - } - ], - "paires_qr": [], - "nb_questions": 0, - "nb_reponses": 0, - "tableau_md": "# Analyse des Questions et Réponses\n\n| Question | Réponse |\n|---------|---------|\n\n## Paramètres LLM utilisés\n\n- **Type de LLM**: Mistral\n- **Modèle**: mistral-medium\n- **Température**: 0.3\n- **Tokens max**: 2000\n\n**Paramètres modifiés durant l'analyse:**\n- **temperature**: 0.3\n- **max_tokens**: 2000", - "parametres_llm": { - "agent": "AgentQuestionReponse", - "llm_type": "Mistral", - "parametres": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n", - "temperature": 0.3, - "max_tokens": 2000 - } - } - } - } - ] -} \ No newline at end of file diff --git a/output/ticket_T0140/rapport/ticket_analysis.md b/output/ticket_T0140/rapport/ticket_analysis.md deleted file mode 100644 index 13bbdc7..0000000 --- a/output/ticket_T0140/rapport/ticket_analysis.md +++ /dev/null @@ -1,76 +0,0 @@ -# Analyse de ticket de support - -## Statistiques - -- Images analysées: 1 (0 pertinentes) -- Questions identifiées: 0 -- Réponses identifiées: 0 - - -## Paramètres LLM par agent - -### Agent de filtrage d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.2 -- **Tokens max**: 500 - -### Agent d'analyse d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.3 -- **Tokens max**: 1024 - -### Agent d'extraction questions-réponses - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - - -## Journal d'actions - -### 2025-04-01 17:31:17 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 31975_ecran - 2020-04-07T120505.164.png -**Résultat**: Non pertinente -**Type**: autre -**Description**: Cette image semble être un logo, une signature ou un élément graphique décoratif, et n'est pas pertinente dans un contexte technique. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:31:17 - AgentQuestionReponse (mistral-medium) -**Action**: extract_questions_reponses -**Questions**: 0 -**Réponses**: 0 - - -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 - -**Paramètres LLM utilisés:** -- **model**: mistral-medium -- **temperature**: 0.3 -- **max_tokens**: 2000 -- **top_p**: 1.0 - ---- diff --git a/output/ticket_T0140/ticket_info.json b/output/ticket_T0140/ticket_info.json deleted file mode 100644 index d69cf1e..0000000 --- a/output/ticket_T0140/ticket_info.json +++ /dev/null @@ -1,140 +0,0 @@ -{ - "id": 152, - "active": true, - "name": "Problème sur numérotation de lots de béton qui s'effectue par unité !", - "description": "

Problème sur numérotation de lots qui s'effectue par unité !

Serait-il possible de remédier à cela ?

Tél : 06.20.90.27.57

Plage horaire : 9h / 17h

Réf. GestCom : D006435

Origine : Logiciel

", - "sequence": 11, - "stage_id": [ - 8, - "Clôturé" - ], - "kanban_state": "normal", - "create_date": "2020-04-07 13:15:23", - "write_date": "2024-10-03 13:10:50", - "date_start": "2020-04-07 09:24:00", - "date_end": false, - "date_assign": "2020-04-07 13:15:23", - "date_deadline": false, - "date_last_stage_update": "2020-04-10 15:15:57", - "project_id": [ - 3, - "Demandes" - ], - "notes": false, - "planned_hours": 0.0, - "user_id": [ - 9, - "Youness BENDEQ" - ], - "partner_id": [ - 7732, - "CONSEIL DEPARTEMENTAL DE HAUTE SAVOIE (74), Patrick LAVY" - ], - "company_id": [ - 1, - "CBAO S.A.R.L." - ], - "color": 0, - "displayed_image_id": false, - "parent_id": false, - "child_ids": [], - "email_from": "patrick.lavy@hautesavoie.fr", - "email_cc": false, - "working_hours_open": 0.0, - "working_hours_close": 0.0, - "working_days_open": 0.0, - "working_days_close": 0.0, - "website_message_ids": [ - 11136 - ], - "remaining_hours": 0.0, - "effective_hours": 0.0, - "total_hours_spent": 0.0, - "progress": 0.0, - "subtask_effective_hours": 0.0, - "timesheet_ids": [], - "priority": "0", - "code": "T0140", - "milestone_id": false, - "sale_line_id": false, - "sale_order_id": false, - "billable_type": "no", - "activity_ids": [], - "message_follower_ids": [ - 10888 - ], - "message_ids": [ - 11137, - 11136, - 11088, - 11072 - ], - "message_main_attachment_id": [ - 31975, - "ecran - 2020-04-07T120505.164.png" - ], - "failed_message_ids": [], - "rating_ids": [], - "rating_last_value": 0.0, - "access_token": "e2a9af6a-dc90-4892-82b7-33fa5d062d75", - "create_uid": [ - 9, - "Youness BENDEQ" - ], - "write_uid": [ - 1, - "OdooBot" - ], - "x_CBAO_windows_maj_ID": false, - "x_CBAO_version_signalement": false, - "x_CBAO_version_correction": false, - "x_CBAO_DateCorrection": false, - "x_CBAO_Scoring_Facilite": 0, - "x_CBAO_Scoring_Importance": 0, - "x_CBAO_Scoring_Urgence": 0, - "x_CBAO_Scoring_Incidence": 0, - "x_CBAO_Scoring_Resultat": 0, - "x_CBAO_InformationsSup": false, - "kanban_state_label": "En cours", - "subtask_planned_hours": 0.0, - "manager_id": [ - 22, - "Fabien LAFAY" - ], - "user_email": "youness@cbao.fr", - "attachment_ids": [ - 31975 - ], - "legend_blocked": "Bloqué", - "legend_done": "Prêt pour la prochaine étape", - "legend_normal": "En cours", - "subtask_project_id": [ - 3, - "Demandes" - ], - "subtask_count": 0, - "analytic_account_active": true, - "allow_timesheets": true, - "use_milestones": false, - "show_time_control": "start", - "is_project_map_empty": true, - "activity_state": false, - "activity_user_id": false, - "activity_type_id": false, - "activity_date_deadline": false, - "activity_summary": false, - "message_is_follower": false, - "message_unread": false, - "message_unread_counter": 0, - "message_needaction": false, - "message_needaction_counter": 0, - "message_has_error": false, - "message_has_error_counter": 0, - "message_attachment_count": 1, - "rating_last_feedback": false, - "rating_count": 0, - "access_url": "/my/task/152", - "access_warning": "", - "display_name": "[T0140] Problème sur numérotation de lots de béton qui s'effectue par unité !", - "__last_update": "2024-10-03 13:10:50" -} \ No newline at end of file diff --git a/output/ticket_T0150/attachments_info.json b/output/ticket_T0150/attachments_info.json deleted file mode 100644 index 0637a08..0000000 --- a/output/ticket_T0150/attachments_info.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/output/ticket_T0150/messages.json b/output/ticket_T0150/messages.json deleted file mode 100644 index 3ecec09..0000000 --- a/output/ticket_T0150/messages.json +++ /dev/null @@ -1,168 +0,0 @@ -[ - { - "id": "ticket_info", - "name": "Problème d'impression des PV de compression des éprouvettes 11H22", - "code": "T0150", - "description": "

La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée.

", - "date_create": "2020-04-14 12:41:38", - "role": "system", - "type": "contexte", - "body": "TICKET T0150: Problème d'impression des PV de compression des éprouvettes 11H22.\n\nDESCRIPTION:

La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée.

" - }, - { - "id": "ticket_info", - "author_id": [ - 0, - "" - ], - "role": "Client", - "type": "Question", - "date": "", - "email_from": "", - "subject": "", - "body": "TICKET T0150: Problème d'impression des PV de compression des éprouvettes 11H22. DESCRIPTION: La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée." - }, - { - "id": "11183", - "author_id": [ - 0, - "" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-14 12:39:49", - "email_from": "Monsieur Yoan Cazard ", - "subject": "Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2.", - "body": "Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour" - }, - { - "id": "11291", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-20 16:40:40", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - { - "id": "11296", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-21 08:29:06", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - { - "id": "11304", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-21 14:57:48", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Etes vous disponible demain dans la matinée ? Je reste" - }, - { - "id": "11305", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-21 15:03:22", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée ? Je reste" - }, - { - "id": "11309", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-22 08:22:21", - "email_from": "\"Youness BENDEQ\" ", - "subject": "False", - "body": "Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique. Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa. Or avec la résistance brute, il obtient une non conformité. Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date. C'est faisable ?" - }, - { - "id": "11320", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-23 09:46:11", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - { - "id": "11321", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-23 10:33:06", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste" - }, - { - "id": "11322", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-23 12:33:46", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien" - }, - { - "id": "11323", - "author_id": [ - 0, - "" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-23 12:59:43", - "email_from": "Support Technique CBAO ", - "subject": "échanges de mail entre M. Pierre PAYA du Cerema d'Aix et M.Dierkens du cerema de LYON", - "body": "-------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien" - }, - { - "id": "11462", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-05-06 11:36:50", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Appeler fait par Youness BENDEQ Pour savoir si la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée a été ajouté. Commentaire Possibilité ajoutée" - } -] \ No newline at end of file diff --git a/output/ticket_T0150/messages.json.backup b/output/ticket_T0150/messages.json.backup deleted file mode 100644 index 72719f2..0000000 --- a/output/ticket_T0150/messages.json.backup +++ /dev/null @@ -1,293 +0,0 @@ -[ - { - "id": 11463, - "body": "", - "date": "2020-05-06 11:37:11", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11462, - "body": "
\n

\n Appeler fait\n par Youness BENDEQ\n \n

\n

Pour savoir si la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée a été ajouté.

\n
\n Commentaire\n

Possibilité ajoutée

\n
\n
\n ", - "date": "2020-05-06 11:36:50", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11323, - "body": "
\r\n", - "date": "2020-04-23 12:59:43", - "author_id": false, - "email_from": "Support Technique CBAO ", - "subject": "échanges de mail entre M. Pierre PAYA du Cerema d'Aix et M.Dierkens du cerema de LYON", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11322, - "body": "
Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton.
Il faut bien distinguer :
- la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section,
- la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30.

Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient.
Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions.

cdlt
Pierre PAYA
Responsable de l'activité Matériaux, Construction et Certification
Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30
Direction Territoriale Méditerranée
\"\"
Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement
www.cerema.fr

Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit :
Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair.

Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais.

Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau?

Yoan CAZARD
Responsable Laboratoire Départemental Routes et Ouvrages d'Art
Conseil Départemental 66
Direction Infrastructures et Déplacements
Développement et Expertise Technique
1265 avenue Julien Panchot
66000 Perpignan
04-68-68-36-90
06-73-87-52-43


De: \"PAYA Pierre\" <Pierre.Paya@cerema.fr>
Ă€: \"CAZARD Yoan\" <yoan.cazard@cd66.fr>
Cc: \"JAN Didier\" <didier.jan@cerema.fr>, \"ddumas\" <ddumas@ardeche.fr>, \"Gérald LACROIX\" <glacroix@cg83.fr>, \"s labourasse\" <s.labourasse@cg04.fr>, \"Stephane roques\" <Stephane.roques@cg12.fr>, \"claude trelcat\" <claude.trelcat@cg84.fr>, \"benoit gaumet\" <benoit.gaumet@cg12.fr>, \"jm dao\" <jm.dao@cg04.fr>, \"a ferrer\" <a.ferrer@cg04.fr>, \"pierre david\" <pierre.david@cg05.fr>, \"philippe delorme\" <philippe.delorme@cg05.fr>, \"Morales Frederic\" <frederic.morales@vaucluse.fr>, \"CELLI Sylvain\" <sylvain.celli@cg-corsedusud.fr>, \"BOISSONNADE-CORP Pierre\" <pierre.boissonnade-corp@cg12.fr>, \"Richard BOREL\" <richard.borel@cg05.fr>, \"alain guiraud\" <alain.guiraud@cg12.fr>, \"raymond cayzac\" <raymond.cayzac@cg12.fr>, \"georges pouget\" <georges.pouget@cg12.fr>, \"noel sanchez\" <noel.sanchez@ct-corse.fr>, \"joseph pau\" <joseph.pau@cg-corsedusud.fr>, \"nicolas teisseire\" <nicolas.teisseire@cg11.fr>, mmohammedi@ardeche.fr, \"jerome gombault\" <jerome.gombault@cg11.fr>, \"alain nargeot\" <alain.nargeot@gard.fr>, \"bhilaire\" <bhilaire@ardeche.fr>, \"TEKATLIAN Annick\" <Annick.TEKATLIAN@cerema.fr>, \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" <Nathalie.Cordier@cerema.fr>, \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" <lisa.gontard@cerema.fr>
Envoyé: Jeudi 23 Avril 2020 10:17:43
Objet: Re: Ecrasements béton

bonjour Ă  tous,

Je viens d'avoir Michael  Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab :
\"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée).
Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\"

Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 :
\"Je rajoute également que doivent figurer dans le PV d'essais :
- la charge maximale Ă  la rupture en N,
- la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\"

Il faut retenir que :
- la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV,
- la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client.

Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC).

Je reste disponible pour toute précision.

bien cordialement,
Pierre PAYA
Responsable de l'activité Matériaux, Construction et Certification
Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30
Direction Territoriale Méditerranée
\"\"
Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement
www.cerema.fr

Le 22/04/2020 à 10:11, > CAZARD Yoan (par Internet) a écrit :

Bonjour Ă  tous,


J'espère que tout le monde va bien dans ce contexte particulier.


Je vous fait remonter une problématique que nous avons rencontrée en passant sur la version web de BRG-LAB. Cela concerne les résultats d'essais des écrasements des éprouvettes 11x22. Les PV ou rapports d'essais n'affichent plus que les résistances brutes sans la correction de 1 MPa. Je vous joins ci-dessous la réponse de CBAO. Je les ai contactés depuis afin de pouvoir ajouter une option à cocher pour choisir d'afficher cette résistance corrigée. Je pense que nous sommes nombreux dans ce cas. Nous sommes dans l'attente d'une solution de CBAO.


Pierre Paya nous avait déjà indiqué de n'afficher que la résistance brute sur le PV d'essais, mais il me semble que nous prenons tous en compte que la résistance corrigée?



Yoan CAZARD
Responsable Laboratoire Départemental Routes et Ouvrages d'Art
Conseil Départemental 66
Direction Infrastructures et Déplacements
Développement et Expertise Technique
1265 avenue Julien Panchot
66000 Perpignan
04-68-68-36-90
06-73-87-52-43


De: \"Youness BENDEQ\" <youness.bendeq@cbao.fr>
Ă€: \"Yohan CAZARD\" <yoan.cazard@cd66.fr>
Envoyé: Jeudi 23 Avril 2020 12:33:06
Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22

\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n Voir Tâche\r\n \r\n \r\n \r\n \"CBAO\r\n
\r\n
\r\n \r\n
\r\n
\r\n

Bonjour,


Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens.


Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ?

Je reste à votre disposition pour toute explication ou demande supplémentaire.

L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.

Cordialement.


Support Technique - CBAO

www.cbao.fr

80 rue Louis Braille

66000 PERPIGNAN

support@cbao.fr

Tél : 04 68 64 15 31

Fax : 04 68 64 31 69 \t

\r\n\r\n


\r\n

\r\n Envoyé\r\n \r\n par\r\n \r\n CBAO S.A.R.L.\r\n \r\n \r\n \r\n .\r\n

\r\n
\r\n \r\n\"\"
", - "date": "2020-04-23 12:33:46", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11321, - "body": "

Bonjour,


Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens.


Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ?

Je reste à votre disposition pour toute explication ou demande supplémentaire.

L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.

Cordialement.


Support Technique - CBAO

www.cbao.fr

80 rue Louis Braille

66000 PERPIGNAN

support@cbao.fr

Tél : 04 68 64 15 31

Fax : 04 68 64 31 69 \t

", - "date": "2020-04-23 10:33:06", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11320, - "body": "
Bonjour,

Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens.

C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais.

Yoan CAZARD
Responsable Laboratoire Départemental Routes et Ouvrages d'Art
Conseil Départemental 66
Direction Infrastructures et Déplacements
Développement et Expertise Technique
1265 avenue Julien Panchot
66000 Perpignan
04-68-68-36-90
06-73-87-52-43


De: \"Youness BENDEQ\" <youness.bendeq@cbao.fr>
Ă€: \"Yohan CAZARD\" <yoan.cazard@cd66.fr>
Envoyé: Lundi 20 Avril 2020 18:40:40
Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22

\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n Voir Tâche\r\n \r\n \r\n \r\n \"CBAO\r\n
\r\n
\r\n \r\n
\r\n
\r\n

Bonjour,

Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée).

En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque.

C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN.


La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel).


Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous.


Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme.

Je reste à votre disposition pour toute explication ou demande supplémentaire.

L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.

Cordialement.

Support Technique - CBAO

www.cbao.fr

80 rue Louis Braille

66000 PERPIGNAN

support@cbao.fr

Tél : 04 68 64 15 31

Fax : 04 68 64 31 69 \t

\r\n\r\n


\r\n

\r\n Envoyé\r\n \r\n par\r\n \r\n CBAO S.A.R.L.\r\n \r\n \r\n \r\n .\r\n

\r\n
\r\n \r\n\"\"
", - "date": "2020-04-23 09:46:11", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11310, - "body": "", - "date": "2020-04-22 08:24:29", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11309, - "body": "

Salut Laurent,

> Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir.

Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup.

Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution.

En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique.

Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa.

Or avec la résistance brute, il obtient une non conformité.

Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date.

C'est faisable ?

", - "date": "2020-04-22 08:22:21", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11305, - "body": "
Oui pas de souci merci.

Yoan CAZARD
Responsable Laboratoire Départemental Routes et Ouvrages d'Art
Conseil Départemental 66
Direction Infrastructures et Déplacements
Développement et Expertise Technique
1265 avenue Julien Panchot
66000 Perpignan
04-68-68-36-90
06-73-87-52-43


De: \"Youness BENDEQ\" <youness.bendeq@cbao.fr>
Ă€: \"Yohan CAZARD\" <yoan.cazard@cd66.fr>
Envoyé: Mardi 21 Avril 2020 16:57:48
Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22

\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n Voir Tâche\r\n \r\n \r\n \r\n \"CBAO\r\n
\r\n
\r\n \r\n
\r\n
\r\n

Bonjour,
Etes vous disponible demain dans la matinée ?
Je reste à votre disposition pour toute explication ou demande supplémentaire.
L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.
Cordialement.

Support Technique - CBAO
www.cbao.fr
80 rue Louis Braille
66000 PERPIGNAN
support@cbao.fr
Tél : 04 68 64 15 31
Fax : 04 68 64 31 69

\r\n\r\n


\r\n

\r\n Envoyé\r\n \r\n par\r\n \r\n CBAO S.A.R.L.\r\n \r\n \r\n \r\n .\r\n

\r\n
\r\n \r\n\"\"
", - "date": "2020-04-21 15:03:22", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11304, - "body": "

Bonjour,
Etes vous disponible demain dans la matinée ?
Je reste à votre disposition pour toute explication ou demande supplémentaire.
L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.
Cordialement.

Support Technique - CBAO
www.cbao.fr
80 rue Louis Braille
66000 PERPIGNAN
support@cbao.fr
Tél : 04 68 64 15 31
Fax : 04 68 64 31 69

", - "date": "2020-04-21 14:57:48", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11296, - "body": "
Bonjour,

Vous pouvez me rappeler?

Yoan CAZARD
Responsable Laboratoire Départemental Routes et Ouvrages d'Art
Conseil Départemental 66
Direction Infrastructures et Déplacements
Développement et Expertise Technique
1265 avenue Julien Panchot
66000 Perpignan
04-68-68-36-90
06-73-87-52-43


De: \"Youness BENDEQ\" <youness.bendeq@cbao.fr>
Ă€: \"Yohan CAZARD\" <yoan.cazard@cd66.fr>
Envoyé: Lundi 20 Avril 2020 18:40:40
Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22

\r\n
\r\n
\r\n \r\n \r\n \r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n Voir Tâche\r\n \r\n \r\n \r\n \"CBAO\r\n
\r\n
\r\n \r\n
\r\n
\r\n

Bonjour,

Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée).

En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque.

C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN.


La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel).


Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous.


Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme.

Je reste à votre disposition pour toute explication ou demande supplémentaire.

L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.

Cordialement.

Support Technique - CBAO

www.cbao.fr

80 rue Louis Braille

66000 PERPIGNAN

support@cbao.fr

Tél : 04 68 64 15 31

Fax : 04 68 64 31 69 \t

\r\n\r\n


\r\n

\r\n Envoyé\r\n \r\n par\r\n \r\n CBAO S.A.R.L.\r\n \r\n \r\n \r\n .\r\n

\r\n
\r\n \r\n\"\"
", - "date": "2020-04-21 08:29:06", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11291, - "body": "

Bonjour,

Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée).

En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque.

C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN.


La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel).


Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous.


Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme.

Je reste à votre disposition pour toute explication ou demande supplémentaire.

L'objectif du Support Technique est de vous aider : n'hésitez jamais à nous contacter si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes.

Cordialement.

Support Technique - CBAO

www.cbao.fr

80 rue Louis Braille

66000 PERPIGNAN

support@cbao.fr

Tél : 04 68 64 15 31

Fax : 04 68 64 31 69 \t

", - "date": "2020-04-20 16:40:40", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11279, - "body": "", - "date": "2020-04-20 13:45:40", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11244, - "body": "", - "date": "2020-04-20 07:01:28", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11190, - "body": "", - "date": "2020-04-14 12:54:18", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11189, - "body": "", - "date": "2020-04-14 12:53:27", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11188, - "body": "", - "date": "2020-04-14 12:53:21", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11185, - "body": "", - "date": "2020-04-14 12:41:38", - "author_id": [ - 2, - "OdooBot" - ], - "email_from": "\"OdooBot\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11184, - "body": "", - "date": "2020-04-14 12:41:38", - "author_id": [ - 2, - "OdooBot" - ], - "email_from": "\"OdooBot\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11183, - "body": "

Notification d'appel\r\n\r\n\r\n\r\n

\r\n\r\n\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n
 \r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\r\n\t\t\t
\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t    \r\n\t\t\t\t\t\t\t\t\t

Version imprimable

\r\n\t\t\t\t\t\t\t\t\t

Notification d'appel

\r\n\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t
Nous avons reçu un appel pour support technique (CBAO) pour le numéro de téléphone +33 / 4 - 11980441.
 
 
 
\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t
Date: Mardi, 14. avril 2020, 14:37
 
Appel de: Monsieur Yoan Cazard, Conseil départemental du 66
 
\r\n\t\t\t\t\t\t\t\t\tTéléphone principal: \r\n\t\t\t\t\t\t\t\t\t\t+33673875243\r\n\t\t\t\t\t\t\t\t
 
Sujet d'appel: Demande technique
 
\r\n\t\t\t\t\t
\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\tEditer les données de l'appelant\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t
 
 
\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t
 \r\n\t\t\t\t\t\t\t\t\tMonsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2. \r\n\t\t\t\t\t\t\t\t 
\r\n\t\t\t\t\t
 
 
 
Nous attendons vos commentaires, afin de nous assurer que vos secrétaires préférés prennent en charge vos appels.
 
\r\n\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      Ne convient       
      pas      \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t      Pas       
 satisfaisant(e) \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t         Correct(e)         
 \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t        Satisfaisant(e)        
 \r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"\"\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSecrétaire
préférée\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t\t\t\t
\r\n\t\t\t\t\t
 
\r\n\t\t\t\t\t\t\t\r\n\t\t\t\t\t\t
 
\r\n\t\t\t\t\t\t\tParrainez un nouveau client
Votre secrétariat bureau24 vous donne satisfaction ? N’attendez plus et recommandez-nous auprès des professionnels de votre réseau! ! Pour chaque parrainage vous bénéficierez d’un bonus de 40 euros sur les frais de consommation. Complétez facilement en ligne le formulaire sécurisé: www.bureau24.fr/parrainage. N'hésitez pas à nous contacter si vous avez la moindre question au 0805 965 770.\r\n\t\t\t\t\t\t
 
\r\n\t\t\t\t\t\t\tVous souhaitez utiliser plus de fonctions pour gérer votre secrétariat ou nous suggérer des améliorations quant à celles existantes? Le travail de notre équipe de développeurs dépend de vos commentaires, n'hésitez pas à nous envoyer vos commentaires à feedback@bureau24.fr\r\n\t\t\t\t\t\t
 
\r\n\t\t
 
\r\n\r\n\r\n", - "date": "2020-04-14 12:39:49", - "author_id": false, - "email_from": "Monsieur Yoan Cazard ", - "subject": "Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2.", - "parent_id": [ - 11182, - "[T0150] Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2." - ] - }, - { - "id": 11182, - "body": "", - "date": "2020-04-14 12:41:38", - "author_id": [ - 2, - "OdooBot" - ], - "email_from": "\"OdooBot\" ", - "subject": false, - "parent_id": false - } -] \ No newline at end of file diff --git a/output/ticket_T0150/messages.json.original b/output/ticket_T0150/messages.json.original deleted file mode 100644 index cc00756..0000000 --- a/output/ticket_T0150/messages.json.original +++ /dev/null @@ -1,155 +0,0 @@ -[ - { - "id": "ticket_info", - "name": "Problème d'impression des PV de compression des éprouvettes 11H22", - "code": "T0150", - "description": "

La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée.

", - "date_create": "2020-04-14 12:41:38", - "role": "system", - "type": "contexte", - "body": "TICKET T0150: Problème d'impression des PV de compression des éprouvettes 11H22.\n\nDESCRIPTION:

La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée.

" - }, - { - "id": "11183", - "author_id": [ - 0, - "" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-14 12:39:49", - "email_from": "Monsieur Yoan Cazard ", - "subject": "Monsieur Cazard souhaite que vous le rappeliez. Il indique avoir un problème au niveau de la moyenne sur des écrasements 11M2.", - "body": "Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour" - }, - { - "id": "11291", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-20 16:40:40", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - { - "id": "11296", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-21 08:29:06", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - { - "id": "11304", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-21 14:57:48", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Etes vous disponible demain dans la matinée ? Je reste à votre disposition pour toute explication ou demande supplémentaire. L'objectif du" - }, - { - "id": "11305", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-21 15:03:22", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée ? Je reste à votre disposition pour toute explication ou demande supplémentaire. L'objectif du" - }, - { - "id": "11309", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-22 08:22:21", - "email_from": "\"Youness BENDEQ\" ", - "subject": "False", - "body": "Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique. Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa. Or avec la résistance brute, il obtient une non conformité. Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date. C'est faisable ?" - }, - { - "id": "11320", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-23 09:46:11", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - { - "id": "11321", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-23 10:33:06", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste" - }, - { - "id": "11322", - "author_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "role": "Client", - "type": "Question", - "date": "2020-04-23 12:33:46", - "email_from": "CAZARD Yoan ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien" - }, - { - "id": "11323", - "author_id": [ - 0, - "" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-23 12:59:43", - "email_from": "Support Technique CBAO ", - "subject": "échanges de mail entre M. Pierre PAYA du Cerema d'Aix et M.Dierkens du cerema de LYON", - "body": "-------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien" - }, - { - "id": "11462", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-05-06 11:36:50", - "email_from": "\"Youness BENDEQ\" ", - "subject": "Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "body": "Appeler fait par Youness BENDEQ Pour savoir si la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée a été ajouté. Commentaire Possibilité ajoutée" - } -] \ No newline at end of file diff --git a/output/ticket_T0150/questions_reponses.md b/output/ticket_T0150/questions_reponses.md deleted file mode 100644 index b1b15b1..0000000 --- a/output/ticket_T0150/questions_reponses.md +++ /dev/null @@ -1,20 +0,0 @@ -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| -| **Client**: Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour | **Support**: Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | -| **Client**: Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "Youness BENDEQ" À: "Yohan CAZARD" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | **Support**: Bonjour, Etes vous disponible demain dans la matinée ? Je reste | -| **Client**: Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "Youness BENDEQ" À: "Yohan CAZARD" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée ? Je reste | **Support**: Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique. Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa. Or avec la résistance brute, il obtient une non conformité. Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date. C'est faisable ? | -| **Client**: Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "Youness BENDEQ" À: "Yohan CAZARD" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | **Support**: Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste | -| **Client**: Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "PAYA Pierre" À: "CAZARD Yoan" Cc: "JAN Didier" , "ddumas" , "Gérald LACROIX" , "s labourasse" , "Stephane roques" , "claude trelcat" , "benoit gaumet" , "jm dao" , "a ferrer" , "pierre david" , "philippe delorme" , "Morales Frederic" , "CELLI Sylvain" , "BOISSONNADE-CORP Pierre" , "Richard BOREL" , "alain guiraud" , "raymond cayzac" , "georges pouget" , "noel sanchez" , "joseph pau" , "nicolas teisseire" , mmohammedi@ardeche.fr , "jerome gombault" , "alain nargeot" , "bhilaire" , "TEKATLIAN Annick" , "CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB" , "GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : "Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac." Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : " Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment)." Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien | **Support**: -------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "PAYA Pierre" À: "CAZARD Yoan" Cc: "JAN Didier" , "ddumas" , "Gérald LACROIX" , "s labourasse" , "Stephane roques" , "claude trelcat" , "benoit gaumet" , "jm dao" , "a ferrer" , "pierre david" , "philippe delorme" , "Morales Frederic" , "CELLI Sylvain" , "BOISSONNADE-CORP Pierre" , "Richard BOREL" , "alain guiraud" , "raymond cayzac" , "georges pouget" , "noel sanchez" , "joseph pau" , "nicolas teisseire" , mmohammedi@ardeche.fr , "jerome gombault" , "alain nargeot" , "bhilaire" , "TEKATLIAN Annick" , "CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB" , "GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : "Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac." Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : " Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment)." Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien | - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 \ No newline at end of file diff --git a/output/ticket_T0150/rapport/ticket_analysis.json b/output/ticket_T0150/rapport/ticket_analysis.json deleted file mode 100644 index 27f5797..0000000 --- a/output/ticket_T0150/rapport/ticket_analysis.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "entries": [ - { - "timestamp": "2025-04-01 17:30:53", - "action": "extract_questions_reponses", - "agent": "AgentQuestionReponse", - "llm": { - "model": "mistral-medium" - }, - "parametres_llm": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "response": { - "success": true, - "messages_analyses": [ - { - "id": "ticket_info", - "date": "", - "role": "Client", - "type": "Question", - "contenu": "TICKET T0150: Problème d'impression des PV de compression des éprouvettes 11H22. DESCRIPTION: La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée." - }, - { - "id": "ticket_info", - "date": "", - "role": "Client", - "type": "Question", - "contenu": "TICKET T0150: Problème d'impression des PV de compression des éprouvettes 11H22. DESCRIPTION: La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée." - }, - { - "id": "11183", - "date": "2020-04-14 12:39:49", - "role": "Client", - "type": "Question", - "contenu": "Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour" - }, - { - "id": "11291", - "date": "2020-04-20 16:40:40", - "role": "Support", - "type": "Information", - "contenu": "Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avo" - }, - { - "id": "11296", - "date": "2020-04-21 08:29:06", - "role": "Client", - "type": "Question", - "contenu": "Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre de" - }, - { - "id": "11304", - "date": "2020-04-21 14:57:48", - "role": "Support", - "type": "Information", - "contenu": "Bonjour, Etes vous disponible demain dans la matinée ? Je reste" - }, - { - "id": "11305", - "date": "2020-04-21 15:03:22", - "role": "Client", - "type": "Question", - "contenu": "Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée" - }, - { - "id": "11309", - "date": "2020-04-22 08:22:21", - "role": "Support", - "type": "Information", - "contenu": "Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur" - }, - { - "id": "11320", - "date": "2020-04-23 09:46:11", - "role": "Client", - "type": "Question", - "contenu": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"You" - }, - { - "id": "11321", - "date": "2020-04-23 10:33:06", - "role": "Support", - "type": "Information", - "contenu": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste" - }, - { - "id": "11322", - "date": "2020-04-23 12:33:46", - "role": "Client", - "type": "Question", - "contenu": "Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en comp" - }, - { - "id": "11323", - "date": "2020-04-23 12:59:43", - "role": "Support", - "type": "Information", - "contenu": "-------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en" - }, - { - "id": "11462", - "date": "2020-05-06 11:36:50", - "role": "Support", - "type": "Information", - "contenu": "Appeler fait par Youness BENDEQ Pour savoir si la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée a été ajouté. Commentaire Possibilité ajoutée" - } - ], - "paires_qr": [ - { - "numero": "1", - "question": { - "role": "Client", - "contenu": "Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour" - }, - "reponse": { - "role": "Support", - "contenu": "Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - } - }, - { - "numero": "2", - "question": { - "role": "Client", - "contenu": "Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - "reponse": { - "role": "Support", - "contenu": "Bonjour, Etes vous disponible demain dans la matinée ? Je reste" - } - }, - { - "numero": "3", - "question": { - "role": "Client", - "contenu": "Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée ? Je reste" - }, - "reponse": { - "role": "Support", - "contenu": "Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique. Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa. Or avec la résistance brute, il obtient une non conformité. Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date. C'est faisable ?" - } - }, - { - "numero": "4", - "question": { - "role": "Client", - "contenu": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste" - }, - "reponse": { - "role": "Support", - "contenu": "Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste" - } - }, - { - "numero": "5", - "question": { - "role": "Client", - "contenu": "Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien" - }, - "reponse": { - "role": "Support", - "contenu": "-------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien" - } - } - ], - "nb_questions": 5, - "nb_reponses": 5, - "tableau_md": "# Analyse des Questions et Réponses\n\n| Question | Réponse |\n|---------|---------|\n| **Client**: Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour | **Support**: Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste |\n| **Client**: Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | **Support**: Bonjour, Etes vous disponible demain dans la matinée ? Je reste |\n| **Client**: Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée ? Je reste | **Support**: Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique. Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa. Or avec la résistance brute, il obtient une non conformité. Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date. C'est faisable ? |\n| **Client**: Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"Youness BENDEQ\" À: \"Yohan CAZARD\" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | **Support**: Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste |\n| **Client**: Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien | **Support**: -------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: \"PAYA Pierre\" À: \"CAZARD Yoan\" Cc: \"JAN Didier\" , \"ddumas\" , \"Gérald LACROIX\" , \"s labourasse\" , \"Stephane roques\" , \"claude trelcat\" , \"benoit gaumet\" , \"jm dao\" , \"a ferrer\" , \"pierre david\" , \"philippe delorme\" , \"Morales Frederic\" , \"CELLI Sylvain\" , \"BOISSONNADE-CORP Pierre\" , \"Richard BOREL\" , \"alain guiraud\" , \"raymond cayzac\" , \"georges pouget\" , \"noel sanchez\" , \"joseph pau\" , \"nicolas teisseire\" , mmohammedi@ardeche.fr , \"jerome gombault\" , \"alain nargeot\" , \"bhilaire\" , \"TEKATLIAN Annick\" , \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" , \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : \"Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac.\" Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : \" Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment).\" Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien |\n\n## Paramètres LLM utilisés\n\n- **Type de LLM**: Mistral\n- **Modèle**: mistral-medium\n- **Température**: 0.3\n- **Tokens max**: 2000\n\n**Paramètres modifiés durant l'analyse:**\n- **temperature**: 0.3\n- **max_tokens**: 2000", - "parametres_llm": { - "agent": "AgentQuestionReponse", - "llm_type": "Mistral", - "parametres": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n", - "temperature": 0.3, - "max_tokens": 2000 - } - } - } - } - ] -} \ No newline at end of file diff --git a/output/ticket_T0150/rapport/ticket_analysis.md b/output/ticket_T0150/rapport/ticket_analysis.md deleted file mode 100644 index e9b8572..0000000 --- a/output/ticket_T0150/rapport/ticket_analysis.md +++ /dev/null @@ -1,69 +0,0 @@ -# Analyse de ticket de support - -## Statistiques - -- Images analysées: 0 (0 pertinentes) -- Questions identifiées: 5 -- Réponses identifiées: 5 - - -## Paramètres LLM par agent - -### Agent de filtrage d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.2 -- **Tokens max**: 500 - -### Agent d'analyse d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.3 -- **Tokens max**: 1024 - -### Agent d'extraction questions-réponses - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - - -## Journal d'actions - -### 2025-04-01 17:30:53 - AgentQuestionReponse (mistral-medium) -**Action**: extract_questions_reponses -**Questions**: 5 -**Réponses**: 5 - - -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| -| **Client**: Notification d'appel Version imprimable Notification d'appel Nous avons reçu un appel pour | **Support**: Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | -| **Client**: Bonjour, Vous pouvez me rappeler? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "Youness BENDEQ" À: "Yohan CAZARD" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | **Support**: Bonjour, Etes vous disponible demain dans la matinée ? Je reste | -| **Client**: Oui pas de souci merci. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "Youness BENDEQ" À: "Yohan CAZARD" Envoyé: Mardi 21 Avril 2020 16:57:48 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Etes vous disponible demain dans la matinée ? Je reste | **Support**: Salut Laurent, > Si cela pose un problème, on peut mettre une option dans le logiciel pour imprimer le rapport soit avec la résistance brute, soit avec la résistance corrigée à toi de voir. Cela pose un gros problème cette histoire de résistance brute dans le rapport car M CAZARD obtient une non-conformité du coup. Pouvoir donner la possibilité d'imprimer le PV soit avec la résistance brute, soit avec la résistance corrigée semble être la meilleure solution. En effet, en ce moment il travail sur des ROANE (remblais auto-nivelant non essorable). Il s'agit de béton auto-plaçant et auto-nivelant pour les tranchées de la fibre optique. Cela permet d'intervenir plus facilement en cas de coupure du câble. C'est la raison pour laquelle les valeurs en MPa sont aussi faibles. Ils cherchent des valeurs comprises entre 2 et 3 Mpa. Or avec la résistance brute, il obtient une non conformité. Apparemment ils vont reprendre la travail début mai. Je lui ai dit qu'on allé voir ça pour cette date. C'est faisable ? | -| **Client**: Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. C'est un peu plus clair. On devrait pouvoir continuer à afficher les deux valeurs de résistances sur les PV et rapports d'essais. Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "Youness BENDEQ" À: "Yohan CAZARD" Envoyé: Lundi 20 Avril 2020 18:40:40 Objet: Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Voir Tâche Bonjour, Je vous contacte suite à votre demande concernant un problème d'impression des PV de compression des éprouvettes 11H22 (résistance brute affichée au lieu de la résistance corrigée). En fait on à eu une non-conformité qui nous a été remonté suite à un audit (qui n'est autre que Mr DIERKENS du CEREMA de Lyon, qui est cité sur la norme 12390-3 et la EN-206/CN) et jusqu'à présent aucun auditeur n'avait fait la remarque. C'est encore une des spécificités incompréhensibles Française. Nous avons 2 normes, la 12390-3 et la EN-206/CN. La norme EN-206/CN indique que pour des écrasements d'éprouvettes 11x22 il faut compenser en retirant 1 MPa. Cependant, lors d'un essai d'écrasement de béton, on doit se limiter strictement aux spécifications de la norme 12390-3 et fournir un PV avec résistance brute. Les corrections de résistance devant être utilisées uniquement pour des calculs statistiques liés à la marque NF BPE (ce qui est d'ailleurs fait dans notre logiciel). Donc c'est très ambigu, car jusqu'à présent on considérait que tous les bétons devaient respecter la norme EN 206/CN, et on disposait d'une case à cocher sur le PV permettant de ne pas appliquer la compensation qu'on aurais du normalement cocher à chaque écrasement... Mais c'est peut explicite, beaucoup d'autres personnes seront, je pense, dans le même cas que vous. Nous avons également posé la question à Mr DIERKENS si nous pouvions rajouter une colonne indiquant la résistance corrigée et la réponse est négative, car on doit se limiter strictement à ce qui est indiqué dans la norme. Je reste | **Support**: Bonjour, Ci-dessous les échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis en relation avec M.Dierkens. Je ne vois pas l'échange complet, pouvez-vous me le renvoyer svp ? Je reste | -| **Client**: Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "PAYA Pierre" À: "CAZARD Yoan" Cc: "JAN Didier" , "ddumas" , "Gérald LACROIX" , "s labourasse" , "Stephane roques" , "claude trelcat" , "benoit gaumet" , "jm dao" , "a ferrer" , "pierre david" , "philippe delorme" , "Morales Frederic" , "CELLI Sylvain" , "BOISSONNADE-CORP Pierre" , "Richard BOREL" , "alain guiraud" , "raymond cayzac" , "georges pouget" , "noel sanchez" , "joseph pau" , "nicolas teisseire" , mmohammedi@ardeche.fr , "jerome gombault" , "alain nargeot" , "bhilaire" , "TEKATLIAN Annick" , "CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB" , "GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : "Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac." Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : " Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment)." Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien | **Support**: -------- Message transféré -------- Sujet : Re: [T0150] Problème d'impression des PV de compression des éprouvettes 11H22 Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST) De : CAZARD Yoan Pour : support Oui, il faut prendre la valeur corrigée (selon EN 206/CN) pour évaluer la conformité du béton. Il faut bien distinguer : - la norme d'essai 12390-3 qui ne traite que de l'essai et qui n'a pas vocation à se prononcer sur la conformité du matériau : le résultat d'essai est bien la force appliquée (en N) divisée par la section de l'éprouvette, quelle que soit cette section, - la norme béton EN 206/CN, qui donne des indications pour se prononcer sur la conformité du béton, notamment la prise en compte de la taille de éprouvette (11x22) et des corrections à apporter pour se ramener à une éprouvette normalisée 15x30. Le mode de correction des valeurs brutes d'essai est indépendant de la norme d'essai et vous appartient. Dans le cas de carottes prélevées sur ouvrages existant par exemple, la correction ne se fera pas selon l'EN 206/CN mais selon d'autres dispositions. cdlt Pierre PAYA Responsable de l'activité Matériaux, Construction et Certification Laboratoire - service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30 Direction Territoriale Méditerranée Centre d’études et d’expertise sur les risques, l’environnement, la mobilité et l’aménagement Le 23/04/2020 à 10:36, > CAZARD Yoan (par Internet) a écrit : Bonjour et merci beaucoup Pierre pour ces précisions. C'est plus clair. Donc, on peut bien avoir, comme ce qui se faisait déjà, les deux valeurs affichées sur le rapport d'essais. Par contre, pour la vérification de résistances d'éprouvettes béton, pour des laboratoires départementaux comme nous, et notamment pour de petites valeurs (pour le RAANE par exemple), pouvons-nous continuer à prendre les résistances corrigées pour la conformité du matériau? Yoan CAZARD Responsable Laboratoire Départemental Routes et Ouvrages d'Art Conseil Départemental 66 Direction Infrastructures et Déplacements Développement et Expertise Technique 1265 avenue Julien Panchot 66000 Perpignan 04-68-68-36-90 06-73-87-52-43 De: "PAYA Pierre" À: "CAZARD Yoan" Cc: "JAN Didier" , "ddumas" , "Gérald LACROIX" , "s labourasse" , "Stephane roques" , "claude trelcat" , "benoit gaumet" , "jm dao" , "a ferrer" , "pierre david" , "philippe delorme" , "Morales Frederic" , "CELLI Sylvain" , "BOISSONNADE-CORP Pierre" , "Richard BOREL" , "alain guiraud" , "raymond cayzac" , "georges pouget" , "noel sanchez" , "joseph pau" , "nicolas teisseire" , mmohammedi@ardeche.fr , "jerome gombault" , "alain nargeot" , "bhilaire" , "TEKATLIAN Annick" , "CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB" , "GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB" Envoyé: Jeudi 23 Avril 2020 10:17:43 Objet: Re: Ecrasements béton bonjour à tous, Je viens d'avoir Michael Dierkens au téléphone et il m'a retransmis la réponse faite à BRG-Lab : "Si une seule valeur apparait, çà ne peut être que la valeur brute (non-corrigée). Une autre solution peut être aussi, s'il y a assez de place sur le rapport d'essai, de faire apparaitre 2 colonnes : 1 corrigée et 1 non-corrigée. Mais la valeur corrigée peut être vue comme une interprétation du résultat et poser des problèmes à un labo qui serait Cofrac." Sa réponse est cohérente (heureusement ...) avec celle que j'avais faite en décembre 2019 : " Je rajoute également que doivent figurer dans le PV d'essais : - la charge maximale à la rupture en N, - la résistance à la compression non corrigée en Mpa (c'est à dire sans prise en compte des corrections de l'EN 206 sur les 11x22 notamment)." Il faut retenir que : - la norme impose d'afficher dans le PV la charge maximale à rupture non corrigée (en N) ainsi que la résistance non corrigée (en MPa) : ces données doivent donc figurer impérativement dans le PV, - la norme n'interdit pas de rajouter des éléments dans le PV, en particulier la résistance corrigée pour des 11x22, si cette donnée vous parait utile (ou pour votre client) : dans ce cas le COFRAC peut considérer que l'affichage de cette valeur corrigée est une interprétation du résultat et demander à vérifier que l'interprétation des résultats a bien été définie clairement dans le contrat qui vous lie à votre client. Pour information nous faisons apparaitre les résistances brutes et corrigées sur nos PV (sous accréditation COFRAC). Je reste disponible pour toute précision. bien | - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 - -**Paramètres LLM utilisés:** -- **model**: mistral-medium -- **temperature**: 0.3 -- **max_tokens**: 2000 -- **top_p**: 1.0 - ---- diff --git a/output/ticket_T0150/ticket_info.json b/output/ticket_T0150/ticket_info.json deleted file mode 100644 index 336960c..0000000 --- a/output/ticket_T0150/ticket_info.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "id": 162, - "active": true, - "name": "Problème d'impression des PV de compression des éprouvettes 11H22", - "description": "

La résistance affichée sur le PV correspond à la résistance brute au lieu de la résistance corrigée.

", - "sequence": 17, - "stage_id": [ - 8, - "Clôturé" - ], - "kanban_state": "normal", - "create_date": "2020-04-14 12:41:38", - "write_date": "2024-10-03 13:10:50", - "date_start": "2020-04-14 12:41:38", - "date_end": false, - "date_assign": "2020-04-14 12:53:27", - "date_deadline": false, - "date_last_stage_update": "2020-05-06 11:37:10", - "project_id": [ - 3, - "Demandes" - ], - "notes": false, - "planned_hours": 0.0, - "user_id": [ - 9, - "Youness BENDEQ" - ], - "partner_id": [ - 9043, - "CONSEIL DEPARTEMENTAL DES PYRENEES-ORIENTALES (66), Yoan CAZARD" - ], - "company_id": [ - 1, - "CBAO S.A.R.L." - ], - "color": 0, - "displayed_image_id": false, - "parent_id": false, - "child_ids": [], - "email_from": "yoan.cazard@cd66.fr", - "email_cc": "", - "working_hours_open": 0.0, - "working_hours_close": 0.0, - "working_days_open": 0.0, - "working_days_close": 0.0, - "website_message_ids": [ - 11323, - 11322, - 11321, - 11320, - 11309, - 11305, - 11304, - 11296, - 11291, - 11183 - ], - "remaining_hours": -0.25, - "effective_hours": 0.25, - "total_hours_spent": 0.25, - "progress": 0.0, - "subtask_effective_hours": 0.0, - "timesheet_ids": [ - 50 - ], - "priority": "0", - "code": "T0150", - "milestone_id": false, - "sale_line_id": false, - "sale_order_id": false, - "billable_type": "no", - "activity_ids": [], - "message_follower_ids": [ - 10906, - 10962 - ], - "message_ids": [ - 11463, - 11462, - 11323, - 11322, - 11321, - 11320, - 11310, - 11309, - 11305, - 11304, - 11296, - 11291, - 11279, - 11244, - 11190, - 11189, - 11188, - 11185, - 11184, - 11183, - 11182 - ], - "message_main_attachment_id": false, - "failed_message_ids": [], - "rating_ids": [], - "rating_last_value": 0.0, - "access_token": "fc567ae1-ede0-4cd0-b08b-4e3310759d4d", - "create_uid": [ - 1, - "OdooBot" - ], - "write_uid": [ - 1, - "OdooBot" - ], - "x_CBAO_windows_maj_ID": false, - "x_CBAO_version_signalement": false, - "x_CBAO_version_correction": false, - "x_CBAO_DateCorrection": false, - "x_CBAO_Scoring_Facilite": 0, - "x_CBAO_Scoring_Importance": 0, - "x_CBAO_Scoring_Urgence": 0, - "x_CBAO_Scoring_Incidence": 0, - "x_CBAO_Scoring_Resultat": 0, - "x_CBAO_InformationsSup": false, - "kanban_state_label": "En cours", - "subtask_planned_hours": 0.0, - "manager_id": [ - 22, - "Fabien LAFAY" - ], - "user_email": "youness@cbao.fr", - "attachment_ids": [], - "legend_blocked": "Bloqué", - "legend_done": "Prêt pour la prochaine étape", - "legend_normal": "En cours", - "subtask_project_id": [ - 3, - "Demandes" - ], - "subtask_count": 0, - "analytic_account_active": true, - "allow_timesheets": true, - "use_milestones": false, - "show_time_control": "start", - "is_project_map_empty": true, - "activity_state": false, - "activity_user_id": false, - "activity_type_id": false, - "activity_date_deadline": false, - "activity_summary": false, - "message_is_follower": false, - "message_unread": false, - "message_unread_counter": 0, - "message_needaction": false, - "message_needaction_counter": 0, - "message_has_error": false, - "message_has_error_counter": 0, - "message_attachment_count": 0, - "rating_last_feedback": false, - "rating_count": 0, - "access_url": "/my/task/162", - "access_warning": "", - "display_name": "[T0150] Problème d'impression des PV de compression des éprouvettes 11H22", - "__last_update": "2024-10-03 13:10:50" -} \ No newline at end of file diff --git a/output/ticket_T0167/attachments/32380_image001.png b/output/ticket_T0167/attachments/32380_image001.png deleted file mode 100644 index 46fee79016d2a818502904700dac67f08057a031..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25085 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 diff --git a/output/ticket_T0167/attachments/32382_Problème partie.png b/output/ticket_T0167/attachments/32382_Problème partie.png deleted file mode 100644 index b1e19c3cad6edab291a15580fbade28dc570b872..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 255246 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

LpQ^KwmHX@8UT~l0jS?sF4e><& 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 @?pi=)I-njGE@^M54*O{$o5o$;Zoa#_t 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

Z(O^4}M6?z9S8_5zkmE(O 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 a`2PWGPM==N`<+Gr0000Je viens vers toi car Mr NOVO m’a fait remonter un léger beug sur le numéro d’échantillon B2020-0001 (Voir PJ).

En effet, il n’arrive pas à mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussée côté giberville » comme stipulé dans le numéro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE.

J’ai essayé de modifié la partie mais je n’y arrive pas.

", - "date_create": "2020-04-27 06:21:36", - "role": "system", - "type": "contexte", - "body": "TICKET T0167: Pb d'affaire/chantier/partie dans un programme d'essai.\n\nDESCRIPTION:

Je viens vers toi car Mr NOVO m’a fait remonter un léger beug sur le numéro d’échantillon B2020-0001 (Voir PJ).

En effet, il n’arrive pas à mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussée côté giberville » comme stipulé dans le numéro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE.

J’ai essayé de modifié la partie mais je n’y arrive pas.

" - }, - { - "id": "11333", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "Réponse", - "date": "2020-04-27 06:20:22", - "email_from": "Youness BENDEQ ", - "subject": "Pb d'affaire/chantier/partie dans un programme d'essai", - "body": "-------- Message transféré -------- Sujet : De retour ! Date : Mon, 20 Apr 2020 14:52:05 +0000 De : LENEVEU Guillaume Pour : Youness BENDEQ Bonjour Youness, J’espère que tu vas bien ainsi que toute l’équipe BRG-LAB. Je viens vers toi car Mr NOVO m’a fait remonter un léger beug sur le numéro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas à mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussée côté giberville » comme stipulé dans le numéro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE. J’ai essayé de modifié la partie mais je n’y arrive pas. Merci de ta réponse. Bonne fin de journée." - } -] \ No newline at end of file diff --git a/output/ticket_T0167/messages.json.backup b/output/ticket_T0167/messages.json.backup deleted file mode 100644 index c9295dc..0000000 --- a/output/ticket_T0167/messages.json.backup +++ /dev/null @@ -1,125 +0,0 @@ -[ - { - "id": 11346, - "body": "", - "date": "2020-04-27 07:24:40", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11332, - "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai" - ] - }, - { - "id": 11345, - "body": "", - "date": "2020-04-27 07:20:20", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11332, - "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai" - ] - }, - { - "id": 11344, - "body": "", - "date": "2020-04-27 07:19:57", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11332, - "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai" - ] - }, - { - "id": 11343, - "body": "", - "date": "2020-04-27 07:19:29", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": [ - 11332, - "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai" - ] - }, - { - "id": 11342, - "body": "", - "date": "2020-04-27 07:15:48", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "\"Youness BENDEQ\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11335, - "body": "", - "date": "2020-04-27 06:21:37", - "author_id": [ - 2, - "OdooBot" - ], - "email_from": "\"OdooBot\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11334, - "body": "", - "date": "2020-04-27 06:21:37", - "author_id": [ - 2, - "OdooBot" - ], - "email_from": "\"OdooBot\" ", - "subject": false, - "parent_id": false - }, - { - "id": 11333, - "body": "
\r\n", - "date": "2020-04-27 06:20:22", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "email_from": "Youness BENDEQ ", - "subject": "Pb d'affaire/chantier/partie dans un programme d'essai", - "parent_id": [ - 11332, - "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai" - ] - }, - { - "id": 11332, - "body": "", - "date": "2020-04-27 06:21:37", - "author_id": [ - 2, - "OdooBot" - ], - "email_from": "\"OdooBot\" ", - "subject": false, - "parent_id": false - } -] \ No newline at end of file diff --git a/output/ticket_T0167/questions_reponses.md b/output/ticket_T0167/questions_reponses.md deleted file mode 100644 index 1774812..0000000 --- a/output/ticket_T0167/questions_reponses.md +++ /dev/null @@ -1,15 +0,0 @@ -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 \ No newline at end of file diff --git a/output/ticket_T0167/rapport/ticket_analysis.json b/output/ticket_T0167/rapport/ticket_analysis.json deleted file mode 100644 index 66ddc3d..0000000 --- a/output/ticket_T0167/rapport/ticket_analysis.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "entries": [ - { - "timestamp": "2025-04-01 17:34:01", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T0167/attachments/32382_Problème partie.png", - "response": { - "pertinente": false, - "type_image": "autre", - "description": "Cette image semble être un logo, une signature ou un élément graphique décoratif, et n'est pas pertinente dans un contexte technique.", - "confiance": 90, - "justification": "L'image ne contient pas d'éléments techniques utiles pour résoudre un problème.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:34:01", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T0167/attachments/32380_image001.png", - "response": { - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalités techniques liées au problème décrit dans le ticket.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:34:01", - "action": "analyze_image", - "agent": "AgentAnalyseImage", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.3, - "max_tokens": 1024, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques.\nVotre rôle est d'examiner des captures d'écran ou des photos liées à des problèmes techniques et de:\n1. Décrire précisément le contenu de l'image\n2. Identifier les éléments techniques visibles (erreurs, interfaces, configurations)\n3. Extraire tout texte visible (messages d'erreur, logs, indicateurs)\n\nSoyez précis et factuel dans votre analyse.\n" - }, - "image_path": "output/ticket_T0167/attachments/32380_image001.png", - "response": "{\n \"pertinente\": true,\n \"type_image\": \"capture_ecran\",\n \"description\": \"Capture d'\\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.\",\n \"confiance\": 85,\n \"justification\": \"L'image montre clairement une interface utilisateur avec des fonctionnalit\\u00e9s techniques li\\u00e9es au probl\\u00e8me d\\u00e9crit dans le ticket.\"\n}", - "tokens": { - "prompt_tokens": 208, - "completion_tokens": 150, - "total_tokens": 358 - } - }, - { - "timestamp": "2025-04-01 17:34:01", - "action": "extract_questions_reponses", - "agent": "AgentQuestionReponse", - "llm": { - "model": "mistral-medium" - }, - "parametres_llm": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "response": { - "success": true, - "messages_analyses": [ - { - "id": 11333, - "date": "2020-04-27 06:20:22", - "role": "Support", - "type": "Information", - "contenu": "-------- Message transféré -------- Sujet : De retour ! Date : Mon, 20 Apr 2020 14:52:05 +0000 De : LENEVEU Guillaume Pour : Youness BENDEQ Bonjour Youness, J’espère que tu vas bien ainsi que toute l’équipe BRG-LAB. Je viens vers toi car Mr NOVO m’a fait remonter un léger beug sur le numéro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas à mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrai" - } - ], - "paires_qr": [], - "nb_questions": 0, - "nb_reponses": 0, - "tableau_md": "# Analyse des Questions et Réponses\n\n| Question | Réponse |\n|---------|---------|\n\n## Paramètres LLM utilisés\n\n- **Type de LLM**: Mistral\n- **Modèle**: mistral-medium\n- **Température**: 0.3\n- **Tokens max**: 2000\n\n**Paramètres modifiés durant l'analyse:**\n- **temperature**: 0.3\n- **max_tokens**: 2000", - "parametres_llm": { - "agent": "AgentQuestionReponse", - "llm_type": "Mistral", - "parametres": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n", - "temperature": 0.3, - "max_tokens": 2000 - } - } - } - } - ] -} \ No newline at end of file diff --git a/output/ticket_T0167/rapport/ticket_analysis.md b/output/ticket_T0167/rapport/ticket_analysis.md deleted file mode 100644 index 5c744ce..0000000 --- a/output/ticket_T0167/rapport/ticket_analysis.md +++ /dev/null @@ -1,116 +0,0 @@ -# Analyse de ticket de support - -## Statistiques - -- Images analysées: 2 (1 pertinentes) -- Questions identifiées: 0 -- Réponses identifiées: 0 - - -## Paramètres LLM par agent - -### Agent de filtrage d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.2 -- **Tokens max**: 500 - -### Agent d'analyse d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.3 -- **Tokens max**: 1024 - -### Agent d'extraction questions-réponses - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - - -## Journal d'actions - -### 2025-04-01 17:34:01 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 32382_Problème partie.png -**Résultat**: Non pertinente -**Type**: autre -**Description**: Cette image semble être un logo, une signature ou un élément graphique décoratif, et n'est pas pertinente dans un contexte technique. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:34:01 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 32380_image001.png -**Résultat**: Pertinente -**Type**: capture_ecran -**Description**: Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:34:01 - AgentAnalyseImage (pixtral-12b-2409) -**Action**: analyze_image -**Image analysée**: 32380_image001.png - -**Analyse**: -``` -{ - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalit\u00e9s techniques li\u00e9es au probl\u00e8me d\u00e9crit dans le ticket." -} -``` - -**Paramètres LLM utilisés:** -- **model**: pixtral-12b-2409 -- **temperature**: 0.3 -- **max_tokens**: 1024 -- **top_p**: 1.0 - -**Tokens utilisés**: -- Prompt: 208 -- Completion: 150 -- Total: 358 - ---- - -### 2025-04-01 17:34:01 - AgentQuestionReponse (mistral-medium) -**Action**: extract_questions_reponses -**Questions**: 0 -**Réponses**: 0 - - -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 - -**Paramètres LLM utilisés:** -- **model**: mistral-medium -- **temperature**: 0.3 -- **max_tokens**: 2000 -- **top_p**: 1.0 - ---- diff --git a/output/ticket_T0167/ticket_info.json b/output/ticket_T0167/ticket_info.json deleted file mode 100644 index b41a537..0000000 --- a/output/ticket_T0167/ticket_info.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "id": 179, - "active": true, - "name": "Pb d'affaire/chantier/partie dans un programme d'essai", - "description": "

Je viens vers toi car Mr NOVO m’a fait remonter un léger beug sur le numéro d’échantillon B2020-0001 (Voir PJ).

En effet, il n’arrive pas à mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussée côté giberville » comme stipulé dans le numéro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE.

J’ai essayé de modifié la partie mais je n’y arrive pas.

", - "sequence": 22, - "stage_id": [ - 8, - "Clôturé" - ], - "kanban_state": "normal", - "create_date": "2020-04-27 06:21:36", - "write_date": "2024-10-03 13:10:50", - "date_start": "2020-04-20 14:52:00", - "date_end": false, - "date_assign": "2020-04-27 07:15:48", - "date_deadline": false, - "date_last_stage_update": "2020-04-27 07:24:40", - "project_id": [ - 3, - "Demandes" - ], - "notes": false, - "planned_hours": 0.0, - "user_id": [ - 9, - "Youness BENDEQ" - ], - "partner_id": [ - 8504, - "CONSEIL DEPARTEMENTAL DU CALVADOS (14), Guillaume LENEVEU" - ], - "company_id": [ - 1, - "CBAO S.A.R.L." - ], - "color": 0, - "displayed_image_id": false, - "parent_id": false, - "child_ids": [], - "email_from": "guillaume.leneveu@calvados.fr", - "email_cc": "", - "working_hours_open": 0.0, - "working_hours_close": 0.0, - "working_days_open": 0.0, - "working_days_close": 0.0, - "website_message_ids": [ - 11333 - ], - "remaining_hours": -0.5, - "effective_hours": 0.5, - "total_hours_spent": 0.5, - "progress": 0.0, - "subtask_effective_hours": 0.0, - "timesheet_ids": [ - 51 - ], - "priority": "0", - "code": "T0167", - "milestone_id": false, - "sale_line_id": false, - "sale_order_id": false, - "billable_type": "no", - "activity_ids": [], - "message_follower_ids": [ - 10972 - ], - "message_ids": [ - 11346, - 11345, - 11344, - 11343, - 11342, - 11335, - 11334, - 11333, - 11332 - ], - "message_main_attachment_id": [ - 32380, - "image001.png" - ], - "failed_message_ids": [], - "rating_ids": [], - "rating_last_value": 0.0, - "access_token": "cd4fbf5c-27d3-48ed-8c9b-c07f20c3e2d4", - "create_uid": [ - 1, - "OdooBot" - ], - "write_uid": [ - 1, - "OdooBot" - ], - "x_CBAO_windows_maj_ID": false, - "x_CBAO_version_signalement": false, - "x_CBAO_version_correction": false, - "x_CBAO_DateCorrection": false, - "x_CBAO_Scoring_Facilite": 0, - "x_CBAO_Scoring_Importance": 0, - "x_CBAO_Scoring_Urgence": 0, - "x_CBAO_Scoring_Incidence": 0, - "x_CBAO_Scoring_Resultat": 0, - "x_CBAO_InformationsSup": false, - "kanban_state_label": "En cours", - "subtask_planned_hours": 0.0, - "manager_id": [ - 22, - "Fabien LAFAY" - ], - "user_email": "youness@cbao.fr", - "attachment_ids": [], - "legend_blocked": "Bloqué", - "legend_done": "Prêt pour la prochaine étape", - "legend_normal": "En cours", - "subtask_project_id": [ - 3, - "Demandes" - ], - "subtask_count": 0, - "analytic_account_active": true, - "allow_timesheets": true, - "use_milestones": false, - "show_time_control": "start", - "is_project_map_empty": true, - "activity_state": false, - "activity_user_id": false, - "activity_type_id": false, - "activity_date_deadline": false, - "activity_summary": false, - "message_is_follower": false, - "message_unread": false, - "message_unread_counter": 0, - "message_needaction": false, - "message_needaction_counter": 0, - "message_has_error": false, - "message_has_error_counter": 0, - "message_attachment_count": 2, - "rating_last_feedback": false, - "rating_count": 0, - "access_url": "/my/task/179", - "access_warning": "", - "display_name": "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai", - "__last_update": "2024-10-03 13:10:50" -} \ No newline at end of file diff --git a/output/ticket_T11067/attachments/144792_image003.png b/output/ticket_T11067/attachments/144792_image003.png deleted file mode 100644 index 121eaf87b825740fe5c0bc1488eb92efe74bca69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5417 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 Tq=>^300000NkvXXu0mjfcXxH7 diff --git a/output/ticket_T11067/attachments/144794_image004.jpg b/output/ticket_T11067/attachments/144794_image004.jpg deleted file mode 100644 index 5c3401dd8163530d10573858f1b2d50a548fd1a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63295 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 CMUbEX diff --git a/output/ticket_T11067/attachments/144796_image.png b/output/ticket_T11067/attachments/144796_image.png deleted file mode 100644 index db688c6b338df272efcb51837bda35b39d8d3d53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45686 zcmb@tcT`hr_ce+~kBSY&f`WhwDvB6OkQ%UtE`lhX97KdrLT`Zt3yO##6af(d=^d2b z5|kDNX`zIcL&&h5aJImjVl;MW!}W38J)MIFayfH&J5ZW!DU68eJOy=nU= z@Lt$m+uTb?XkVk?XA8kC=dqAb$!?w7H%$C(=DB`}hqRI__G(Ixb62>h7;_y9C@N>} zCq?aU>D6U_2971Q1(OZ`s{kwmdUj!1beXc{58?fkz}&PZnsj9g(f21-n${HME4 z`mHb80+andS{%%EHcAxAyJZf~Xc^4wE4(BB$8}P7pf01(zvdgK=-O!AmQ@WTmOSi- zAFe3$PwuLVRluxhY%UR`$@RR+bJT}hg@m3yTASB=4c65Lp5j(L7Ay3LGmfiVp1i?` z_CqXBZn@5^qEl2(XBtuJklWzfgoGkRh;jtX;BFOkUuNWl}p**eRqpgXi z*b~5>2`%3c&-@dI^h*I6HjOC-w#n#wt#%W!JyosM#VkeJ&CTpYeg0dGs71`E}i_ z%(IW-2aZ=wAf~@(BHH?0U)qBWsgo7uu1r3^aqCJDZV%U$4uXB@hA6wIrWC=hSbTQ0 z4)tvC;ZO0Z5o5ivXv;hTiaS~R<)HNWy!1jP*C%?RGlhkgn-xzwEouCR-0k};M^X{5 z*5oOssqC3}o3fuTwjN=#ht*vTC)}LK#_zMPlLM9I4b=>5o%coroo@eiLVZ zn&$&)ZtxP3iC6C?T@;hz7;_MshEj~$Sutsb`v+c% z&s)V}c|wNLJ?=DH57cou zAotR#iu$#^Nzw=ENjK-1GOLtsXDddg?(D-ND@#LWA9Cxfi@wez*Na1}g-C$~K6tT? zILxq{NPLR4)?liAdlGqyhzvictrP^?<0ng$4>IfP@Ww z=<*Xa-!!~eQ;X-$AK8~8vow{~<=l%rK4Bdi66}VtnT4g_g zVH)>jK{w&OB^zFTyaq)UHoJbM?d2a@SALZi->tr-b+HDY4l_8j;}LvyM84Ul=$gn| z|7NcH^mESga1ZaO+XhF8_x^$z)2LF`I9)frVwm7y+opxC=dG&4V|&3r!Zq1Y59Ovn+xC>$sGamx zpR;(BB6CJ(r61%cX$;wpH6xDVPM>>R(iTy#^Kntteprr4>At+6wBB*Kf_1(ATlh$p zfuBaFd@NLTpU6J5Uz#b*N{!;vH@%aYey54w-9XR2{t&n`U0fwFzye8!+J^*!IekWX z#%#d(dT^pLaig0pagCxv*!rqG#ZFCW^h(kUTz1fNvsZHPV5f+1rcqF%v|hSD`A`#a zdN3X>muKn}3EgNS$|Z{kby=Rk5Q+BijKrr@GK4_Z{Od+{-BEHAcVS@=F*-Kp=0%eb zR=m`A{h^HI-g5@KCAa}fU?=}@_YdNg9(L+hB=PbOS@W~ouO8YnyCoGqgbqqilgQ4! zYPuouw6Ag^G^)JN9p-a21Ii!S@IxR9G{jB%c%Us~_O0`@^eg(}Guz#|7EeneUU{dB zQmh^ype%Yn6gPJ}PnW!>D_%~rzcu;_@{#ef>3im#Q(99UYY=+NXHj@>pB+)+9TG5& z{C>_|>T7yX!R~Fj+b}j$HKU|^kpzr|Cam{nx|71gs# z0b#IPuP9fM3I-{-np-0Eo<8yqiV!1ZKO0W_t(htn-OnnX?Rt?{`%YCUU?tCoQbKWf zl{NEm=A&caHEY8CDT9^erf`Ec_S_r#r++EWO7thkkqBYSIZd^~&N#Ucy+hV{si`~MEBxTfiqnrMLnG`h(&3Dix zuza>LJcITLWZ+_+x{|*#QekgN){((gEYxIkQSTKsA2+>UV~sw)GstMXC*IsMr??-{ zXtPxnp(>UN7VUBHQGYmkr7s%FUkY^~cPQkkE@ZH4B;Dn}?;3Y$Niv zPVL6UB1Wnvnh85nk{27k%`Sb92_#pqkT$Qx7mqAHpVDMd7BbrsyiCdQ)a3InQ~7R& z94Uwg3aTH_Hb3asPp+95>C0Clf0G7P9W)~2npB1_daOE*e22SLr=Pu8I}hUjf_C~3 z^Z6@)Kl7R@=BTEq`!p+@*9@gsL*~tJ%FFX&KtmZSgm1fp^nTv-L%%QHc=_Krj#2ci4CJx(&EW@ z>5f`?Qv|!_xTeRTg4y6j$F&7bI=T+kq0dtFlTcyKT;(f8SE?~15zJbA!ebB{VoFqSfP{?FUhLJ_h1x)V=ehO!j zy%8Mbj!u0hWoNz0sPRLDCT@|zN8L-;!8j;}^f_PeX@CajN{H9mev#OHOG%RZ>cVW- z(Mlg$GSq2$mOo0{D=N*l^bvM5X^?PKETAR6_qRkR{RK0CHY?q$Nxd{aYu<+*+O13%Y+CPnbJ?(V~RHcZMABzB{%eTK}qH2FZATv@1}zr>#$+*eYxf z)BQfGm3+uI)_CfSn@xF#WiBh?bEi(&+&x+CfoUsU)3 zezU6&G_$&La^0$NoK7Ddah*fCZ_n+fFvn==o#BL=Y$WR#jBgu5ahF#@E!+v81)Y0L zl%p?!he`1^Zd6hwMRV+KGJf_<`*5Fa(AmQ5iRA7tk}ia`S5&tjUEAj4z|qmylytJP4(We($OP*P}bKdOcZ z(nNo_&TrsuC8xG@-oBkY@dU*A8vh^+?8M=aY<99qKYqoJ>@Jq{cIdG2SusVAS7?kF ziN1tj0kFuA0p0aKS+Ud!+n{YWZN#`I;MA z;>lr4kd)o-Bt2rX(sv2=C6D{%xDUT_3A}pr0T7GeqqOZyRp-o=Y+_%>xWfv+ z6?&G7ATOL4kyZe0WJt&=hWIpA&!wup(1|})H=27}{3XGH7Bld)Z&c&SykRc4-QpSr z5ma|a*?=!XKfLc1B^HQ0zf+nAG*r9~<(4k_kh6sx#`~w@!*EDz7ISPR?m^tz4f-@L zopo=$>QQygM65HNUPs^Le5-AH*JHliVL+*K`luwy^1lREd#EZV+JOw79dI&tz2D>g zv9Xh|&Q0G!JMHMblE@siA8<(9%ahi?o6Mq;Y8FNV>qnT4v&OUKGGoqRJPchT_~I^w zsXKZJ^m|pVT-UAVoi$f?ew>xq7b0nsT^3O<_0FFWGI0zE%CQ<|R8ekDHE)C7A!-}v z--I7>(@RsiP@Mlx^wz}W%sQFM=-_m<^c_S}$tVutn74+mPNp%zJdG5Qh~XS6N}oA{ zX?XVe0XFxl<)+w~iaN~>Yan1UtJY&qX*i2!mtHtO?@mPX`XAdX?!v5)pm~CKrW_I82WcX!wSS_^;(w@211rCrrjM@ljs_!;V*8Ch}@~EDW z&~_mIB}YSF;jPy&DS=b#9?HG$#xmcPpqz`}B}1;^yLUD}l?@Y5X_Fed$4rLK@2yp% zo(W}k8ANvd%C33VU2ltXQ9mWI?P2uI;V$J%732cstKn&VLm2~7JGS5Yi>KWV_~YqU zH|b8B=~Z9E55^_>ypX!PJD!Od_+>foE=^mJbFna71Miyod3k2I1bF5v0YCa-kcUQf#D=NC_VpI3s^y>q%F zK%PlCu!ipC^gOO??Vk$EY92eSVd$Z<D_8p{iwhT%7u|s&jAeHX-(31}t zPv+r=(pGF4w=k9&q(pS{PfBQ^O8w#!g39rp?~A934?-}TDpFsX6kgl70a!K`nu!#D zIi?lt_dvXPBE;VGJf0mx>QaG1STdlj*|x;8(qBNHp8r_3$9 z{87IpWLQ!7plqpR+*Zt9d_IF`PeVDNJ-Sm^*rDmB#(3xk1|d z=0{@HzM9lh+WrN*AgSTD1@`p;aVv9dLdc3wdge12m#;UX{1B<{^sJ8ckWv>}glDWG zyEeXyyI4%g#i`!JVh2^;c2;tS-r4jl1^iIusdg@Lv>505@~z0av5AV)K31Jhzw_;v z-psm*dBb&d?^JTfOR0IH!&?e9_Dy_2=fzvkPieTZ?RDr(W2X}?kVnG@eL#NP&l6*$ zyKnK}*TtuS*c|02NpwgZ4-uA4Eap4t$h4Qz-~DJZW+e4F5ADb)jsustPV5bFC1LN0 z4>HpW=R26`AHUA*`khF>E-E)?G-cek zdjhccZhy>a%vdrs75t_W4#9X!tHIP3F2i6lbO@VNw{U>ntAH+a!T2Bv4z)Hi#+cRIg$&N|sp4#Sxs@utkk~xnKGohU9sM!N4@#~5iK1>_o z;PX}j?@`?LJ5|ED`K0HwXPE`0avPCZg`@qsYU4?Xbpe;HRou)8`EpM)drPJR@Y3(k)zZB^3eSRfvqwgJ*U59eN&M`A(TTVTg zYC$4q+1pQsq zE-#XYD^V`n$lwA08>i?kw?&~!-yRkr^ren=;p=BD7zFo0;ulNY>^09hPyWuguj9M@ z#e9E)_q|0r53C>akZh13tV2P^i*Nf_RRN`t^W_Xxt%?Z5TH&{%;PSonZu=J!!!>y^ zg$`yAd6oaM*&|6Ps<7liNeSE;@16{n*@&LQ`g{9?;>3cLTnTC6=5?+FkflgDj(Xa5 z0%?8Qc@oKX7rlvm+`j#a2$jTkDRq5Vy5MnaP4)Xw@#5d5p35~$B!`+-68#?I z&-|2rEPeml_SV{c!hLsA{MO7Kt*c@(qdwE$6@k#3pG6r-<#Z)6PDX+0Fvg43vXbW)xY$K~sy}!);u4?oGxgcdFDwatB#OMD@tS zN|iPZ_Z`7?zp%xV^Mk=tU#{-`&ZTwhp_A8ijN3D!I))Fbtpy&)QJwbJ+dgad_TyTX z+B)q{@E)I_I@vu)sq!-PLR&YIR773IrJ^-|H8xg?a5w(u6}+M1H@MMEe{mrp69LTAmdQER8-8wXZ`brcnT##q zKW6WkV3Kc=PaEz5%1~O7(Dp6FokE}JKt1g__>bw+zfsvIzaMHq5lQG1ay%@xE`Yg{ zn4@xCe2b8`Bv2cOgbLwq3w*KE>cs#cftC_7!Kz<=r&KI;1Gq(K`~_HdH*x2u_}?|q z7nIWi%ia2PHcDV0eKJ5S5_%d0fR!NvdUF40`5pu-i9_V3`cJt}UNbry-fF zhnug!{?xuRAC;a`v>0Ei?J1$GYh9ehuGCu|J#Piyc>@?2z-)~j2B;vRPY$254*)z^ zwDjMz1}-V?`aQNEe=|wIg{R_w{wB%Bcfj8r0i2bP&~?n;M44a=z&Z$?1HB=B0C@Pu z-`o;#fYPrTPXRT~Fg|(p`={R#~L|Npk3w zM=Umx$fN1;R&~=qdQ3-N=K@fY$KZBWV}jYOZK*KL_o#hYAatj-+{xUU4`gbRhaWTe z8zzw%p=p>oc4tH_lnh!JT=+98;+7eokGJOMliXVJMQ>{N3G6gJqkDBwVWB86T;iHw z?)Mg=KEA<)`!>G*-9S~-fHCxen zwd00QrhX=Idal~JD3j?`=|aw4_`amaQ%-Kp39iEe$K{k@e|5!k{i2XZ%x`7!Bkv%V zS05k%k`8TSr7W1DcM>H?9dMCSbYsI*Wzj#8VCUwR&XJ4&Mos9opjkAD@h1q=n?IRJ z52(CVyMB7ycsK9EvS0o zKIn^cJHLvNEg6y?K*eivvT(gi5~rZCIvroJ(!0VT9>INewUSIMpC`=COtCn$ z&CzTEInN-4<66$;O7P!*YP|}Vt*(5O-ak0;upGUx#&s|H9IS+(cuJ$t4Jj;mIK>MK z;Uop49{2Gl4Kfa#ltlslE!RxEklHoLTl}gH3SXete^s!=r{-J|>`RVR`FV`&ehO#$ zJ%=%jE#@v$ByD!i@I~H6f@`LEo6`tttpm9N6rK?k(w@TGC`jE1sW`&9ZibyoZ~lAlmf(!G5BiY}RuNGBi` z#J$OkYEg*3Bo48y9!vz|pn_j&`hg&vYdUw)or@$m4NAj)G$5s~{dzN3$50 z-7N{1{qZST9mpAxCVDUAoOu9alQ<cL3>y z-onC35QhnZRnJ`GPRQ54-F}Hb*S3c0{}Llq<3IDtvU=$%=>4kMh!Qo)*H0wi$KIo? z4-Ajfm%(;RfxP$H+bFXgE9j8@#AX1c7)ODLN1>unkv(RwFZ}^5>hwvc8-TxDmE`70 zDD!-<$o?QU^PG~)aw5+IjIowA-5&w(JqBN$F6CJ1(H$1}n>ME=K1s`KPvACNPS(#) zNN9L;)~&yQ`O;GAmp!47lvT4hWOEQM8^w8pq^j4iJcao(Cw&uoJoJH8l#!rn(Gw0K zd3{?E96il-%56&?4^!NeP-;q^KIT>(yupmI8JaeOTzZtv*>FqoZ%yhx zPy)<2)s82B_?5Q5=Y00jS`)}(0 z37B9BQQPkD;3ra>smq1)0`n6hb|n(!7)xNx@YTm-5_m!@EA-+z><@Yg7&)m{nKL0n zwVaq2i8!*YOHKN?2Y-Vwk68ME9q9oD!M=cp(3Y26QB~HHtM9-iHX2BC*pQwFP3#&cDkG>_&A)w*p_LT1*}x+JO_&=v zTK)oXUF!wGkLQ>B){=Eq@%_$W`)?v;fUx*37P{sPzwc0SsBn*9ax>Eg@W+ERT_`_C2-nIO;g&kZ z$*460&X*@`Q#OCS+-j@0Ggjh{?^1?6>3=m({rV`tQ^59Olrkvy8nf$W&;blz7QoKp z_D5e}S5h@-{C*91%4zzlv%k2r(|B3srVN~2UV955gm`u^=GaUpe`Fqr>p9YIH+iFK z0Dn7jz#cgBF#u}LEC3ThnL6T2&Tzr1LG%=~)7On;FZ)iaEquj_1z`_|rMcT&z$7CP z^|e70HDVIt9OzbKP2L>7p*S1P1G3mne>LQu*4C(?fbm@1!fd&OjhS{tj+U_sJVQ!( z)>St3V847E)MBdKZy(1-XNl(%39SqyPcIeS6VJ_#o^|j16<_z&C_vO`2oxqRPbZ<0 z{oLyPdRgB$M!N$1sGs9;RVp6Ktx3A^+PTj@HxDGZRiE{nTfu(!QNE}`)b=p}<=p7D z^WJTW8t?d6JLwxt;?d!%53j+d^l7(d#Ky{aN`ZGdOIQ~?udlcdu7CFC&Kb<#Nf|KX z93uhg1Vr!}e5^pDVu%D_(lA}id4^uZn(v$J5_TWbhn)sa>TV0?}bJ|k`F`e;U^p+AF`0B zT2?`E&!}DeCNCH_tYwKE+^@u`4j8Ma ztWGLEMy}^mH>t>hq^4i(bz&)ltLnK~A{}#1{h|enAR~rCbtco5rHJKpz-*oc2L@G& z>6#W*VBInZQ?f5*w~0trPqS`dPtB@_cH{G`AX3>IzR5dJW+*-Xoe0X>%8nfda#Nub z3b=C^?G5dl@SiD~`;fVfzewhTwfq8Uj@H)a(m=tKKX&|NNaVu5vbj8Njzb5k(XYl_ zPjeCLZa>l5mxut!l?Chzm}d&g94+JmWOuRu{tWiG3i^j;oS0^deYdh+;93$B8-DUF zFr=D)Wr2XcGIH}@+bqcY(0}L0z<_(@ek(F%H38?*`xfj3hkG=>+Uq5ugt+j5l$fJI zCl!M}*qpNnCT8d$Rwmo;tTa`)4v+Na-Y2)l%7;(J-n5@Jn|a^7VtmQAVVjcIg%(d~$!GW%y*@`PhE*mGX~qARl!MMV$mdl|BE>bRWb+YmP~R9V0Dk zyy4w->aFCT4`Vt;j_OUnl~k*k!vq|0b#+CoPIn`g#+vV}+`Q&8@C*9(=xBd|`F$`b z+-Y}=r}w1)gGA%va3|>(KJ@n>6 z^pKxPY9xb?%H6ER*Hg_G%szj`NGKJh+2gAjg?S#|72O=l8{oAXl{_A9#8_TW(s|{vN-XYt3_%k z7LlcB*zLEui_wmZ=&Jm!{KprZ04v$EPG%2B_B^wUmg<}d( zd+C=@?A3-KrsEacNYj+ad$Q9(Ka(NDpkk)Cl)iV4m83*|X#Z}kwcMRYGY1!5@cL*b zA8d3zo9KjM>|*&rW2cnHWfO-$%rx^8Jb)t^UHP#h)hm0(R`t{U5WNF@k4Ez<%r_kLb2uu&Vle0_J^H z?XRyw!HrIK<&Ko-(|VgVH36~S17+|SX=!aGTFtkooif}j~uWli~c$#j?zAFeWXlYWxQ+c@{B(9p~w|( zbDF6A==N|0DzfZ8q}(Nw_}xZ&s3;sSXv<7EZTxs;Ak-R(_n#p`{`n@o}Z9 zEyLk-m*U-l)^O=YRp*+H+O<2JEYwfc|E$TlU`>EJ*T2@}FY;3hkW|dYnyB{Zt+Rul z63q^(jSeW-itKT1LqxW@Y6XWXwTNCGLMY!W&v-c=N)8GglNq^NSEM7ZkR32ua^87! zeaXf*w*%0_>FT7{aodpAO>K{H8V#-z0i2I#G0SUe@6;#aV$_Mw4cjyO=`H=8=R5BO_y);dC>LP| zn>oaUBIonoF8UnMOJDaN;^^}$y{u<0|0(pe>;&e2oDMOas2zgs3c=DIlYb5wI0fBu z8~y?}R~pHzNDoN;_`^c!W87Jd)yi1uQ^KMkd0Aob=Ze`(trulha`4{abM!2Ayg3%D zm5XYRfyVX{KGWeZ#yLFW?mfbj|yyWraK3Us*EBt*HkpJ zY*8y~mY&V67Xee1$xW{Z)WqX}j6r9o&b3^>=epuLnmvoyfs}{}6im?!W&O%#T(${b~^5*_cQvNF4OUX3w;k zDYY)`^`rQ%`pIF&w0?#l=6qHP6F1eD4ro3ozg(oD9y( z(D1;`Ey>3mIcYv6#~66Y?B&fweW}uqV%EGSkt!NjEZ+dO29ps?OD$u>bF|`t15Tri zv9vbEG;x!Z*14l#mv+9O6cX{I&H0x%PP5EK1#U9CRHhqoPDm)@zcs`-saPoc^yPz) znjcA;!D!p-4yjv^jazaXf!AlBee4PoEhUCe<3~G&BPN}#nb*4c2EGHn<#&~@dz>C? zMCRvQh|QNe3FsRvw4%SF6WX`auj!;SYp?A0rQj!Z(mk2N!uD}%4>$!A<&?4JaMZD( zia2@2{T1_#c@Oe8OT;f(ObvJ7CUY<3x4k=eKS;$q`c_E8ZMyyk@DI$ft68_OQn6x1 zF_oR>MD5_j*XPQqXO`a@x8>eN;%0qZo}Z0_j;=jg)#y4gH`G~Rx4-Qc4k|ETRzeb8 z7yG}>6wnf(3+^bT*DRS7Z|4ZRk>Aa}dVss{eN}>gsERz0XGLBN)#Mi@i}}8gZ2MR@ zKd?OX3gUE-x2INWUfBLRz%q>1jMDC&agp_LF%JxBi`&aGBp6I+^O^`I+K+M(7N(D& z_Vo9^H}Jf`tBS+%Yu#vL8=wBmpHW8@o!+Hf^vDdTP>}32FMZ;p9IQ$`qhbOB#Oxo+ z0BOezW07e~kh9TxH#AkH&Q+K>`z_4}ICipbDzWFHvSxgXZf-e-09_=FKUqh#nA-gW<^Z$0v18MH&AnVcwL>0fPLe zmH*l-09allopKy>`ek4zC9b(FLY|i(i+ZpAuA47B`(Kf4H&N~~@}m~^9fD4WF35kK*YBeIzi`CwMh79MLjpMYzZbWgs(t6hg|3sMt^j}o81zhb ztpGQD;+()}e_V&|5&9&hee7T5@TM@gCLy8OXYc-nYyQ9Aj5HB1w65(hFDo-?`k?6i zrhfiKoiObR_g?&UL&>@S0x8>2npEiqtMr~RrYbY;mKoX+B79PUmUV7)S>cd< zkkzhR3rrG>al*A%Drh`PtIly(sU2ZoC7R35qr9%$m`p_QHa8XkaJE$NK{rTdyU;z6 zj6FccYj6_tq%(PbyNJ{rfStN*kpSXI1n`L4wy-D}E%x@;lZ95*L;=iDif($kWvc++ zaaAjL>r1rVD=*_r0|3Fv4UW3|uj|wkyR+Q}OPUn`aMao3yUGv*Z1q0Bu1_~!s;<&W zod)kOr8eSQIB6(JRqq^2d{BUqWLZHgseY+0(wN}g^7fcyMA+;>>4QvV2?)}Av?_nJ z3PG+(a|KodtOlUxyD1v;S^5cM$pMqc{J3l%kS}kovc7tzC%blKs*@0YR_7eN_vb&1 zB6BpeJIf$3$j?saV3=6q#RD=4Cv8*hWff(g$zHwYMzNALl-26BADVRj5GVF9>+$!+ z(MEC^yywlVk+6j!(s=c_>JVxZnTf6?an2!f$(skEOH=SJT z#{s47lTFjY3IG7gkcv@05bv%&G{-Unj=jb_%w_ z2MxxjUK=36g6G@rxt%GOmI_+DL6sUPcaB%{7z>fO`s6Lh)Dhp>!*&WaPjC`zR+6!R z&L4NKg)DyEYU7Ps{I=ued`=;AzLI(bsrZs}pyPg^iR*i6PWWqw1&nc zE(<+Hp0EcJ0k}V0cJx$OYVzfDDCYc5Y2n?9yBcgDPKVwvevdxu6qMuf7rlw7opa!T zVg9yQh|9nws)EJvP8Mvhv|`bmTbP(adQCG?+fll_c*ud9R1UH|W(z5a!<_TczjFa| z+y5h2(}pnX{74vBmmz>ac0> ze73@Cs$(CqB_nD`erOF)S8vMrvd7%`JT6)j$XX@?UFrM^>GN8g)Z_=z`WA-6@t4@Z z_wMGTy0$Q5wP(+H9HPG7BGkL}oPamEr6+^pWbCd+E}CKEjVGMUnf^wNcle;wh9=2P zpV)m*f_^oJHD7EHwRy(1Tr?RH4m0L>>j=^p?&2{98~mL%o&5(OGk+5 zSdH1ht1q#|31H*mvz80e{B^C+iC#7B;cEBMo3@&BSy1ME@&ip*J|mbPXp3V}gQ+A_ zVqR~B@mc(VtwK3FjJE?dfLC$QXz^&}*}E5v(%kBGA*vO?r$I_{9)-rsw;$P!HHE$8 zhtgO%mlc6?u@4*f;HH(54=3&rG2L>hC-M_Ld5;^LhmJ&WEhzSIsy>@d$Clq}uF!iII)SLb1qx zFKx8G=mX4@8l#RTy;4Hx+7nyoc?+JwY|!f8!#q_3_{`MJ3sDE#GJ!a3W3>Z9%(5@L ztDF^`)!g=qIUm-f^ayam*MB?VE}}N(*=JJtL_P$h zRvroFGX+3hOh%$u?rs(84g^zXW4L!)a_m0>qWDAc-1vxXdL#5ZAG@`v6-ojTz{&KQvldfm8za#j=% z1URl=-uF*l&fxANfQ@UlCU(c>`o3(6saTpT?W|Fv_{(_dr|V{RCqn`^HE=vO9W9|c zIg}-JBOEB-=7Va+*jKU+2wm6seYhHRWpqyb_@wCEe<&+=%O|b2Inoc81hb=IX2}Dc zO;bSa`p5fqvF7DV2hz8EZk$;QhYuCS{Sbwo0<2PRh~QqA<_`-Izi*EHYOmn@dxjZo z$K<%~lBMEoVKihfP>M+eDpqfrqL6>g>^=pF%XF^T-hAzb@l0{{%;kW2EaLbw8shr( z=@y&CfxRuY3_N{UWo@U$Ivs9d^TJ$jJVdY~4cvQ)w_iLWU810!VLL!ml^>59+9|#I<6N_xS6}U{++|hx!TIK28n>VWRfO3A`o_ zgwdWq{g1OL6%S21`5yprT|7$pAFyLJ2S`!?pVE5c-`D>a961nn@V`#(zXF1PJ>>t_ zoBz+!g#XD80YL~bR6*@gw!=`9yN&$GWNhLS`ouQC{p9JTS5*Awt8@O)mU$%X7VSo^ zdEiakv(ZF&OS9lNO@)Kq{#C|G3sL&f(w?XU0Z93$$LEw^5-#d#xLeUf>%4S7T>U2^ zI}kSU3K3Tft6vBUPMQXaRPIctZjUcC`?QmX?i?qvPiUMqpE~5xTla6sDW}}qHZ~~6 zs^;VQDpYi6>qc>)U)9+Ph7YO8n$eXmr(RT#d`h!0+yrRNg{ApGa^LV&@Av^Y{$B++ z**W2KDY1I=;znAcL(ZPC^xZ%cX-HHmjh(1*oP@kRHodvA=Jf{bMEM&q=I|q5zFcng zfblo((1E^WA@D)%^vSyeZQ9szt2+N~?q;Q-7+LwMk`iry&+X)Qj)gGHn$)2PzOluJcMUjK;*g@uKP$)5>D!F*nkVTuLzE14^mUmn`a2+YOSw zU^#Zho-{b{fMVi?S%*tpjc1#H_1h+yk42tYChJbQ)^k#r#%s#>I-&Yqa=j?qp( z^IJHSE*^F19}{>1&ePCNZ`lgJ4V;&m!*Hk`&9$;xk6Tk&I2(bYg7pAvpQMWF<8GwXs?8;?P2G~L9iCbk zJ-b#@I#tAG7Te%vY|ykwK~oU7uA&}ABm7Z9WBJw3DF*K;vaX-d*jx>vUtK<|#7Y(6 zR`5InEd`bJiF0h$=1b>=VysVr*6WT@L6;pNg-jY%4;N_ksM5*|1f{o_#U0Hn?W zY%{sIvj`ip0Y9R~s;_ehEv{WV`x7HkIRcX+&sRW}U4H~Hf{}HP6FhLG*Tn%1ng#NX zxPna$rO>8lw%O>MZLc-F%(45Fl4IAWQ#V9KMJ_1Fn)g}~;u2JS@+8!J3#2oU8_N^; z>?2YNINLx=$r+`*a~Rn@7h(9(ebUv_uME(QK!5*y zPn%A9Hf)^&sH@t;p8|dP(}M13ztJ%tkTSUNBe=$QJ}dsg)wnvC8GtJ}BFTRIhs`KO zSqyl+91u#@8^c!#-$1o)YacxX!UsBYRd^A)b zFp(|=1V!I)>@{0I_RqsgUO#puY&8N|v%=JXcJIWB&(_-qR}b8$dTUBmPYYCB5?5)i zN}jWp2o}E7<~ZciSnQgY*RMJbi(1~+NT^_}7&|wn;8&+8B51O)`g%FFxMy(17j-m# z!#ee+F;V_D@jLo}2)y^BfDkmz=w>hy>2VjSzy7l!CV8d?+9O_C{8jz8q7KtY%?4d}UBZ=TOo8yn@K&0)cm11rFcjU0wKi;DPV=M5p+ zGCId~qTYRViz@56SdoNNimP(+Oe#O4by#9hInOj@3-ac2LX8+JbYm% z?m?o4-wqMjst=M6wEcZc4~W*!qeUd`*sNw0f#0+hj58y^0twdY8}P3Gtc~n}G#kYv zNg3@cgsd6U?_GNx6?0_{eE?j!pU zF_~i!vzs?ebj4@*qPJ%aN@hSXj_2$RaR}b7Ud?x`L_&!!$pRh2{)i1!cNM7R1pT#= zAn9p$7g8B&^loyEv9iV)jG%#!4|A~UG+8j+XNtfUC6ji1 zN76HCP>qHR%qOs3GhQt#3YlbbYJV#r$5|a;p~lBTr$A-cl|xg2@{)ZyA>w#F`NbLK z3JV6%yAL#`5e#W}QMjqMwP-+^oXTv9;PQ;hFTf8;UD1hW4wqzx%f?E5S>YVm{c+eh zr+4W!Afor)fZAGR6kNujm3uF~Sf11ow~sR)b(Z`c1mI?HSy^LQ9X5->2prjST)B(Y zayeHNd!QF6KY?sk-^V`=fBc5Gx2?A(8hq_*+54*w5fYdFx;}YL^%kyA3@~ay%7@!k4do93L25lc+NZR)J`?Drf)xh*_04f% zK(B6@xqWiYm{g7RlREB&NT>iM0@dvLdOt+e(epoWt3m$ypIgaO_{>aR{m)CY(=XIXv1qbAvk?qK2<0Q0OExlfo)Hv$1BV=u=@0|Oi z;|xsrn`0%@jW6lMM5AB?s!OsBlyr;dgML5S`Sn(b!jp=eI5g3fHr0(Xslm_6p=PGN z&ZYY3f2izas+|HmEzgPpXtne)_3lZx((PQM@a`3dLl2~(h?zBGr#fuKB9~+`7NUYYtYAY7cKM9)?T8mqp8TWp&A0HSgoBmd`Z zspwrEqLza_dha|$r?O2dW^2d+TniK#qA{OyKi$5Sr4FvTy`C!wlWidGQ16#h))bk& z8GPIZzhmxMdAHC~$$7vk8osaO&c4vmlDBNY+CO#WS@|Gi`f^c|Jh%KF(2EHNzf5)d z@NKL%*vl|+9%JrR7cLy=S~9MQk{mLwnDS`Q8ys0!F_^nCPRgG@V~WV~qwuTL*I!A_ zb3F}Pz53)RSN%g}ElkVtN0>!zKH#392pVxwyeNKIe>)@5@`4*fCZ7irn1DgQ6c)bh7$0!>%&_9xgo%(fsVA?)d^oXjxjfiKq`slIQfboOq*0GNVg8hrCeENw z%pnFH__*aT1{IC1GmGqZcdRCa&lE&bl}ny;a}tbsEm@^N_EtXqX0o1tIYwqn@KoO5sEQsfWy!}XsAZ%pe#G{)p(T^+sV#T@hU-o;UbuQ?xg(!iB|wd<8^$% zwtIwwUg%V7(A&GgCeiSh+@~IfhkOYoz_R`*@@)wSqkWV5j&Jb_q*1fBLs#i0PZs0u z*DfN;?HL9~7NcFPR4RFE<3V1!{6>W6?8hv=5&0V>H0v!C$j1RI^Wb;VlLSh@(Qejd zqMg_OQ#HVVJ(d0*BdZgAQ_@0>kKq^G+gFxYql?a&G%%9UIYShW3z_y_;z|ClgAi9w z^s~unbgvgup5v*JiHctBJU6A+^B=KJ2tzt}}zuj+32d3QZbW7UsLHO8}rd z$o&xjUE31J>G_%~HOe)rWvbh1^2M@m9SC#JwziV$%N3B$y3 z@$l;$LEa+~#!wLB`{Ilf-?gHT&4wCmCXG>ExhB4TzRX!)Og>b~grCpMS8~0Q({O6& z$d8-R%+JH)=Dc@|yd*>x99UN-Y{J2|^v3FbMooZKAo;xC%I*Xje~nHiPR}77gHO-Y zi0d&DkftQrYxouhP2YkK3F0%hNdom4Q$;WDr{yXkHgjgEs9k(!>3BU8M7R*tk*?c; zkV^k3kn$6g_aPro7Q?dBbCuiNZ&2Z$u~in|htO%@yyMX=e}xbs5&n_Nb>x%EKUJK7 zVC)05(WPv_23u!MDU*zau5U1f_7erMzazWobC->B7x5I1V=g(OS};dn2Kk-G_b+?z zeWQ2|2sNJDkU+16_*Sdbu8j2<6(Pv4v&Wl&#r$V!KIa>plJ~_4^^a=S*cBGHIh8`Q zHtw}^-66&cpL?yoetP%0GuzM#rt&lWio#go&)*74oKey{**JDVruyf~v*TJX-)a8@ zGR!5Sg`K~~Lt!LO7pV9p?kjljar!d`9xM6O@uX)?Ceeix=9Hvnnfc{Go(TTzEtC*bccWa zLv(d0esZt8Fgr)-c`|C$ z?6z{K$f!=}z(His+SJA#f_`Y-P$I`!5hVzPMn~AY)*RdUv&OGh^|@20VhxswSxLNl z#jR`j2=@yLTW!K9TzP-Z31DX5c zynGi$7*iLZ64>Lzz;za)iso2p_o!F{B^M}C?jq9_rs4R@7jF!7w4fVWU8c*zmL_lo z{6f}!Jgq5(^c9-LyVyK~q2LV9z)sNRxQ@oZw*9u8k-L9htgefCBlIamviMLC#=4BG z8F19Rpeidv4!CWq$jdyAi$C*-;}Of@7yGV5b$V0NWpy?9#(?u<(srD>@QgV>o#f7U z$l?R)Z#8$$rL3^5PAzrh$2Y~ta3$=QJru8Es`_xwor)SkqiytcBxm+9n4d0`H{aq>A%)DDC@9g@$0)!JGI%6Kz!OzCA z_uJ!m20XZmJTt<(`OEjgWf1-wQG)$%`|kv+_-2G1_?`B5QNbYJEChl7bhB?rHw&LZ zSbU$}1|SGxd8w1TQV#5Ig|KVIj_3dG*9_&;9$3;3N8p`HG~PiUua8>HubT)%d?JHG zIf$lEpSP-dupa>)Gp+l}p#X2w8%oE0F7z_OX)@y1FDSsI` zCTZ0_ITJ_v9hu3a>P^R-T=v)Haq5CjEZE?~Rp~yN1c~JAIIHWLtuYyu2?H6xBVJYZGM)#;Ohc z!^Wpy2>EbaI;qVO%3;A_?1>-39!}o#?qo>TaO*5q)IEKV?9m|Mh!b-sBWf8)A8r_3 zi4^3$Drrh3(K09%3McnyapRn)g64bYW$NS~Yh{JsDv9Z=)#b}9;gB;oH;>sv-kzhc z*Hz9uw2%2*z1oEp3i6$-Svefj3gj3xIY`MEhCiYj|(nkrQ8cUR`MqOG; z6y5Ge6B&krzx}ZZ_Arr(s0QD7-_W+DoE74Q=C35qMB!wyUfmC_+n8-Qc5-mmEnpnARh)TKoaGQLmyi6?i_#Z5mxqVWSwvzYsyoHvFvpd!@ z?&4m*!Y_JCR&P^VJRdxQ3kRbc!nHQeD86*ApsM?xzVGPXvA4;P_dp@?yeCni<`wB+ zdoxRa&~kQ7PM(sseMdn$*HxaH8?raXo}{?9-|BF+~*FRfg^KJ(E~YXhL4IkHCZc7dF^0zZ7NJDUt4uCD2Sah zD<+}7LX7m%x?-ihaKa)YH1fPnEOl|nfA@s$l_-&M;H0Q&wRfH1y7KfSPf%e-kx2eh zo`;M-3vUF==jf3M(VJz>WcTKJl_HOb1>g%fo-cS9+7jk$R(Y-HR!pS`vvs~NBevRf9klVY|1DbYcF5L2&XEUd%F(#2O;y6At1@DZ*yGJ8j8L^-k^eg^Dd+L_D)m zh#`#EZ(Z!BY{gBu56X#8#(cswwrUXBd+rko4%4kZ-JR(Vbg^G3F*$=AHcZ+%X^oSFynU_u=CUA$p==>9p;N?H= zZe5)&b6KDiv@|@sxYGYD0Au#aTrYpW_}cR9-W$@RU+?Z<`C`DLU*TR>X&1yTEU05( z4}fz-37(uv?e1S4>Ard5cDh(LTE$_yZ_2?7RWBlTIMp>jGOtXvJNRR>%M>v|{uSd>myvLjWf4(#){aw9HC9tgR5*21 zzP_WNwOZ8i^HHFmtF|ELGl_`xrzUS^6x?Uekh%RX-yC?GXw&&?ZArFCslMh^$+|1j ziF*7q?m(FKu6M`Vc-`Y0b|yR~w>K9_a2re**LSSyIA1S&z2+?%sBWOkpH}0GCnjG{ z$6$8hZkBo9a1P4X@5?zee_l`Ij?)AE9mj$5imzpkUUd2t!udK16H;yr+x=m;z6s+N zmTB6W?v{LvA-!1?O*{nOBgwomjW?)0?ZN{?WAw6=ryXndv`r$saT7_k&2iHXyiH^c z1N{{57pvC(8s<@~3r*Y4CmNl;I87r7i*2}>rT?TpeVApHa!4HThC`T%*rsX+Cv zX|8D39OY=$?uUk=gh5CO18Q4b*n%$=)SE=R6}))F5!ICyNHgt$;rwY+kejHabg)78zn7SdKZdxT#gR(gY1jxz^qa~@uy}4R zx+9}HylHJ}Cei7bg~0q=VZ85ZC|Y@|D(%j92Lw1cm0vTtQ!8kW2=LgyQfF7SZ=%ef zzNVSTH>cA86?v~SnI)cg`5I>I*n=f0y2Hsf=HfK04Oe?LWb`^UcDT&(g<>L-cIOmi zoXv}pWlsz8yGybnm{W%f4iK?x9R>NNen|z8e!JD{WWk{}q)WJ+VP0Vo>P1Sa*)y3R zcQ%igY4TzpU4Wx&UTK3jD#ao0`Kv5N6iyfTvBk|}>l?aota+Jdxn76jF19>QsRNy}mOn7ze^swA53AZ$vax2M*sv&$HnIlD12Jlw%{;rac`?Z@gdJcPXT z)q+c6LrZ3pU0S=jbvuuB$HX_|>6LV@*sB}9sZ!EfSmYX31KbJN9y^##n5Wapa=c7d z2FWo23u$JUS_j%C1E=jmtML^%Z*I&vv&tRT zW1o`QBROtZS3^8`?W#xj=&c8C*|FyLGovYcz^+7(-*Yu~wZu@912Qp* z`0zKgcwe5)fWGuzj$Vjaq-%~d3Yi0ooB&b3sJ7j2@pR*Blt2kl7fwHgD<6b)t_Xc@ zKdsT7^(mXA6BD`))XSQUiG(jIqwnP7*SfNj!_maAf*u*_M|&Sf4zQbKLh zl{{0sua0AyB|Zi9=MgM!oe(Xa?5k%ESb4X0wu$R2*y2XJ_I{zt)~E4^u1h;LZv>L$HVhTp@M( zS-i|-tBY(|o?P20u`7WNkB~Rsu?}7So`{&cE4$^mH%TNXrLd^95OPFU)B0rab_#WA zLS~_8dV2A8ms9RX^@QHeA1-1!lgq06qEC8$%x=-irQNVC`%@|>vK{k{aed%qo6`zk z?E@a@q1`8RxC1bOO!#2Z`|xvKOMwT4qe;?+We;E(XXEFdM6kH!_DKu=TId;FkTjL% zNciN(k}v_Jq}J}Y?#5yYJOs1{NVS-&#cR7YpK76SYaIB&6}6=T4|-Ajr}S1q&N8%; zzj2B z9^?1Oz73yyII4RC7mq}7^0Bvc=T9C-&gi|3kqT^+5AX{{+1`M6RYUy_1P5< zr#Lo=x)EvEFApYXWR!8y6O+aMmh!D5{m0lG-17Rw=rNH()((!nxMH(V9n^;* z%L2_%)MdU1h{jvzxM$3-R@H5in7TdDp0RjVE&s>s!9LJq4Zt)Vgta#bDQo>x2_%1D&Uv;<4tDS%!Rxnm`~AZw34)egt%gL? zp=w2JobdL)0TSyf0?$tJe%v;_&Hpd|En5}W>e%!;7MGBGQ#)S8?QiMPw^5Uvq-gn| zQRgkP!4)A=wgud- z=zd;vot3iyFxcO_&&wCV3a<`8{D00igDcs#(Mr8|J`R(!Gc!A@^$b* z>6X)*aq9j5h9^DVS0d&hgR+M@&VM;9oqLGM2?@WXDsbbf2tp~|Rax5lC7zGd|2a+L z!x<`!ou}v}bAFV&kVRmz9k;D52}Q*ESQo!sI*||HQ0+wMKGi>=S^66tGV%NEyjqD5 zB5$dh`xr!?S?@9O%{NH`X2t{b@0rS=Z?6*S*WO3e^)c{806)ziEJBW|On)r<*e+1y z%egY>@0C>Lbk7L6_s#9#&*^noJ`OrWT;*^|t!HI@;*CzdoytoHUNkN}w~yFXm6gyS zv6IdDTV8>fGd&D=v7i1t!keR{dzZHQNGs(lf9SejkYL$0KZL(z86=6)9%Q;uDtkqq)B6sI%DcY5u-dkvOIv@vtpeG} z5;}7{GiOE@ufo>(bHPQquqtrN_2!FJHBqxa7lYRCNsqpcMoM~`K6-0|jQz$16B7S| zM}iD_cWTM}B`SU6?hi#aaiD&BVvfU|is(3*m!JO$>N?o9bnF zPV75SrsT?Zo~!p;yP9=@JU}tMt#kk-k|DzQq>*Sa&87GtwO+VxqA>|rr(Fk>YkUEH7 z|4_!JrHYMv+}FvqDVg@hsk={;nFnvbemM?RR~U+Qtv5#)P^ov22`Nj3h?HyfRq_r&D!D8Ub^<;6~jkV=q zPharc7BYfp#TtV=&(g$EQW|vn=P!{p%Oo$v6{j|&mV~M?r$4%7UOn^^^vEGb#RMS(Z{YTryt&WT5M%acV|9@(8K?!c6tHL~n0eOXzcQBd3FdeKBD zD;G>tN(}R0O}uuU0+h`DNz{+gm8~$FuVuA5&I3teB>LngECa)k$Xn7?~aN4vmo9xd#mKWIOQA1mz?8=L-exTbs49m)wtdaO^^ zaWSE%(V0Ifd1jdb5tjAFzSYAlIfpYIHRHxn*}@k0nnk-`E*>;-y;3 z(|sh-xW1Fz24&{0C7klNJX=mEMyThMYN1jZx+;{Pzae6c?g!RC*pbV~t#%{6bx}D6 zP3#YpPc7UQ*min)5vRjL7#ud#Rx^8^&SQ570p>Y2D{n>&s(slpv zaqD+`MZ1ht*@L+T)+(cnnC zgMYZ~^$RRM1cD#n?3PUgc^;0(^!d`RR_Dd_e%fk25wX}j?Bdv&a}&-t4S%VR7Vlr+ zfVWq5SLz{c6VJ>I;z^bu8KV>h*@%X>G(p1ii;r1ji!` zxJ$F-qL?N@`}dr=Fxoe8;Na>-Eq9t3d~I%A8+=OIkbkqp3d6rn)C3twU=MJLV%XrfMpN5G=EyJD|DqRbi{t7qs5|3IXRh+ zv~+_U_9Z}F<-$yPb;SXbEvM46Zu)QkgHJ%Bz*0OEBU#fEuTol;ZlE*)A&s!Va5VQ- zd)h{?f|Qj)!$cOfXQKQAFV)>z?{T|s<6Si>Pd9i16M*aACjgL9;xBKJ8ax%XcT6rDKA%A76p$=#=Dzs-q><~+;VJRywpjD z0;}E#&%R)pnU^Vrvug4i3=AaAyi?51NKfYA z?+?J(lUC_KE?1A#!ai^c*I_Hg+<$G_u-x|f^N!JjnYnEkBXg!MO(oyB#hzn?;=LOt zB1qhneDMaGiW2AqTQ819iH&;(u-UY>xA!s7;MAl4?T(HS(hL1Pn?V)XtGB=?A9WzF zz-qpG@?9Th<|PoHemY!x-Av!GT-$EBwi@S!9!`#SON* zXl~l|u>7yl)B4m(NHM{|bB$mKsNqmPJsosbXmi++N^d&HG|dd|hz{+4o3JXl#~4w% z_4hUY5&}gcJE-7>Xc$fu0Yi!rl_}^3+kh2NH@t9=K;8zle1=ff94AxaJUg;v5Z)}Z zl2#Ld_EXea1>=|9LtP5dVr8b~S}%UP8=Z9jDe0{3r?-1e-Mamn;*ov#IV1az3T;m!UklAxg5!EI!@WE@c}!-LO8N1sn=7AWzEK|V?dSC`LUrZ zDMc*_zd63b{^^M;PsbLxdNiGmTIeKDPg^LDYn|{K4!-C;vzpo<%qkp3De1Y;zS&=e4utS@w-B)gu5kN2I(f;aA8hR~t?`NH?7z(tQQ#-& zfN)(Fi+!xcAEA6c`O@kA%Bftwo|iZQ9hQ_dg6g){l38BLo)8Tmsphlv%ynV>3uKKf z=<@|-AxWw^xw#yS7RJ^h67Q#kumv0ljd2cC8pwn6!Fg2K!(=L}wk=Pt!AA3lgKJy& zNprDHXx8kBO52WvLV>=6aadD+U<1Zgy{h|^#5tn($jXF;r>)OX+sEe5xk2n|_ zH-C2|th@YEXoe8Pp&pj>Tet7|(&Aa$o_#I*h8I%nj!v{sk6I5~<3|zBg})rTKqkj! z1(fIOm|&-7TS~j?U<^I(=8e}JzN_u?uPsA^PDUg}iIT?SEF(*^o#ElzgWlpV#e3A^cNawvq&+}cL)y&cd*>#*4^Z=`u<>5d{ zqk226%guXB-|$!9)FMkN)|O+9r0OCxE8d6l>h?ar?&~|^Jr|D-ympF{U~xoGoWpRk zj#*EQ!^)2E>v%lBv_dVmeN299Mw)q2XxmK7Az}J+HgqR~FvV6RVZOP-@-NEa&fOjP z3bT27ylLhw5B9S!mlh=j6l59YyTO0tZ41kE`Rnt)+rnfhvqtB24`olkHCuV#2~EHe zDcyL+6a|;%I+V9&n3KZM?o3oW{#q?d5>Y6M9;@j9+|43pf%8);=O$DRO#8p+yD(qq z7eH`1;DFYPCUsP~I5WGz z&(BLLK&l?$ajn^xHI*v2de(g?4is*ms7ZWdD`U!>ak^Q}j9Q!-u`}YF$(5KLFG#Up zhiogIDczo7UB`ZYetGs4OMkZyhB|GNxSNFYK1T%F!Lz7?6GMxs7oxfGd)4-;&kxbH z45%0$8X6ar*O-$Q^J^C6<6?VbdsgqO6I)JBA2q`lRS45XBvlu$^4UNA3gx~F!rlWz zc_huiqzl-HcPo`lX@mgJ>y4;O-kZQL*?i#FU z`t4L9<|6wNY%Q`|Rvtd_*`XM;^DWbKb-NlnFOPxh@la+8qe}mQYX7h|_CC#c8-B)# zcd=95ajFAZk+_mTl(tbQ!%=!pXW*1SG3~b~WxZT;jIR*xtNlXjoRddBou)D8==rog zX_1O`5ipmfVJ@qne17rmuIXz26C}a_0nlwG_Kf@BZT8mLR+fWxux|L-Ysu(Tsj8dr zp2^`+II1wFz>@j2+g)~>cysq_nVH@ZCS)4v{Xd-~r@{rIA0 zR1RdnwH=*%2eOhvx<+AxIX-c;nrdEC=RTehc>8Er%#`WT-9a8RuA5B7Zm=~c6R`^6 z<*CP9M)rQz4z70`Fe1P&j`K=lexAq0@ zqTgorWL#HP;OJ$a>wy@;CGsXB#q8JnqV}GvnwOO&kAH59Ev^#vK`W9~;#BLZjJzt0 zPxxFP+D$|A^vj`kN$&ke&93PDFui9{iu~0`x_M4+?EA6jIZM8v zPwJ@ScsO|mt;dD#$1jZGlPB`rFDTC1uQUr>=qZ24td~34oPF!1ZMV=;obv#GA&o4z zr7oD*kh&}@J|*(s$tx}A`1#0@LSzZ*L9ir>(WJeiyaXv%D@j~%#NwG8aDqX)_x@>2 z-ik!Fs1P9B0Yvz-!goFR1N)?J@a11H9VFnzsYe(GVF=s*8Oi;(AfNT4zcjRU_A$o(r`Qn;=m4rqfhbKBOGCrNcDDuafW$`p zTlr^NbLzW8GAxnqoR;F5S9d|kN;jIM`IqQz( zfk}VcaonLwlyet=Nlx56%D-DR#iJi3vPse53K*p6G)13PtKnmtSGsBO;c$% z`~K)i{6+EnZU21xDp{(pwRd|0zfM-+nV3x3SOS3xC}7s+{c4HO7du~EFTZq{ z9|(R;+DMF_N*l^=@ELr0uGv|6mWw*j*f$YO{o(~%(ciM2~l4I^-;QeJ4m69L82SiCDCE7S2%Q= z9SLp1!q3~>7?6(#apsLTyZSH6cDSu{6N##MWyV0d`@Uw7%cAB~U(58LO+9n+Lj3(0 zseqf0%R{c^-1LF;EqpqlwW~`<>k0wOD}!qzx^Ze#b&u4s)W$4h9 zFDxc>qb`)!-JO$Y3h`;VmKLu{0dKT$>XrhJX|M+lnQ z1&(q0!q&@*)9J}YRNv*@#VjVibvxEagW*A3AD7r6%=sdF2-_{U%m&1XS! z@d24@#SI7n_EvB7S)*Ns>zI2y(gbEe9ZPLcJSHueYDE88T9Z&AUp zV>$yS@7$VORr7SnKyM@IOaar|nTK<`Pf^GrPOzFJ6nMCE9(3IO%)mOtGid*_9hs^c z5xdpEjE9||cc2l>4Ngk)oR-_4wc{DPSd??sgyc`<13>dZEhKT(C*hYlmYJ7#e*zcR zE2XH1TE9s&?vLI*2C9-D%Y6M{7rA@ct6abRv%eCgiymtsJJ{tal^nNXxMb%s&BW4uw9K{T@K z3~9tAZ3#?m`|}G57!^Cv^}b1$ox!PK^8Q|CQhTPJE}GvMup%omsm%)T1L;{+sH%U* zMC27^<3d9jksJ?%aOXQfIIy+=mR&udl+iD)3fe{{KcFND21)prHzw75gK^EZiD-x)K-{9?ti?GgGpP~bK0w*E!;ymFedHq0Ld{i|=hXVSbnuP82HlQo~l&><~s(K3BajS^;7&@P8 z(AMndjYJXU)xWHrbv$N!7MYRW3__Ai0(&^`E1}fFtc*x7)K8s0< z>pM0}-5i-ITCf0wGminirs1 z{jmsBAi&-phcd>uzQ;4!=O+cUcL=>`|0B(A5^%~pI#uPz0z^`Oxz3@0dSmeZiIh)5 zfL^4foB58;IE26@<njCn1YXfD3xFHlBG=90BE%&6F6l&WqnJsa&`LMF#g3Cwx(c zGKz*Qm}BE>QI1E+lT0PdLvZl;QO}rLu+#+p3X9*YHg11?pM1{!1pSb8X&37SH98iT zJqjLaTrXBbgH`x{lRZRpG$cv?B5D6oc$}LA{48`^hCX&dA}3;B8z`w|jeNPQ3(<#u+`2G+eEl5g4<)2A?h`6#L%yXBOABG=#ljOcfMoDV?4jJFZ^q=aTf=qPB_rTSgQw=wgPz9hQ|M@xEq@-JOlNIV zn9w(TN|G8~7fM`4;I(a%2sv*zrrd*OM@~ybPg~4ENNlvS0j6Tli*GM>V^5S%0^akX z6q5jfn}`Dbgp$E9BfsAC=o_!~8PYK@gZ>e>tMd@rtxa!xIQ8vOAiSf`t={@ zKFreeuz>A<_+8x&Kl-yNILy!wSqX~IKB#W!GQV%T$mFXCK7j)w7;-CfJbzge>yLx6 zwA9_u{r{Nt|J>@}`W%m>N{_?O{OsWUA1%&~cokjUNG51~5P9KtBE;p9-5Z3bcY1t$ zT;?CvxlZun?{rCaxa$>C=f;Pi6sL-=DC{h@Ptz^K+kbG7QTi#0Z%b(Qq+xI!;@|DV z3T?)}2`tO6CsxSI#yPzdStpd1d1qFFjcn?ou!!^5oBdXuz@Tj|jgqqT2U<}H;3ta} zSJSly?(aD=h$Ibp7D_*@JCHa&K>Z$bvNkRlP1>{0CGCsLC7OcQ=)pn;ReJe2oh^SJ zaG_v=Xr@exd;_=$9?241_9LPN+lVadH85_z`a}pk;KUoD`5oBOoh9|6Z&d9xD5z~c z3kZP&=on{b^Cls&SP==i2s5~Xxt^{tWeExSY2`A6pmJ4c@gXO6Wu4x81IKX+Ld#;t z2}+82Zf0S@Q?e8bw5vEIIFoPCL1}N-GzhJ2rRZ2grOT@#zf`X<>B=(_Baha{tQPL8 z6Cmt-sa$wUEpc)9wX<20XIU)y$u*vU*6lCc#`-HNBEek8!>)dw-O8~OZ{}foF~Vx< zVYWs!|Z4=_QB4VQKt=D8<93IwXY4?#&YjP^jx`1(qn%U>n( zeL7*IfYQFFI6+#|+#yOb?ycv%*ZQ{Qt4?EW8@gT>46d!K%qZ~IT(>qs%KjaQ|AE5Ad})fuV&aV2LYs=Y)oigH9(rLKiJ5EdEKT;h z9X1(p_8RxA8eeCps37*i-GTY~dIVaSXFtd)po;EYtT6|L8yR1$T6RUJ0acVab`_HsiH0dOBH92`4m3WD95vX7{bNU;|^F0 z_0WYJu|5}!AqjB2itp1TaVGE=y|#smqjxPZ{WS5R$rJC5&SPj8oP<0oiUI|{2Ii#`f|+E<&Ds=cMKh9waW53@!~7S(n&i2*&l^P(D5HaM ztah<`n&V>vu2lofd)pFU*!XZ5scW7ja3r;gJ*e}mK@-mk3aYdVf{sd?L4z__TYVAC zcPy@PFtuP+AD&r{hQEHV=__xob3Y=jS1EAf4$36De zb$wIZREEuvi;H%r&=hZG<4_!2K(+2bTyVdi$cMmf=7i^Cv`@deGV8iu`!_&IKfXO) zrSokCC|^}7S-<-DA7P6Ze&-T>X^K8N?Evx$KCgF#ZRJLtN2SUt$;Z72u zV5UB=FrP!|B<2*kaKaOPdC?-3b#S&>E!qcW!ndqS?tnbq7z-4GCcA%glV5(no7&^i zzxLFcOLBO*qwHc&(8c*;^Nvi%MTckmi1}5~irof1qwXtz-2QBGWLi8~)ZMvp@4{lP zOHW(cxEMpgH(oJB63`y7Nfdt>HO_S1&2Tww$3Bdn^x)Xwn>yxlJuXi>-Wih?YpR(4 zuc_xa{2HQ4f+x@I|Irjz-RH*m=H9rZc$G!Pa+Xs?PBXF8j(!o1)-T?*7hL8`#Y0od zwYlPtK;!kfiqH7sv6b!ljqlV(1Kmy>UvEqddmpz7kLYt3sO8hoE3N`31~DRSP03x= zB0WhwTzT)YF}B^Lr2^y;frd3oTvP=qRKm9uP9s(eFR?I2i?bW9J?J>{9{LvuU9cI< z6AwLQ^>`;P^ro928-WzWE~9kfpWgy-;gT^~@z-^K(Q&wzCUv{dV`JHN6CeqR1)$}~ z;SYYylvF7IA3rzi635_7!^T z>cF+@QLCaJ0}<3Z!#76ifS5o2%r%jlf+CuBc-Qn~=rZ>MoM&JIG|3^P$*g!BM!~sd zrEaP*v)+T+#Vq35Oo&|Zi=;Mrujbar+I}oJbvvRQo)lNQ;{4Nr6_o z6iWk2qeL731iN(iQk}SC$?2=sjETLaOF>jh_c^Pg`Oyxgm)7#F)<`=p3!fEA2cP@i z`%uXQauF<~@6%2Q^np*uGSMjXs=ecvn%%4S$Hqr1_yffYtu8E(y1jP`9nW5O)x3Cn zJ~gs@apm`0siA1f>c^$`Zr#+C3kw4#T+5~X^KP%oRvWGxG(38~_t_5$3lIW{E} z?ip89_w<`bWcAuW%u01RX)idE7BV*kVe!x>QC~S6O%k6MSg3rp+iP6siqXV5v*9UW zAP7H@Q*;@fUtP^Ai2^&RrIjulmx__nmW0Mvki4lQ?p;L zGFqtebF+G0Ehuc;Jmos8eCZ>0726<^H*k*MXmw`J(W;xhpHY_GCy`EE^s{v<%h9EW z)X&}|FtQOds%hBjZow%VcPpy;h;|{lF7_-pUdaMq*LW|J=QI5}F+jKcY-mC>Hg@G1XWZ?<0VFS4myAvgD~=AH^x#NT{R`faO` zHxYZ!c;fcl`L?Bs^Z-8DiEBqIf(a1lVbhZyS07O2f5sKvJ-ydx4ow`5zz=$g`pS{f5x<&*U38th zp#nz!)+eD=QSrGj_mAa$x2rw)a2D)Ti_;LtbRj)lFU#;1_!I0(-UGp=S7^Dx-H16Z z^Ue=Z-uL4fAB-`WZZGU)uB*ULC3Y{4X6^D14}TgkdBJuvup;GxYn~QLR#=Q)VX}gQy-}RpyKl1|Vk>rl2 zbmd2`8iOdk_oAK2Kyx-Tf1&U3cdWhJ#z&?cSM+c3mpe2)yWmm}?M{6n3uCE3M6Z~m zuz3WXxA@AWN3!$;6)5!`#iEv8^jU%`F215rY?%NC5{ZX8NW%>BaW3BFlhCZX{MbD? zS@s$Kr1@gsFe|55D|KMk4*taTN9k~j!9pwS=Bd6cE-j-yvsp*KRE)LfEX@Y~e$qUm zfUSA;{qBCM!HqO^6t1FtmTI4F`r)7B6NFK+=pViEv~=)9LwDPyJS=JK3|cnEP24W{ z9I9|Ai2q7xFh&Ps=zFc$wbHVJm%tG#wnhpDziP6BzBAAM2E)b(L zl5J8x8+~ZErkks-ts_r&HIJ&czsSpuXBQmnaXyhk9$yU)dJVCKH-)3E!@^`K%c?f? z7=P>jj)CR^t$iU8^IaFc-LkHbpLXT0Ss1S{=DUI^BukZ^wN6`tr+rN4c@nTd$l?qlP)kKy7C!w3I| zhzEEQAXoji3gL&h{q0(1oCNTozXyKk;NWt_;hq#Wmt!Iq;d~#xfIs`eQ zoCl9u&-X7=>hCqaj5aEre(tdJrnkGdIgTsn-(pL!u?dyw-xht*v0-H;yRpZkH@7T# zhHhzj@Uuy;!Rn09#oHt4;-L=L(wx6P$9O=E`0cd?F|kOJ*IFr6dm+hN+$KpWX+4w# zzC0qTgni%4b5ZzN==Uf%;D(S%N0x!(A%1 zV*HHqt^Ic53g8%->MiLgTbb{cp1zdKJ9%zqtT|3r90|@-iq{WA7vgxz zKg0Nhfa~JcZUe7>@vq)b1Mxf0Q&C;JYm-iI#82x@F>y#noN^UxqnlY8OZoecBT3Ce zfsrX)H-WDL+r7RSS1wxO*PpZc%LjFjxljKxA=o*WPn@^-bQwgAkM^lP`&8EW+`*?& zH&VG@Yv_W( zqaK>NnvkxOUn`#rM4N;4kRT`XBKhG@Fe|vRNOCAksszhG@0$s%8T3faZrUwJo>ampXwg)$XC;tsQ zdpQgh%2AhvC%=KW7QqBsnOP0I_HvK9={J(1z#tMRh;qRWldMH4iBn$0x3$gl>i<`J zS04>!zQ#V*xcjMrXwqSOu{ zG9lF-D=m^`l#uB*QkZB{y1Pp5=l3ML{I&O-d+xdSoaVpB^E`gP=lAk``+dHjFT@Rn zVTzjj;A#O91RL~ct&xzLg*}Jo+sT^JOk0*Yi;pE4@?ATD_&QM3_N2X3Lm@8g*ftQn z!2+?F0T1G9{vL^@DoGBpOX7!q-0E&B7|H~SfIBVDPtI1jUSz8$s06sGfA4}E{qiq_ z5;L<|t8&Yadk4-9^Np_u*>{PbXdvFt1b~jhC2OQ*?n(6FSoMaRVq4M@<<(AZX~>xw zvE_Ti1zWBp(F2AuQJf=l%w}-d2-Pa9d0e@3XNz^&l~CVNJDDVfuHN9q4fBP0qt)+A zuS+*hkJn!*6}5ABno`HjWgOy@{$YIsp+9U;-+#e~icU53clj|RtD>ocwD z6+D!++F@&wZ*k^yDhl>2>WtJ)xZxtjaeemGk3mY^LEaKi$y)20ha%YCAp4xgxPB@`0 z0(Z&D`er|WlI5aEc-3|!u9&|>L2y@$;f6r*rFq{W05CFgZt=jLhL=#V^+PHVeqQ*10i287KENgB)zXCCAA%-JFO4Nm%e&$K4X_S+ zqm|sM7_YqOGmUu}LYCw3MSgH`@F|DNfvna7y?H95SAuSftMB)pq3_ksLiHaHTPoc0 z`zO;gSY=LPm#WrXBrrZtKPlfD(8Yh&NXf7rBE9VXc7AjyScnmKjMdUx7OKQchgW0c zS&{3KY%$_r7IaDm+b!B^1_tyc6?M7#YVdMS?NaEGdz%5sK`CSdfjCw_OseB{dyXxl zptrk&pS=@2c&gR%S-8cqv5J_&YujWc#$D2dN>`kvl#*q;-@A*3&ux<{HdwQb0=H5j zFb`vSEvot0GiPmjT;f1;Fgozo#roJrf^H*fwjxWjMU6Ih+^sIZpouSUs%fhT0d2)k zd7Q1Gn<4v8Ln8rKEIbAR+Q*bEd3E=wJE{RZZH%5h&U?LR27;NOF4euai3L z0MU^m>!~cfdBt(co4~uibaI&1d+Kz_?PF|d*%N5{s3yZk4J3dNd2BOfL%9{X<|?bGmLqAfg5N2rK;?`| z*cg{l;^=G7( zPPx;3U&|SVoqCH49wyUM-rNT|IYQ69xA||!z9mwomp^6x)7)tO97A`F7^yec=l0H-a;XLdZw{Q9d?mpn}YWFjLvRowNnXnoCA=J}hv zq`$IIN%W;3LN$0WC}E0Fqo=W+WwVY3?EIYZ3g?wu#E1Bz>JBUWg@zp7ly|JCFmvYLV5hZ51 z8|4_M-cg3?_4r5|`4^Mbq31m{0Bz5OZ`oXv%~IN9PtZ;{7}=gkG#sP7I&rB$Y5KU1 zl-Gi--u}GM68R*PwOQB!aDE)$a6vpC{!=V%!PV7g=`u0 z9-sHVP_3!|>0L`HNrOfT1WAKl%UT|A>v*4uTegQ4Q^WjhPj{agkH-rGOWH17o9&B_ z5)3nb0%ddrx`E_l@8vS~3~soe&qg|Pmn)r<6UwEA7mvZFgY`m0uPcRdhD(-h62>4I z58g-Xw3Bim*Ivok)qhEeG$4%9Yjl@|iiq9bZ0!Ut&CEMTta!qw?X5+d>@3e;>;lw! zwq${Wv8S=gnv+kmW=r$jpYL=H*JW%?d^-0`W#10|${wF4v&Ob)Z)WSRRnqFc;$!^J zcRL@%#NlT@Kun&z{uVI$ai$aKYeRNu^j(#OgPW|9oNKvP@jledQB)) z{W_9lF(?1Pwfqh_rSYkfPUJN;cg@&6B}<(&$N#j55z;-8qDU zydfF6{Jy6iv?JM{eRQgPvBG%v!IR$05;`F`CAzj>g>3eC8hUwreZ|(Ipt!&d$KQrL zMwr~m(vKd3fBQyrzJfvDCf|8^kwETpr`n~h^^-+&n0ryueR^ZcYexzNh?86({i!K> zk(eDhhu>auW{JDpsl{|K4n&M~nFY$FrM+USlDJC#Ms{W|2pEOjj<)jSpZSlEsb3tm zUbRz=G1@<@w58()dRl-}LGzK|DuIDH}ed

", - "date_create": "2025-03-18 13:22:27", - "role": "system", - "type": "contexte", - "body": "TICKET T11067: changement nom centrale d'enrobage.\n\nDESCRIPTION:


" - }, - { - "id": 227725, - "author_id": [ - 5144, - "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL" - ], - "role": "Client", - "type": "Question", - "date": "2025-03-18 13:18:31", - "email_from": "CARVAL Dominique ", - "subject": "changement nom centrale d'enrobage", - "body": "Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites)" - }, - { - "id": 227731, - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "role": "Support", - "type": "Réponse", - "date": "2025-03-18 14:18:51", - "email_from": "support@cbao.fr", - "subject": "Re: [T11067] - changement nom centrale d'enrobage", - "body": "Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire." - } -] \ No newline at end of file diff --git a/output/ticket_T11067/messages.json.backup b/output/ticket_T11067/messages.json.backup deleted file mode 100644 index cffc801..0000000 --- a/output/ticket_T11067/messages.json.backup +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "id": "ticket_info", - "name": "changement nom centrale d'enrobage", - "code": "T11067", - "description": "


", - "date_create": "2025-03-18 13:22:27" - }, - { - "id": 227725, - "author_id": [ - 5144, - "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL" - ], - "role": "Client", - "type": "Question", - "date": "2025-03-18 13:18:31", - "email_from": "CARVAL Dominique ", - "subject": "changement nom centrale d'enrobage", - "body": "Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites)" - }, - { - "id": 227731, - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "role": "Support", - "type": "Réponse", - "date": "2025-03-18 14:18:51", - "email_from": "support@cbao.fr", - "subject": "Re: [T11067] - changement nom centrale d'enrobage", - "body": "Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire." - } -] \ No newline at end of file diff --git a/output/ticket_T11067/questions_reponses.md b/output/ticket_T11067/questions_reponses.md deleted file mode 100644 index 7f56260..0000000 --- a/output/ticket_T11067/questions_reponses.md +++ /dev/null @@ -1,16 +0,0 @@ -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| -| **Client**: Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites) | **Support**: Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire. | - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 \ No newline at end of file diff --git a/output/ticket_T11067/rapport/ticket_analysis.json b/output/ticket_T11067/rapport/ticket_analysis.json deleted file mode 100644 index 5ebf9ee..0000000 --- a/output/ticket_T11067/rapport/ticket_analysis.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "entries": [ - { - "timestamp": "2025-04-01 17:08:06", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T11067/attachments/144796_image.png", - "response": { - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalités techniques liées au problème décrit dans le ticket.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:08:06", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T11067/attachments/144794_image004.jpg", - "response": { - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalités techniques liées au problème décrit dans le ticket.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:08:06", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T11067/attachments/144792_image003.png", - "response": { - "pertinente": false, - "type_image": "logo", - "description": "Cette image semble être un logo, une signature ou un élément graphique décoratif, et n'est pas pertinente dans un contexte technique.", - "confiance": 90, - "justification": "L'image ne contient pas d'éléments techniques utiles pour résoudre un problème.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:08:06", - "action": "analyze_image", - "agent": "AgentAnalyseImage", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.3, - "max_tokens": 1024, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques.\nVotre rôle est d'examiner des captures d'écran ou des photos liées à des problèmes techniques et de:\n1. Décrire précisément le contenu de l'image\n2. Identifier les éléments techniques visibles (erreurs, interfaces, configurations)\n3. Extraire tout texte visible (messages d'erreur, logs, indicateurs)\n\nSoyez précis et factuel dans votre analyse.\n" - }, - "image_path": "output/ticket_T11067/attachments/144796_image.png", - "response": "{\n \"pertinente\": true,\n \"type_image\": \"capture_ecran\",\n \"description\": \"Capture d'\\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.\",\n \"confiance\": 85,\n \"justification\": \"L'image montre clairement une interface utilisateur avec des fonctionnalit\\u00e9s techniques li\\u00e9es au probl\\u00e8me d\\u00e9crit dans le ticket.\"\n}", - "tokens": { - "prompt_tokens": 84, - "completion_tokens": 150, - "total_tokens": 234 - } - }, - { - "timestamp": "2025-04-01 17:08:06", - "action": "analyze_image", - "agent": "AgentAnalyseImage", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.3, - "max_tokens": 1024, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques.\nVotre rôle est d'examiner des captures d'écran ou des photos liées à des problèmes techniques et de:\n1. Décrire précisément le contenu de l'image\n2. Identifier les éléments techniques visibles (erreurs, interfaces, configurations)\n3. Extraire tout texte visible (messages d'erreur, logs, indicateurs)\n\nSoyez précis et factuel dans votre analyse.\n" - }, - "image_path": "output/ticket_T11067/attachments/144794_image004.jpg", - "response": "{\n \"pertinente\": true,\n \"type_image\": \"capture_ecran\",\n \"description\": \"Capture d'\\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.\",\n \"confiance\": 85,\n \"justification\": \"L'image montre clairement une interface utilisateur avec des fonctionnalit\\u00e9s techniques li\\u00e9es au probl\\u00e8me d\\u00e9crit dans le ticket.\"\n}", - "tokens": { - "prompt_tokens": 84, - "completion_tokens": 150, - "total_tokens": 234 - } - }, - { - "timestamp": "2025-04-01 17:08:06", - "action": "extract_questions_reponses", - "agent": "AgentQuestionReponse", - "llm": { - "model": "mistral-medium" - }, - "parametres_llm": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "response": { - "success": true, - "messages_analyses": [ - { - "id": "ticket_info", - "date": "", - "role": "Client", - "type": "Question", - "contenu": "TICKET T11067: changement nom centrale d'enrobage. DESCRIPTION:" - }, - { - "id": 227725, - "date": "2025-03-18 13:18:31", - "role": "Client", - "type": "Question", - "contenu": "Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites)" - }, - { - "id": 227731, - "date": "2025-03-18 14:18:51", - "role": "Support", - "type": "Information", - "contenu": "Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire." - } - ], - "paires_qr": [ - { - "numero": "1", - "question": { - "role": "Client", - "contenu": "Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites)" - }, - "reponse": { - "role": "Support", - "contenu": "Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire." - } - } - ], - "nb_questions": 1, - "nb_reponses": 1, - "tableau_md": "# Analyse des Questions et Réponses\n\n| Question | Réponse |\n|---------|---------|\n| **Client**: Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites) | **Support**: Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire. |\n\n## Paramètres LLM utilisés\n\n- **Type de LLM**: Mistral\n- **Modèle**: mistral-medium\n- **Température**: 0.3\n- **Tokens max**: 2000\n\n**Paramètres modifiés durant l'analyse:**\n- **temperature**: 0.3\n- **max_tokens**: 2000", - "parametres_llm": { - "agent": "AgentQuestionReponse", - "llm_type": "Mistral", - "parametres": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n", - "temperature": 0.3, - "max_tokens": 2000 - } - } - } - } - ] -} \ No newline at end of file diff --git a/output/ticket_T11067/rapport/ticket_analysis.md b/output/ticket_T11067/rapport/ticket_analysis.md deleted file mode 100644 index 8942a15..0000000 --- a/output/ticket_T11067/rapport/ticket_analysis.md +++ /dev/null @@ -1,157 +0,0 @@ -# Analyse de ticket de support - -## Statistiques - -- Images analysées: 3 (2 pertinentes) -- Questions identifiées: 1 -- Réponses identifiées: 1 - - -## Paramètres LLM par agent - -### Agent de filtrage d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.2 -- **Tokens max**: 500 - -### Agent d'analyse d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.3 -- **Tokens max**: 1024 - -### Agent d'extraction questions-réponses - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - - -## Journal d'actions - -### 2025-04-01 17:08:06 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 144796_image.png -**Résultat**: Pertinente -**Type**: capture_ecran -**Description**: Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:08:06 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 144794_image004.jpg -**Résultat**: Pertinente -**Type**: capture_ecran -**Description**: Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:08:06 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 144792_image003.png -**Résultat**: Non pertinente -**Type**: logo -**Description**: Cette image semble être un logo, une signature ou un élément graphique décoratif, et n'est pas pertinente dans un contexte technique. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:08:06 - AgentAnalyseImage (pixtral-12b-2409) -**Action**: analyze_image -**Image analysée**: 144796_image.png - -**Analyse**: -``` -{ - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalit\u00e9s techniques li\u00e9es au probl\u00e8me d\u00e9crit dans le ticket." -} -``` - -**Paramètres LLM utilisés:** -- **model**: pixtral-12b-2409 -- **temperature**: 0.3 -- **max_tokens**: 1024 -- **top_p**: 1.0 - -**Tokens utilisés**: -- Prompt: 84 -- Completion: 150 -- Total: 234 - ---- - -### 2025-04-01 17:08:06 - AgentAnalyseImage (pixtral-12b-2409) -**Action**: analyze_image -**Image analysée**: 144794_image004.jpg - -**Analyse**: -``` -{ - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalit\u00e9s techniques li\u00e9es au probl\u00e8me d\u00e9crit dans le ticket." -} -``` - -**Paramètres LLM utilisés:** -- **model**: pixtral-12b-2409 -- **temperature**: 0.3 -- **max_tokens**: 1024 -- **top_p**: 1.0 - -**Tokens utilisés**: -- Prompt: 84 -- Completion: 150 -- Total: 234 - ---- - -### 2025-04-01 17:08:06 - AgentQuestionReponse (mistral-medium) -**Action**: extract_questions_reponses -**Questions**: 1 -**Réponses**: 1 - - -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| -| **Client**: Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites) | **Support**: Bonjour , Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier. Je reste à votre entière disposition pour toute information complémentaire. | - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 - -**Paramètres LLM utilisés:** -- **model**: mistral-medium -- **temperature**: 0.3 -- **max_tokens**: 2000 -- **top_p**: 1.0 - ---- diff --git a/output/ticket_T11067/ticket_info.json b/output/ticket_T11067/ticket_info.json deleted file mode 100644 index 50f63b1..0000000 --- a/output/ticket_T11067/ticket_info.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "id": 11046, - "active": true, - "name": "changement nom centrale d'enrobage", - "description": "


", - "sequence": 10, - "stage_id": [ - 32, - "En attente d'infos / retours" - ], - "kanban_state": "normal", - "create_date": "2025-03-18 13:22:27", - "write_date": "2025-03-18 14:19:28", - "date_start": "2025-03-18 13:22:28", - "date_end": false, - "date_assign": "2025-03-18 13:42:04", - "date_deadline": "2025-04-02", - "date_last_stage_update": "2025-03-18 14:19:28", - "project_id": [ - 3, - "Demandes" - ], - "notes": false, - "planned_hours": 0.0, - "user_id": [ - 32, - "Romuald GRUSON" - ], - "partner_id": [ - 5144, - "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL" - ], - "company_id": [ - 1, - "CBAO S.A.R.L." - ], - "color": 0, - "displayed_image_id": false, - "parent_id": false, - "child_ids": [], - "email_from": "CARVAL Dominique ", - "email_cc": "", - "working_hours_open": 0.0, - "working_hours_close": 0.0, - "working_days_open": 0.0, - "working_days_close": 0.0, - "website_message_ids": [ - 227731, - 227725 - ], - "remaining_hours": 0.0, - "effective_hours": 0.0, - "total_hours_spent": 0.0, - "progress": 0.0, - "subtask_effective_hours": 0.0, - "timesheet_ids": [], - "priority": "0", - "code": "T11067", - "milestone_id": false, - "sale_line_id": false, - "sale_order_id": false, - "billable_type": "no", - "activity_ids": [], - "message_follower_ids": [ - 89590, - 89592, - 89593 - ], - "message_ids": [ - 227733, - 227732, - 227731, - 227730, - 227728, - 227726, - 227725, - 227724 - ], - "message_main_attachment_id": [ - 144792, - "image003.png" - ], - "failed_message_ids": [], - "rating_ids": [], - "rating_last_value": 0.0, - "access_token": "3295983b-a3aa-4d8c-817d-2332829ca264", - "create_uid": [ - 1, - "OdooBot" - ], - "write_uid": [ - 32, - "Romuald GRUSON" - ], - "x_CBAO_windows_maj_ID": false, - "x_CBAO_version_signalement": false, - "x_CBAO_version_correction": false, - "x_CBAO_DateCorrection": false, - "x_CBAO_Scoring_Facilite": 0, - "x_CBAO_Scoring_Importance": 0, - "x_CBAO_Scoring_Urgence": 0, - "x_CBAO_Scoring_Incidence": 0, - "x_CBAO_Scoring_Resultat": 0, - "x_CBAO_InformationsSup": false, - "kanban_state_label": "En cours", - "subtask_planned_hours": 0.0, - "manager_id": [ - 22, - "Fabien LAFAY" - ], - "user_email": "romuald@mail.cbao.fr", - "attachment_ids": [], - "legend_blocked": "Bloqué", - "legend_done": "Prêt pour la prochaine étape", - "legend_normal": "En cours", - "subtask_project_id": [ - 3, - "Demandes" - ], - "subtask_count": 0, - "analytic_account_active": true, - "allow_timesheets": true, - "use_milestones": false, - "show_time_control": "start", - "is_project_map_empty": true, - "activity_state": false, - "activity_user_id": false, - "activity_type_id": false, - "activity_date_deadline": false, - "activity_summary": false, - "message_is_follower": false, - "message_unread": false, - "message_unread_counter": 0, - "message_needaction": false, - "message_needaction_counter": 0, - "message_has_error": false, - "message_has_error_counter": 0, - "message_attachment_count": 3, - "rating_last_feedback": false, - "rating_count": 0, - "access_url": "/my/task/11046", - "access_warning": "", - "display_name": "[T11067] changement nom centrale d'enrobage", - "__last_update": "2025-03-18 14:19:28" -} \ No newline at end of file diff --git a/output/ticket_T11094/attachments/144918_image.png b/output/ticket_T11094/attachments/144918_image.png deleted file mode 100644 index e3fdf376cfab175a45b0e250988cc1aac8d5f7f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 115046 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�!|%=s^+fSe=4z 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 z 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 t5c{B2;Olgx-lmDHm^A#{;(w}Y diff --git a/output/ticket_T11094/attachments_info.json b/output/ticket_T11094/attachments_info.json deleted file mode 100644 index 74819b5..0000000 --- a/output/ticket_T11094/attachments_info.json +++ /dev/null @@ -1,9 +0,0 @@ -[ - { - "id": 144918, - "name": "image.png", - "mimetype": "image/png", - "create_date": "2025-03-21 14:50:36", - "file_path": "output/ticket_T11094/attachments/144918_image.png" - } -] \ No newline at end of file diff --git a/output/ticket_T11094/messages.json b/output/ticket_T11094/messages.json deleted file mode 100644 index 06d71e6..0000000 --- a/output/ticket_T11094/messages.json +++ /dev/null @@ -1,25 +0,0 @@ -[ - { - "id": "ticket_info", - "name": "Calcul de la masse volumique", - "code": "T11094", - "description": "

Point particulier :

  • Essais :E2025-0002
  • Une norme :NF EN 12697-6
  • Multi laboratoire :Rouen labo sol
  • Le cas est bloquant

Description du problème :

Bonjour,\r\nEst-il possible de vérifier pourquoi le calcul de ma masse volumique ne fonctionne pas.\r\n\r\nCordialement

", - "date_create": "2025-03-21 07:54:57", - "role": "system", - "type": "contexte", - "body": "TICKET T11094: Calcul de la masse volumique.\n\nDESCRIPTION:

Point particulier :

  • Essais :E2025-0002
  • Une norme :NF EN 12697-6
  • Multi laboratoire :Rouen labo sol
  • Le cas est bloquant

Description du problème :

Bonjour,\r\nEst-il possible de vérifier pourquoi le calcul de ma masse volumique ne fonctionne pas.\r\n\r\nCordialement

" - }, - { - "id": "228106", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "role": "Support", - "type": "Réponse", - "date": "2025-03-21 14:50:37", - "email_from": "support@cbao.fr", - "subject": "Re: [T11094] - Calcul de la masse volumique", - "body": "Bonjour , Pour obtenir une valeur, il est nécessaire de renseigner la \"masse volumique du produit d'étanchéité\". Vous trouverez une capture d'écran ci-dessous pour vous guider dans cette démarche. Je reste à votre entière disposition pour toute information complémentaire." - } -] \ No newline at end of file diff --git a/output/ticket_T11094/messages.json.backup b/output/ticket_T11094/messages.json.backup deleted file mode 100644 index f5bdefd..0000000 --- a/output/ticket_T11094/messages.json.backup +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "id": 228108, - "body": "", - "date": "2025-03-21 14:50:41", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "email_from": "\"Romuald GRUSON\" ", - "subject": false, - "parent_id": [ - 228083, - "[T11094] Calcul de la masse volumique" - ] - }, - { - "id": 228107, - "body": "", - "date": "2025-03-21 14:50:41", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "email_from": "\"Romuald GRUSON\" ", - "subject": false, - "parent_id": false - }, - { - "id": 228106, - "body": "

Bonjour,

Pour obtenir une valeur, il est nécessaire de renseigner la \"masse volumique du produit d'étanchéité\". Vous trouverez une capture d'écran ci-dessous pour vous guider dans cette démarche.

\"image.png\"

Je reste à votre entière disposition pour toute information complémentaire.

Cordialement,

---

Support technique
 

\n

\"CBAO

\n

Afin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance technique à support@cbao.fr
L'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.

Confidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport avec la communication du contenu des informations est strictement interdit.

", - "date": "2025-03-21 14:50:37", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "email_from": "support@cbao.fr", - "subject": "Re: [T11094] - Calcul de la masse volumique", - "parent_id": [ - 228083, - "[T11094] Calcul de la masse volumique" - ] - }, - { - "id": 228091, - "body": "", - "date": "2025-03-21 10:57:58", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "email_from": "\"Romuald GRUSON\" ", - "subject": false, - "parent_id": false - }, - { - "id": 228086, - "body": "", - "date": "2025-03-21 08:20:00", - "author_id": [ - 28961, - "Fabien LAFAY" - ], - "email_from": "\"Fabien LAFAY\" ", - "subject": false, - "parent_id": [ - 228083, - "[T11094] Calcul de la masse volumique" - ] - }, - { - "id": 228083, - "body": "", - "date": "2025-03-21 07:54:57", - "author_id": [ - 30810, - "Support Robot" - ], - "email_from": "\"Support Robot\" ", - "subject": false, - "parent_id": false - } -] \ No newline at end of file diff --git a/output/ticket_T11094/questions_reponses.md b/output/ticket_T11094/questions_reponses.md deleted file mode 100644 index 1774812..0000000 --- a/output/ticket_T11094/questions_reponses.md +++ /dev/null @@ -1,15 +0,0 @@ -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 \ No newline at end of file diff --git a/output/ticket_T11094/rapport/ticket_analysis.json b/output/ticket_T11094/rapport/ticket_analysis.json deleted file mode 100644 index ea72403..0000000 --- a/output/ticket_T11094/rapport/ticket_analysis.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "entries": [ - { - "timestamp": "2025-04-01 17:18:01", - "action": "filter_image", - "agent": "AgentFiltreImages", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "image_path": "output/ticket_T11094/attachments/144918_image.png", - "response": { - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalités techniques liées au problème décrit dans le ticket.", - "parametres_llm": { - "agent": "AgentFiltreImages", - "llm_type": "Pixtral", - "parametres": { - "model": "pixtral-12b-2409", - "temperature": 0.2, - "max_tokens": 500, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse d'images techniques. Votre mission est de déterminer\nsi une image est pertinente dans un contexte de support technique ou non.\n\nImages PERTINENTES:\n- Captures d'écran montrant des problèmes, erreurs, bugs\n- Photos d'équipements avec problèmes visibles\n- Schémas techniques ou diagrammes\n- Graphiques de données techniques\n\nImages NON PERTINENTES:\n- Logos d'entreprise\n- Signatures ou avatars\n- Icônes ou boutons isolés\n- Bannières décoratives, séparateurs\n- Images génériques sans information technique\n", - "temperature": 0.2, - "max_tokens": 500 - } - } - } - }, - { - "timestamp": "2025-04-01 17:18:01", - "action": "analyze_image", - "agent": "AgentAnalyseImage", - "llm": { - "model": "pixtral-12b-2409" - }, - "parametres_llm": { - "model": "pixtral-12b-2409", - "temperature": 0.3, - "max_tokens": 1024, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse d'images techniques.\nVotre rôle est d'examiner des captures d'écran ou des photos liées à des problèmes techniques et de:\n1. Décrire précisément le contenu de l'image\n2. Identifier les éléments techniques visibles (erreurs, interfaces, configurations)\n3. Extraire tout texte visible (messages d'erreur, logs, indicateurs)\n\nSoyez précis et factuel dans votre analyse.\n" - }, - "image_path": "output/ticket_T11094/attachments/144918_image.png", - "response": "{\n \"pertinente\": true,\n \"type_image\": \"capture_ecran\",\n \"description\": \"Capture d'\\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.\",\n \"confiance\": 85,\n \"justification\": \"L'image montre clairement une interface utilisateur avec des fonctionnalit\\u00e9s techniques li\\u00e9es au probl\\u00e8me d\\u00e9crit dans le ticket.\"\n}", - "tokens": { - "prompt_tokens": 162, - "completion_tokens": 150, - "total_tokens": 312 - } - }, - { - "timestamp": "2025-04-01 17:18:01", - "action": "extract_questions_reponses", - "agent": "AgentQuestionReponse", - "llm": { - "model": "mistral-medium" - }, - "parametres_llm": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "response": { - "success": true, - "messages_analyses": [ - { - "id": 228106, - "date": "2025-03-21 14:50:37", - "role": "Support", - "type": "Information", - "contenu": "Bonjour , Pour obtenir une valeur, il est nécessaire de renseigner la \"masse volumique du produit d'étanchéité\". Vous trouverez une capture d'écran ci-dessous pour vous guider dans cette démarche. Je reste à votre entière disposition pour toute information complémentaire." - } - ], - "paires_qr": [], - "nb_questions": 0, - "nb_reponses": 0, - "tableau_md": "# Analyse des Questions et Réponses\n\n| Question | Réponse |\n|---------|---------|\n\n## Paramètres LLM utilisés\n\n- **Type de LLM**: Mistral\n- **Modèle**: mistral-medium\n- **Température**: 0.3\n- **Tokens max**: 2000\n\n**Paramètres modifiés durant l'analyse:**\n- **temperature**: 0.3\n- **max_tokens**: 2000", - "parametres_llm": { - "agent": "AgentQuestionReponse", - "llm_type": "Mistral", - "parametres": { - "model": "mistral-medium", - "temperature": 0.3, - "max_tokens": 2000, - "top_p": 1.0, - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n" - }, - "parametres_modifies": { - "system_prompt": "\nVous êtes un expert en analyse de conversations de support technique.\n\nVotre mission est d'identifier avec précision:\n1. Le rôle de chaque intervenant (client ou support technique)\n2. La nature de chaque message (question, réponse, information additionnelle)\n3. Le contenu essentiel de chaque message en éliminant les formules de politesse,\n signatures, mentions légales et autres éléments non pertinents\n\nPour l'identification client/support:\n- Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email\n comme @cbao.fr, @odoo.com, mentions \"support technique\", etc.\n- Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions\n\nPour la classification en question/réponse:\n- Questions: Demandes explicites (avec \"?\"), demandes implicites de résolution\n de problèmes, descriptions de bugs ou dysfonctionnements\n- Réponses: Explications techniques, solutions proposées, instructions fournies\n par le support\n\nConcentrez-vous uniquement sur le contenu technique utile en ignorant tous les\néléments superflus qui n'apportent pas d'information sur le problème ou sa solution.\n", - "temperature": 0.3, - "max_tokens": 2000 - } - } - } - } - ] -} \ No newline at end of file diff --git a/output/ticket_T11094/rapport/ticket_analysis.md b/output/ticket_T11094/rapport/ticket_analysis.md deleted file mode 100644 index f4ecff6..0000000 --- a/output/ticket_T11094/rapport/ticket_analysis.md +++ /dev/null @@ -1,104 +0,0 @@ -# Analyse de ticket de support - -## Statistiques - -- Images analysées: 1 (1 pertinentes) -- Questions identifiées: 0 -- Réponses identifiées: 0 - - -## Paramètres LLM par agent - -### Agent de filtrage d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.2 -- **Tokens max**: 500 - -### Agent d'analyse d'images - -- **Type de LLM**: Pixtral -- **Modèle**: pixtral-12b-2409 -- **Température**: 0.3 -- **Tokens max**: 1024 - -### Agent d'extraction questions-réponses - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - - -## Journal d'actions - -### 2025-04-01 17:18:01 - AgentFiltreImages (pixtral-12b-2409) -**Action**: filter_image -**Image**: 144918_image.png -**Résultat**: Pertinente -**Type**: capture_ecran -**Description**: Capture d'écran d'une interface montrant le formulaire de modification d'une centrale d'enrobage. - -**Paramètres LLM utilisés:** -- Température: 0.2 - ---- - -### 2025-04-01 17:18:01 - AgentAnalyseImage (pixtral-12b-2409) -**Action**: analyze_image -**Image analysée**: 144918_image.png - -**Analyse**: -``` -{ - "pertinente": true, - "type_image": "capture_ecran", - "description": "Capture d'\u00e9cran d'une interface montrant le formulaire de modification d'une centrale d'enrobage.", - "confiance": 85, - "justification": "L'image montre clairement une interface utilisateur avec des fonctionnalit\u00e9s techniques li\u00e9es au probl\u00e8me d\u00e9crit dans le ticket." -} -``` - -**Paramètres LLM utilisés:** -- **model**: pixtral-12b-2409 -- **temperature**: 0.3 -- **max_tokens**: 1024 -- **top_p**: 1.0 - -**Tokens utilisés**: -- Prompt: 162 -- Completion: 150 -- Total: 312 - ---- - -### 2025-04-01 17:18:01 - AgentQuestionReponse (mistral-medium) -**Action**: extract_questions_reponses -**Questions**: 0 -**Réponses**: 0 - - -# Analyse des Questions et Réponses - -| Question | Réponse | -|---------|---------| - -## Paramètres LLM utilisés - -- **Type de LLM**: Mistral -- **Modèle**: mistral-medium -- **Température**: 0.3 -- **Tokens max**: 2000 - -**Paramètres modifiés durant l'analyse:** -- **temperature**: 0.3 -- **max_tokens**: 2000 - -**Paramètres LLM utilisés:** -- **model**: mistral-medium -- **temperature**: 0.3 -- **max_tokens**: 2000 -- **top_p**: 1.0 - ---- diff --git a/output/ticket_T11094/ticket_info.json b/output/ticket_T11094/ticket_info.json deleted file mode 100644 index 546ac82..0000000 --- a/output/ticket_T11094/ticket_info.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "id": 11073, - "active": true, - "name": "Calcul de la masse volumique", - "description": "

Point particulier :

  • Essais :E2025-0002
  • Une norme :NF EN 12697-6
  • Multi laboratoire :Rouen labo sol
  • Le cas est bloquant

Description du problème :

Bonjour,\r\nEst-il possible de vérifier pourquoi le calcul de ma masse volumique ne fonctionne pas.\r\n\r\nCordialement

", - "sequence": 10, - "stage_id": [ - 32, - "En attente d'infos / retours" - ], - "kanban_state": "normal", - "create_date": "2025-03-21 07:54:57", - "write_date": "2025-03-21 14:50:41", - "date_start": "2025-03-21 07:54:57", - "date_end": false, - "date_assign": "2025-03-21 10:57:58", - "date_deadline": "2025-04-05", - "date_last_stage_update": "2025-03-21 14:50:41", - "project_id": [ - 3, - "Demandes" - ], - "notes": false, - "planned_hours": 0.0, - "user_id": [ - 32, - "Romuald GRUSON" - ], - "partner_id": [ - 29954, - "INFRANEO - PANTIN, MickaĂ«l RESSE" - ], - "company_id": [ - 1, - "CBAO S.A.R.L." - ], - "color": 0, - "displayed_image_id": false, - "parent_id": false, - "child_ids": [], - "email_from": "m.resse@infraneo.com", - "email_cc": "", - "working_hours_open": 1.9661111111111111, - "working_hours_close": 0.0, - "working_days_open": 0.0819212962962963, - "working_days_close": 0.0, - "website_message_ids": [ - 228106 - ], - "remaining_hours": 0.0, - "effective_hours": 0.0, - "total_hours_spent": 0.0, - "progress": 0.0, - "subtask_effective_hours": 0.0, - "timesheet_ids": [], - "priority": "3", - "code": "T11094", - "milestone_id": false, - "sale_line_id": false, - "sale_order_id": false, - "billable_type": "no", - "activity_ids": [], - "message_follower_ids": [ - 89735, - 89736, - 89740, - 89747 - ], - "message_ids": [ - 228108, - 228107, - 228106, - 228091, - 228086, - 228083 - ], - "message_main_attachment_id": [ - 144918, - "image.png" - ], - "failed_message_ids": [], - "rating_ids": [], - "rating_last_value": 0.0, - "access_token": "bdbe88e0-f951-416f-bec8-9bfda0441405", - "create_uid": [ - 28, - "Support Robot" - ], - "write_uid": [ - 32, - "Romuald GRUSON" - ], - "x_CBAO_windows_maj_ID": "", - "x_CBAO_version_signalement": "20250318", - "x_CBAO_version_correction": "", - "x_CBAO_DateCorrection": false, - "x_CBAO_Scoring_Facilite": 0, - "x_CBAO_Scoring_Importance": 0, - "x_CBAO_Scoring_Urgence": 0, - "x_CBAO_Scoring_Incidence": 0, - "x_CBAO_Scoring_Resultat": 0, - "x_CBAO_InformationsSup": false, - "kanban_state_label": "En cours", - "subtask_planned_hours": 0.0, - "manager_id": [ - 22, - "Fabien LAFAY" - ], - "user_email": "romuald@mail.cbao.fr", - "attachment_ids": [], - "legend_blocked": "BloquĂ©", - "legend_done": "PrĂŞt pour la prochaine Ă©tape", - "legend_normal": "En cours", - "subtask_project_id": [ - 3, - "Demandes" - ], - "subtask_count": 0, - "analytic_account_active": true, - "allow_timesheets": true, - "use_milestones": false, - "show_time_control": "start", - "is_project_map_empty": true, - "activity_state": false, - "activity_user_id": false, - "activity_type_id": false, - "activity_date_deadline": false, - "activity_summary": false, - "message_is_follower": false, - "message_unread": false, - "message_unread_counter": 0, - "message_needaction": false, - "message_needaction_counter": 0, - "message_has_error": false, - "message_has_error_counter": 0, - "message_attachment_count": 1, - "rating_last_feedback": false, - "rating_count": 0, - "access_url": "/my/task/11073", - "access_warning": "", - "display_name": "[T11094] Calcul de la masse volumique", - "__last_update": "2025-03-21 14:50:41" -} \ No newline at end of file diff --git a/output_processed/ticket_T0167/messages.json b/output_processed/ticket_T0167/messages.json deleted file mode 100644 index 46ca034..0000000 --- a/output_processed/ticket_T0167/messages.json +++ /dev/null @@ -1,38 +0,0 @@ -[ - { - "id": "ticket_info", - "name": "Pb d'affaire/chantier/partie dans un programme d'essai", - "code": "T0167", - "description": "Je viens vers toi car Mr NOVO m’a fait remonter un lĂ©ger beug sur le numĂ©ro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas Ă  mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussĂ©e cĂ´tĂ© giberville » comme stipulĂ© dans le numĂ©ro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE. J’ai essayĂ© de modifiĂ© la partie mais je n’y arrive pas.", - "date_create": "2020-04-27 06:21:36", - "role": "system", - "type": "contexte", - "body": "TICKET T0167: Pb d'affaire/chantier/partie dans un programme d'essai.\n\nDESCRIPTION: Je viens vers toi car Mr NOVO m’a fait remonter un lĂ©ger beug sur le numĂ©ro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas Ă  mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussĂ©e cĂ´tĂ© giberville » comme stipulĂ© dans le numĂ©ro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE. J’ai essayĂ© de modifiĂ© la partie mais je n’y arrive pas." - }, - { - "id": "ticket_info", - "author_id": [ - 0, - "" - ], - "role": "Client", - "type": "Question", - "date": "", - "email_from": "", - "subject": "", - "body": "TICKET T0167: Pb d'affaire/chantier/partie dans un programme d'essai. DESCRIPTION: Je viens vers toi car Mr NOVO m’a fait remonter un lĂ©ger beug sur le numĂ©ro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas Ă  mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussĂ©e cĂ´tĂ© giberville » comme stipulĂ© dans le numĂ©ro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE. J’ai essayĂ© de modifiĂ© la partie mais je n’y arrive pas." - }, - { - "id": "11333", - "author_id": [ - 10288, - "CBAO S.A.R.L., Youness BENDEQ" - ], - "role": "Support", - "type": "RĂ©ponse", - "date": "2020-04-27 06:20:22", - "email_from": "Youness BENDEQ ", - "subject": "Pb d'affaire/chantier/partie dans un programme d'essai", - "body": "-------- Message transfĂ©rĂ© -------- Sujet : De retour ! Date : Mon, 20 Apr 2020 14:52:05 +0000 De : LENEVEU Guillaume Pour : Youness BENDEQ Bonjour Youness, J’espère que tu vas bien ainsi que toute l’équipe BRG-LAB. Je viens vers toi car Mr NOVO m’a fait remonter un lĂ©ger beug sur le numĂ©ro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas Ă  mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussĂ©e cĂ´tĂ© giberville » comme stipulĂ© dans le numĂ©ro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE. J’ai essayĂ© de modifiĂ© la partie mais je n’y arrive pas. Merci de ta rĂ©ponse. Bonne fin de journĂ©e." - } -] \ No newline at end of file diff --git a/output_processed/ticket_T0167/pretraitement_rapport.json b/output_processed/ticket_T0167/pretraitement_rapport.json deleted file mode 100644 index 35a848a..0000000 --- a/output_processed/ticket_T0167/pretraitement_rapport.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "ticket_id": "ticket_T0167", - "fichiers_generes": [ - "ticket_info.json", - "messages.json" - ], - "erreurs": [] -} \ No newline at end of file diff --git a/output_processed/ticket_T0167/ticket_info.json b/output_processed/ticket_T0167/ticket_info.json deleted file mode 100644 index 55bed98..0000000 --- a/output_processed/ticket_T0167/ticket_info.json +++ /dev/null @@ -1,145 +0,0 @@ -{ - "id": 179, - "active": true, - "name": "Pb d'affaire/chantier/partie dans un programme d'essai", - "description": "Je viens vers toi car Mr NOVO m’a fait remonter un lĂ©ger beug sur le numĂ©ro d’échantillon B2020-0001 (Voir PJ). En effet, il n’arrive pas Ă  mettre le nom de la partie dans la partie ( en rouge sur la PJ). Il faudrait mettre « joint de chaussĂ©e cĂ´tĂ© giberville » comme stipulĂ© dans le numĂ©ro d’affaire -> 20017 SETR -> LIAISON RD403 – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE GIBERVILLE. J’ai essayĂ© de modifiĂ© la partie mais je n’y arrive pas.", - "sequence": 22, - "stage_id": [ - 8, - "ClĂ´turĂ©" - ], - "kanban_state": "normal", - "create_date": "2020-04-27 06:21:36", - "write_date": "2024-10-03 13:10:50", - "date_start": "2020-04-20 14:52:00", - "date_end": false, - "date_assign": "2020-04-27 07:15:48", - "date_deadline": false, - "date_last_stage_update": "2020-04-27 07:24:40", - "project_id": [ - 3, - "Demandes" - ], - "notes": false, - "planned_hours": 0.0, - "user_id": [ - 9, - "Youness BENDEQ" - ], - "partner_id": [ - 8504, - "CONSEIL DEPARTEMENTAL DU CALVADOS (14), Guillaume LENEVEU" - ], - "company_id": [ - 1, - "CBAO S.A.R.L." - ], - "color": 0, - "displayed_image_id": false, - "parent_id": false, - "child_ids": [], - "email_from": "guillaume.leneveu@calvados.fr", - "email_cc": "", - "working_hours_open": 0.0, - "working_hours_close": 0.0, - "working_days_open": 0.0, - "working_days_close": 0.0, - "website_message_ids": [ - 11333 - ], - "remaining_hours": -0.5, - "effective_hours": 0.5, - "total_hours_spent": 0.5, - "progress": 0.0, - "subtask_effective_hours": 0.0, - "timesheet_ids": [ - 51 - ], - "priority": "0", - "code": "T0167", - "milestone_id": false, - "sale_line_id": false, - "sale_order_id": false, - "billable_type": "no", - "activity_ids": [], - "message_follower_ids": [ - 10972 - ], - "message_ids": [ - 11346, - 11345, - 11344, - 11343, - 11342, - 11335, - 11334, - 11333, - 11332 - ], - "message_main_attachment_id": [ - 32380, - "image001.png" - ], - "failed_message_ids": [], - "rating_ids": [], - "rating_last_value": 0.0, - "access_token": "cd4fbf5c-27d3-48ed-8c9b-c07f20c3e2d4", - "create_uid": [ - 1, - "OdooBot" - ], - "write_uid": [ - 1, - "OdooBot" - ], - "x_CBAO_windows_maj_ID": false, - "x_CBAO_version_signalement": false, - "x_CBAO_version_correction": false, - "x_CBAO_DateCorrection": false, - "x_CBAO_Scoring_Facilite": 0, - "x_CBAO_Scoring_Importance": 0, - "x_CBAO_Scoring_Urgence": 0, - "x_CBAO_Scoring_Incidence": 0, - "x_CBAO_Scoring_Resultat": 0, - "x_CBAO_InformationsSup": false, - "kanban_state_label": "En cours", - "subtask_planned_hours": 0.0, - "manager_id": [ - 22, - "Fabien LAFAY" - ], - "user_email": "youness@cbao.fr", - "attachment_ids": [], - "legend_blocked": "BloquĂ©", - "legend_done": "PrĂŞt pour la prochaine Ă©tape", - "legend_normal": "En cours", - "subtask_project_id": [ - 3, - "Demandes" - ], - "subtask_count": 0, - "analytic_account_active": true, - "allow_timesheets": true, - "use_milestones": false, - "show_time_control": "start", - "is_project_map_empty": true, - "activity_state": false, - "activity_user_id": false, - "activity_type_id": false, - "activity_date_deadline": false, - "activity_summary": false, - "message_is_follower": false, - "message_unread": false, - "message_unread_counter": 0, - "message_needaction": false, - "message_needaction_counter": 0, - "message_has_error": false, - "message_has_error_counter": 0, - "message_attachment_count": 2, - "rating_last_feedback": false, - "rating_count": 0, - "access_url": "/my/task/179", - "access_warning": "", - "display_name": "[T0167] Pb d'affaire/chantier/partie dans un programme d'essai", - "__last_update": "2024-10-03 13:10:50" -} \ No newline at end of file diff --git a/post_process.py b/post_process.py deleted file mode 100644 index bd12767..0000000 --- a/post_process.py +++ /dev/null @@ -1,982 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script de post-traitement pour amĂ©liorer les fichiers JSON avant analyse. -""" - -import os -import sys -import json -import re -import unicodedata -import shutil -from typing import Dict, List, Any, Optional - -def nettoyer_html(texte: str, debug: bool = False) -> str: - """ - Nettoie le contenu HTML en supprimant les balises et le formatage. - - Args: - texte: Texte HTML Ă  nettoyer - debug: Afficher des informations de dĂ©bogage pendant le nettoyage - - Returns: - Texte nettoyĂ© - """ - # VĂ©rifier et convertir l'entrĂ©e - if not texte: - return "" - - if not isinstance(texte, str): - try: - texte = str(texte) - except Exception as e: - print(f"AVERTISSEMENT: Impossible de convertir en texte: {e}") - return "" - - if debug: - print(f"Texte original ({len(texte)} caractères): {texte[:100]}...") - - # DĂ©tection de HTML - contient_html = bool(re.search(r'<[a-z]+[^>]*>', texte, re.IGNORECASE)) - if debug and contient_html: - print(f"Le texte contient du HTML, nettoyage nĂ©cessaire") - - # Supprimer les balises HTML - regex plus agressive pour capturer tous types de balises - try: - # Première passe - balises standard - texte_nettoye = re.sub(r']*>', ' ', texte, flags=re.IGNORECASE) - - # Deuxième passe - balises restantes, y compris les mal formĂ©es - texte_nettoye = re.sub(r'<[^>]*>', ' ', texte_nettoye) - - if debug and contient_html: - print(f"Après suppression des balises HTML: {texte_nettoye[:100]}...") - except Exception as e: - print(f"AVERTISSEMENT: Erreur lors du nettoyage HTML: {e}") - texte_nettoye = texte - - # Remplacer les rĂ©fĂ©rences aux images - try: - texte_nettoye = re.sub(r'\[Image:[^\]]+\]', '[Image]', texte_nettoye) - texte_nettoye = re.sub(r']+>', '[Image]', texte_nettoye, flags=re.IGNORECASE) - except Exception as e: - if debug: - print(f"AVERTISSEMENT: Erreur lors du traitement des images: {e}") - - # Supprimer les Ă©lĂ©ments courants non pertinents - patterns_a_supprimer = [ - r'Cordialement,[\s\S]*?$', - r'Bien cordialement,[\s\S]*?$', - r'Bonne rĂ©ception[\s\S]*?$', - r'Ă€ votre disposition[\s\S]*?$', - r'Support technique[\s\S]*?$', - r'L\'objectif du Support Technique[\s\S]*?$', - r'Notre service est ouvert[\s\S]*?$', - r'Dès rĂ©ception[\s\S]*?$', - r'ConfidentialitĂ©[\s\S]*?$', - r'Ce message Ă©lectronique[\s\S]*?$', - r'Droit Ă  la dĂ©connexion[\s\S]*?$', - r'Afin d\'assurer une meilleure traçabilitĂ©[\s\S]*?$', - r'tĂ©l\s*:\s*[\d\s\+]+', - r'mobile\s*:\s*[\d\s\+]+', - r'www\.[^\s]+\.[a-z]{2,3}', - ] - - try: - for pattern in patterns_a_supprimer: - texte_avant = texte_nettoye - texte_nettoye = re.sub(pattern, '', texte_nettoye, flags=re.IGNORECASE) - if debug and texte_avant != texte_nettoye: - print(f"Suppression de pattern '{pattern[:20]}...'") - except Exception as e: - # En cas d'Ă©chec des expressions rĂ©gulières, conserver le texte tel quel - if debug: - print(f"AVERTISSEMENT: Erreur lors de la suppression des patterns: {e}") - - try: - # Supprimer les lignes multiples vides - texte_nettoye = re.sub(r'\n\s*\n', '\n', texte_nettoye) - - # Supprimer les espaces multiples - texte_nettoye = re.sub(r'\s+', ' ', texte_nettoye) - except Exception as e: - if debug: - print(f"AVERTISSEMENT: Erreur lors du nettoyage des espaces: {e}") - - # Normaliser les caractères accentuĂ©s - try: - texte_nettoye = normaliser_accents(texte_nettoye) - except Exception as e: - print(f"AVERTISSEMENT: Erreur lors de la normalisation des accents: {e}") - - if debug: - print(f"Texte final ({len(texte_nettoye)} caractères): {texte_nettoye[:100]}...") - - return texte_nettoye.strip() - -def normaliser_accents(texte: str) -> str: - """ - Normalise les caractères accentuĂ©s pour Ă©viter les problèmes d'encodage. - - Args: - texte: Texte Ă  normaliser - - Returns: - Texte avec caractères accentuĂ©s normalisĂ©s - """ - # Si l'entrĂ©e n'est pas une chaĂ®ne, convertir en chaĂ®ne ou retourner vide - if not isinstance(texte, str): - if texte is None: - return "" - try: - texte = str(texte) - except: - return "" - - # Convertir les caractères spĂ©ciaux HTML (comme é) - special_chars = { - 'á': 'á', 'é': 'Ă©', 'í': 'Ă­', 'ó': 'Ăł', 'ú': 'Ăş', - 'Á': 'Ă', 'É': 'É', 'Í': 'ĂŤ', 'Ó': 'Ă“', 'Ú': 'Ăš', - 'à': 'Ă ', 'è': 'è', 'ì': 'ì', 'ò': 'ò', 'ù': 'Ăą', - 'À': 'Ă€', 'È': 'Ă', 'Ì': 'ĂŚ', 'Ò': 'Ă’', 'Ù': 'Ă™', - 'â': 'â', 'ê': 'ĂŞ', 'î': 'Ă®', 'ô': 'Ă´', 'û': 'Ă»', - 'Â': 'Ă‚', 'Ê': 'ĂŠ', 'Î': 'ĂŽ', 'Ô': 'Ă”', 'Û': 'Ă›', - 'ã': 'ĂŁ', '&etilde;': 'áş˝', 'ĩ': 'Ä©', 'õ': 'õ', 'ũ': 'Ĺ©', - 'Ã': 'Ă', '&Etilde;': 'Ẽ', 'Ĩ': 'Ĩ', 'Õ': 'Ă•', 'Ũ': 'Ũ', - 'ä': 'ä', 'ë': 'Ă«', 'ï': 'ĂŻ', 'ö': 'ö', 'ü': 'ĂĽ', - 'Ä': 'Ă„', 'Ë': 'Ă‹', 'Ï': 'ĂŹ', 'Ö': 'Ă–', 'Ü': 'Ăś', - 'ç': 'ç', 'Ç': 'Ç', 'ñ': 'ñ', 'Ñ': 'Ă‘', - ' ': ' ', '<': '<', '>': '>', '&': '&', '"': '"', ''': "'", - '€': '€', '©': '©', '®': '®', '™': '™' - } - - for html, char in special_chars.items(): - texte = texte.replace(html, char) - - # Normaliser les caractères composĂ©s (par exemple, e plus accent) - # Exemple: 'Ă©' qui pourrait ĂŞtre stockĂ© comme 'e' + accent combinant - return unicodedata.normalize('NFC', texte) - -def detecter_role(message: Dict[str, Any]) -> str: - """ - DĂ©tecte si un message provient du client ou du support. - - Args: - message: Dictionnaire contenant les informations du message - - Returns: - "Client" ou "Support" - """ - # VĂ©rifier le champ 'role' s'il existe dĂ©jĂ  - if "role" in message and message["role"] in ["Client", "Support"]: - return message["role"] - - # Indices de support dans l'email - domaines_support = ["@cbao.fr", "@odoo.com", "support@", "ticket.support"] - indices_nom_support = ["support", "cbao", "technique", "odoo"] - - email = message.get("email_from", "").lower() - # Nettoyer le format "Nom " - if "<" in email and ">" in email: - match = re.search(r'<([^>]+)>', email) - if match: - email = match.group(1).lower() - - # VĂ©rifier le domaine email - if any(domaine in email for domaine in domaines_support): - return "Support" - - # VĂ©rifier le nom d'auteur - auteur = "" - if "author_id" in message and isinstance(message["author_id"], list) and len(message["author_id"]) > 1: - auteur = str(message["author_id"][1]).lower() - - if any(indice in auteur for indice in indices_nom_support): - return "Support" - - # Par dĂ©faut, considĂ©rer comme client - return "Client" - -def transformer_messages(input_file: str, output_file: Optional[str] = None, debug: bool = False) -> None: - """ - Transforme le fichier messages.json en un format amĂ©liorĂ© pour l'analyse LLM. - - Args: - input_file: Chemin du fichier messages.json original - output_file: Chemin du fichier de sortie (par dĂ©faut, Ă©crase le fichier d'entrĂ©e) - debug: Activer le mode dĂ©bogage pour afficher plus d'informations - """ - if output_file is None: - output_file = input_file - - if debug: - print(f"Transformation du fichier {input_file} vers {output_file} (mode dĂ©bogage activĂ©)") - - try: - # Lire le fichier messages.json original - with open(input_file, 'r', encoding='utf-8') as f: - messages = json.load(f) - - # Trouver le rĂ©pertoire du ticket et charger les informations - ticket_dir = os.path.dirname(input_file) - ticket_info_path = os.path.join(ticket_dir, "ticket_info.json") - ticket_info = {} - - # Extraire le code du ticket du nom du rĂ©pertoire - try: - dir_name = os.path.basename(ticket_dir) - ticket_code = dir_name.replace("ticket_", "") if dir_name.startswith("ticket_") else dir_name - except Exception as e: - print(f"AVERTISSEMENT: Impossible d'extraire le code du ticket du rĂ©pertoire: {e}") - ticket_code = "UNKNOWN" - - # Charger les informations du ticket - if os.path.exists(ticket_info_path): - try: - with open(ticket_info_path, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - except Exception as e: - print(f"AVERTISSEMENT: Impossible de charger ticket_info.json: {e}") - - # CrĂ©er une version amĂ©liorĂ©e des messages - processed_messages = [] - - # Extraire et formater les informations du ticket de manière sĂ©curisĂ©e - ticket_name = "" - ticket_description = "" - ticket_date = "" - - try: - if ticket_info: - ticket_name = str(ticket_info.get("name", "")) if ticket_info.get("name") is not None else "" - ticket_description = str(ticket_info.get("description", "")) if ticket_info.get("description") is not None else "" - ticket_date = str(ticket_info.get("create_date", "")) if ticket_info.get("create_date") is not None else "" - ticket_code = str(ticket_info.get("code", ticket_code)) if ticket_info.get("code") is not None else ticket_code - except Exception as e: - print(f"AVERTISSEMENT: Problème lors de l'extraction des donnĂ©es du ticket: {e}") - - # Nettoyer la description pour Ă©liminer les balises HTML - ticket_description_nettoyee = nettoyer_html(ticket_description, debug=debug) - if debug: - print(f"Description originale: {ticket_description[:100]}...") - print(f"Description nettoyĂ©e: {ticket_description_nettoyee[:100]}...") - - # Ajouter les informations du ticket comme premier "message" - formatted_ticket_info = { - "id": "ticket_info", - "name": normaliser_accents(ticket_name) or f"Ticket {ticket_code}", - "code": ticket_code, - "description": ticket_description_nettoyee, - "date_create": ticket_date, - "role": "system", - "type": "contexte", - "body": f"TICKET {ticket_code}: {normaliser_accents(ticket_name)}.\n\nDESCRIPTION: {ticket_description_nettoyee or 'Aucune description disponible.'}" - } - processed_messages.append(formatted_ticket_info) - - # VĂ©rifier que messages est bien une liste - if not isinstance(messages, list): - print(f"AVERTISSEMENT: Le fichier messages.json ne contient pas une liste valide. Type: {type(messages)}") - messages = [] - - # Transformer chaque message - valid_messages = 0 - for msg in messages: - # VĂ©rifier que msg est un dictionnaire - if not isinstance(msg, dict): - print(f"AVERTISSEMENT: Message ignorĂ© car ce n'est pas un dictionnaire. Type: {type(msg)}") - continue - - # Ignorer les messages vides - body = msg.get("body", "") - if not body or not isinstance(body, str): - continue - - if debug: - contient_html = bool(re.search(r'<[a-z]+[^>]*>', body, re.IGNORECASE)) - if contient_html: - print(f"Message {msg.get('id', 'unknown')} contient du HTML") - - # DĂ©terminer le type (question/rĂ©ponse) basĂ© sur le rĂ´le - role = detecter_role(msg) - message_type = "Question" if role == "Client" else "RĂ©ponse" - - # Nettoyer le contenu de manière sĂ©curisĂ©e - contenu_nettoye = nettoyer_html(body, debug=debug) - if not contenu_nettoye: - if debug: - print(f"Message {msg.get('id', 'unknown')} ignorĂ© - contenu vide après nettoyage") - continue - - # Normaliser les champs textuels - email_from = normaliser_accents(msg.get("email_from", "")) - subject = normaliser_accents(msg.get("subject", "")) - - # CrĂ©er le message transformĂ© avec des valeurs sĂ©curisĂ©es - msg_id = msg.get("id", "") - if not msg_id: - msg_id = f"msg_{valid_messages+1}" - - # Convertir msg_id en string si ce n'est pas le cas - if not isinstance(msg_id, str): - try: - msg_id = str(msg_id) - except: - msg_id = f"msg_{valid_messages+1}" - - # RĂ©cupĂ©rer author_id de manière sĂ©curisĂ©e - author_id = msg.get("author_id", [0, ""]) - if not isinstance(author_id, list): - author_id = [0, ""] - - # RĂ©cupĂ©rer la date de manière sĂ©curisĂ©e - date = msg.get("date", "") - if not isinstance(date, str): - try: - date = str(date) - except: - date = "" - - processed_message = { - "id": msg_id, - "author_id": author_id, - "role": role, - "type": message_type, - "date": date, - "email_from": email_from, - "subject": subject, - "body": contenu_nettoye - } - - processed_messages.append(processed_message) - valid_messages += 1 - - # Trier par date (sauf le premier message qui est le contexte) - try: - processed_messages[1:] = sorted(processed_messages[1:], key=lambda x: x.get("date", "")) - except Exception as e: - print(f"AVERTISSEMENT: Impossible de trier les messages par date: {e}") - - # VĂ©rifier qu'il y a au moins un message valide en plus du contexte - if valid_messages == 0: - print("AVERTISSEMENT: Aucun message valide trouvĂ© après nettoyage.") - # Ajouter un message factice pour Ă©viter les erreurs - processed_messages.append({ - "id": "msg_default", - "role": "Client", - "type": "Question", - "date": formatted_ticket_info.get("date_create", ""), - "body": f"Problème concernant {formatted_ticket_info.get('name', 'ce ticket')}." - }) - - # Écrire le fichier transformĂ© - with open(output_file, 'w', encoding='utf-8') as f: - json.dump(processed_messages, f, indent=2, ensure_ascii=False) - - print(f"Transformation rĂ©ussie: {len(processed_messages)} messages traitĂ©s ({valid_messages} messages rĂ©els)") - - except Exception as e: - print(f"Erreur lors de la transformation des messages: {str(e)}") - import traceback - print(f"DĂ©tails: {traceback.format_exc()}") - raise - -def corriger_json_accents(input_file: str, output_file: Optional[str] = None) -> None: - """ - Corrige les problèmes d'accents dans un fichier JSON. - - Args: - input_file: Chemin du fichier JSON Ă  corriger - output_file: Chemin du fichier de sortie (par dĂ©faut, Ă©crase le fichier d'entrĂ©e) - """ - if output_file is None: - output_file = input_file - - try: - # Lire le fichier JSON - with open(input_file, 'r', encoding='utf-8') as f: - content = json.load(f) - - # Fonction rĂ©cursive pour normaliser tous les textes dans le JSON - def normaliser_json(obj): - if isinstance(obj, str): - return normaliser_accents(obj) - elif isinstance(obj, list): - return [normaliser_json(item) for item in obj] - elif isinstance(obj, dict): - return {k: normaliser_json(v) for k, v in obj.items()} - else: - return obj - - # Normaliser tout le contenu JSON - content_normalise = normaliser_json(content) - - # Écrire le fichier normalisĂ© - with open(output_file, 'w', encoding='utf-8') as f: - json.dump(content_normalise, f, indent=2, ensure_ascii=False) - - print(f"Correction des accents rĂ©ussie pour {os.path.basename(input_file)}") - - except Exception as e: - print(f"Erreur lors de la correction des accents: {str(e)}") - raise - -def corriger_markdown_accents(input_file: str, output_file: Optional[str] = None) -> None: - """ - Corrige les problèmes d'accents dans un fichier Markdown. - - Args: - input_file: Chemin du fichier Markdown Ă  corriger - output_file: Chemin du fichier de sortie (par dĂ©faut, Ă©crase le fichier d'entrĂ©e) - """ - if output_file is None: - output_file = input_file - - try: - # Lire le fichier Markdown - with open(input_file, 'r', encoding='utf-8') as f: - content = f.read() - - # Normaliser les accents - content_normalise = normaliser_accents(content) - - # VĂ©rifier si des changements ont Ă©tĂ© effectuĂ©s - if content != content_normalise: - # Écrire le fichier normalisĂ© - with open(output_file, 'w', encoding='utf-8') as f: - f.write(content_normalise) - - print(f"Correction des accents rĂ©ussie pour {os.path.basename(input_file)}") - else: - print(f"Aucune correction nĂ©cessaire pour {os.path.basename(input_file)}") - - except Exception as e: - print(f"Erreur lors de la correction des accents dans le markdown: {str(e)}") - raise - -def reparer_ticket(ticket_dir: str) -> bool: - """ - RĂ©pare et rĂ©initialise le traitement d'un ticket dont les donnĂ©es sont corrompues. - - Args: - ticket_dir: Chemin du rĂ©pertoire du ticket - - Returns: - True si la rĂ©paration a rĂ©ussi, False sinon - """ - try: - print(f"Tentative de rĂ©paration du ticket dans {ticket_dir}...") - - # VĂ©rifier que le rĂ©pertoire existe - if not os.path.isdir(ticket_dir): - print(f"ERREUR: RĂ©pertoire de ticket introuvable: {ticket_dir}") - return False - - # Chemins des fichiers critiques - ticket_info_path = os.path.join(ticket_dir, "ticket_info.json") - messages_path = os.path.join(ticket_dir, "messages.json") - attachments_path = os.path.join(ticket_dir, "attachments_info.json") - - # VĂ©rifier et rĂ©parer ticket_info.json - if os.path.exists(ticket_info_path): - try: - with open(ticket_info_path, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - - # VĂ©rifier la structure minimale - if not isinstance(ticket_info, dict): - raise ValueError("ticket_info.json n'est pas un dictionnaire valide") - - # RĂ©parer les champs manquants ou invalides - code = os.path.basename(ticket_dir).replace("ticket_", "") - if "code" not in ticket_info or not isinstance(ticket_info["code"], str): - ticket_info["code"] = code - - if "name" not in ticket_info or not isinstance(ticket_info["name"], str): - ticket_info["name"] = f"Ticket {code}" - - if "description" not in ticket_info or not isinstance(ticket_info["description"], str): - ticket_info["description"] = "" - - # Réécrire le fichier nettoyĂ© - with open(ticket_info_path, 'w', encoding='utf-8') as f: - json.dump(ticket_info, f, indent=2, ensure_ascii=False) - - print(f"âś“ ticket_info.json rĂ©parĂ©") - - except Exception as e: - print(f"! Erreur lors de la rĂ©paration de ticket_info.json: {str(e)}") - # CrĂ©er un ticket_info minimal - ticket_info = { - "code": os.path.basename(ticket_dir).replace("ticket_", ""), - "name": f"Ticket {os.path.basename(ticket_dir).replace('ticket_', '')}", - "description": "", - "create_date": "" - } - - # Sauvegarder la version minimale - with open(ticket_info_path, 'w', encoding='utf-8') as f: - json.dump(ticket_info, f, indent=2, ensure_ascii=False) - - print(f"âś“ ticket_info.json recréé avec structure minimale") - else: - # CrĂ©er un ticket_info minimal - ticket_info = { - "code": os.path.basename(ticket_dir).replace("ticket_", ""), - "name": f"Ticket {os.path.basename(ticket_dir).replace('ticket_', '')}", - "description": "", - "create_date": "" - } - - # Sauvegarder la version minimale - with open(ticket_info_path, 'w', encoding='utf-8') as f: - json.dump(ticket_info, f, indent=2, ensure_ascii=False) - - print(f"âś“ ticket_info.json créé avec structure minimale") - - # VĂ©rifier et rĂ©parer messages.json - messages_valides = False - if os.path.exists(messages_path): - try: - # Sauvegarder l'original s'il n'y a pas encore de backup - backup_file = os.path.join(ticket_dir, "messages.json.original") - if not os.path.exists(backup_file): - shutil.copy2(messages_path, backup_file) - print(f"âś“ Sauvegarde originale créée: {backup_file}") - - # Essayer de charger le fichier - with open(messages_path, 'r', encoding='utf-8') as f: - messages = json.load(f) - - # VĂ©rifier que c'est une liste - if not isinstance(messages, list): - raise ValueError("messages.json n'est pas une liste valide") - - messages_valides = True - print(f"âś“ messages.json valide ({len(messages)} messages)") - except Exception as e: - print(f"! Erreur dans messages.json: {str(e)}") - print(" Tentative de rĂ©cupĂ©ration...") - - # Essayer de rĂ©cupĂ©rer depuis la sauvegarde - backup_file = os.path.join(ticket_dir, "messages.json.original") - if os.path.exists(backup_file): - try: - with open(backup_file, 'r', encoding='utf-8') as f: - messages = json.load(f) - - if isinstance(messages, list): - # Sauvegarder la version rĂ©cupĂ©rĂ©e - with open(messages_path, 'w', encoding='utf-8') as f: - json.dump(messages, f, indent=2, ensure_ascii=False) - - messages_valides = True - print(f"âś“ messages.json rĂ©cupĂ©rĂ© depuis la sauvegarde") - except Exception: - print(" Échec de la rĂ©cupĂ©ration depuis la sauvegarde") - - # Si les messages sont toujours invalides, crĂ©er un fichier minimal - if not messages_valides: - # CrĂ©er un fichier messages minimal - messages = [{ - "id": 1, - "body": f"Message par dĂ©faut pour le ticket {os.path.basename(ticket_dir)}", - "date": "", - "email_from": "client@example.com" - }] - - # Sauvegarder la version minimale - with open(messages_path, 'w', encoding='utf-8') as f: - json.dump(messages, f, indent=2, ensure_ascii=False) - - print(f"âś“ messages.json recréé avec message par dĂ©faut") - - # Transformer messages.json pour le format attendu - print("Transformation des messages pour le bon format...") - transformer_messages(messages_path) - print("âś“ Transformation des messages terminĂ©e") - - # VĂ©rifier et rĂ©parer attachments_info.json - if os.path.exists(attachments_path): - try: - with open(attachments_path, 'r', encoding='utf-8') as f: - attachments = json.load(f) - - # VĂ©rifier que c'est une liste - if not isinstance(attachments, list): - attachments = [] - with open(attachments_path, 'w', encoding='utf-8') as f: - json.dump(attachments, f, indent=2, ensure_ascii=False) - print(f"âś“ attachments_info.json rĂ©parĂ© (liste vide)") - else: - print(f"âś“ attachments_info.json valide ({len(attachments)} pièces jointes)") - except Exception as e: - print(f"! Erreur dans attachments_info.json: {str(e)}") - # CrĂ©er une liste vide - with open(attachments_path, 'w', encoding='utf-8') as f: - json.dump([], f, indent=2, ensure_ascii=False) - print(f"âś“ attachments_info.json recréé (liste vide)") - else: - # CrĂ©er une liste vide - with open(attachments_path, 'w', encoding='utf-8') as f: - json.dump([], f, indent=2, ensure_ascii=False) - print(f"âś“ attachments_info.json créé (liste vide)") - - print(f"RĂ©paration du ticket terminĂ©e avec succès!") - return True - - except Exception as e: - print(f"ERREUR lors de la rĂ©paration du ticket: {str(e)}") - import traceback - print(f"DĂ©tails: {traceback.format_exc()}") - return False - -def diagnostiquer_ticket(ticket_dir: str) -> Dict[str, Any]: - """ - Diagnostique les problèmes dans un ticket et propose des solutions. - - Args: - ticket_dir: Chemin du rĂ©pertoire du ticket - - Returns: - Rapport de diagnostic avec les problèmes identifiĂ©s et solutions proposĂ©es - """ - diagnostic = { - "problemes": [], - "suggestions": [], - "etat_fichiers": {} - } - - print(f"Diagnostic du ticket dans {ticket_dir}...") - - # VĂ©rifier que le rĂ©pertoire existe - if not os.path.isdir(ticket_dir): - diagnostic["problemes"].append(f"RĂ©pertoire de ticket introuvable: {ticket_dir}") - diagnostic["suggestions"].append("CrĂ©er le rĂ©pertoire du ticket") - return diagnostic - - # Chemins des fichiers critiques - ticket_info_path = os.path.join(ticket_dir, "ticket_info.json") - messages_path = os.path.join(ticket_dir, "messages.json") - messages_backup_path = os.path.join(ticket_dir, "messages.json.backup") - attachments_path = os.path.join(ticket_dir, "attachments_info.json") - attachments_dir = os.path.join(ticket_dir, "attachments") - questions_reponses_path = os.path.join(ticket_dir, "questions_reponses.md") - rapport_dir = os.path.join(ticket_dir, "rapport") - - # VĂ©rifier ticket_info.json - if os.path.exists(ticket_info_path): - try: - with open(ticket_info_path, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - - diagnostic["etat_fichiers"]["ticket_info.json"] = "valide" - - # VĂ©rifier la structure minimale - if not isinstance(ticket_info, dict): - diagnostic["problemes"].append("ticket_info.json n'est pas un dictionnaire valide") - diagnostic["suggestions"].append("RĂ©parer ticket_info.json avec --repair") - diagnostic["etat_fichiers"]["ticket_info.json"] = "invalide" - - # VĂ©rifier les champs HTML - description = ticket_info.get("description", "") - if isinstance(description, str) and re.search(r'<[a-z]+[^>]*>', description, re.IGNORECASE): - diagnostic["problemes"].append("La description contient du HTML non traitĂ©") - diagnostic["suggestions"].append("Traiter les balises HTML dans la description") - - except Exception as e: - diagnostic["problemes"].append(f"Erreur dans ticket_info.json: {str(e)}") - diagnostic["suggestions"].append("RĂ©parer ticket_info.json avec --repair") - diagnostic["etat_fichiers"]["ticket_info.json"] = "corrompu" - else: - diagnostic["problemes"].append(f"Fichier manquant: ticket_info.json") - diagnostic["suggestions"].append("CrĂ©er ticket_info.json avec --repair") - diagnostic["etat_fichiers"]["ticket_info.json"] = "manquant" - - # VĂ©rifier messages.json - if os.path.exists(messages_path): - try: - with open(messages_path, 'r', encoding='utf-8') as f: - messages = json.load(f) - - diagnostic["etat_fichiers"]["messages.json"] = "valide" - - # VĂ©rifier que c'est une liste - if not isinstance(messages, list): - diagnostic["problemes"].append("messages.json n'est pas une liste valide") - diagnostic["suggestions"].append("RĂ©parer messages.json avec --repair") - diagnostic["etat_fichiers"]["messages.json"] = "invalide" - - # VĂ©rifier le contenu HTML dans les messages - html_count = 0 - for msg in messages: - if not isinstance(msg, dict): - continue - - body = msg.get("body", "") - if isinstance(body, str) and re.search(r'<[a-z]+[^>]*>', body, re.IGNORECASE): - html_count += 1 - - if html_count > 0: - diagnostic["problemes"].append(f"{html_count} message(s) contiennent du HTML non traitĂ©") - diagnostic["suggestions"].append("Retraiter messages.json avec --debug pour voir les problèmes") - - # VĂ©rifier les accents dans les messages - accents_count = 0 - for msg in messages: - if not isinstance(msg, dict): - continue - - body = msg.get("body", "") - if isinstance(body, str): - # VĂ©rifier les entitĂ©s HTML pour les accents - if re.search(r'&[aeiounc][a-z]{3,5};', body, re.IGNORECASE): - accents_count += 1 - - if accents_count > 0: - diagnostic["problemes"].append(f"{accents_count} message(s) contiennent des entitĂ©s HTML d'accent non converties") - diagnostic["suggestions"].append("Corriger les accents avec --fix-all") - - except Exception as e: - diagnostic["problemes"].append(f"Erreur dans messages.json: {str(e)}") - diagnostic["suggestions"].append("RĂ©parer messages.json avec --repair") - diagnostic["etat_fichiers"]["messages.json"] = "corrompu" - else: - diagnostic["problemes"].append(f"Fichier manquant: messages.json") - diagnostic["suggestions"].append("CrĂ©er messages.json avec --repair") - diagnostic["etat_fichiers"]["messages.json"] = "manquant" - - # VĂ©rifier si une sauvegarde des messages existe - if os.path.exists(messages_backup_path): - diagnostic["etat_fichiers"]["messages.json.backup"] = "prĂ©sent" - else: - diagnostic["etat_fichiers"]["messages.json.backup"] = "manquant" - - # VĂ©rifier le fichier des questions et rĂ©ponses - if os.path.exists(questions_reponses_path): - try: - with open(questions_reponses_path, 'r', encoding='utf-8') as f: - content = f.read() - - diagnostic["etat_fichiers"]["questions_reponses.md"] = "prĂ©sent" - - # VĂ©rifier si des questions/rĂ©ponses sont prĂ©sentes - if "| Question | RĂ©ponse |" in content and not re.search(r'\| \*\*[^|]+\*\*: ', content): - diagnostic["problemes"].append("Le fichier questions_reponses.md ne contient pas de questions/rĂ©ponses") - diagnostic["suggestions"].append("Retraiter le ticket pour extraire les questions/rĂ©ponses") - - except Exception as e: - diagnostic["problemes"].append(f"Erreur dans questions_reponses.md: {str(e)}") - diagnostic["etat_fichiers"]["questions_reponses.md"] = "invalide" - else: - diagnostic["etat_fichiers"]["questions_reponses.md"] = "manquant" - - # VĂ©rifier les pièces jointes - if os.path.exists(attachments_path): - try: - with open(attachments_path, 'r', encoding='utf-8') as f: - attachments = json.load(f) - - diagnostic["etat_fichiers"]["attachments_info.json"] = "valide" - - # VĂ©rifier que c'est une liste - if not isinstance(attachments, list): - diagnostic["problemes"].append("attachments_info.json n'est pas une liste valide") - diagnostic["suggestions"].append("RĂ©parer attachments_info.json avec --repair") - diagnostic["etat_fichiers"]["attachments_info.json"] = "invalide" - - # VĂ©rifier que les fichiers attachĂ©s existent - if os.path.exists(attachments_dir): - diagnostic["etat_fichiers"]["attachments/"] = "prĂ©sent" - - for attachment in attachments: - if not isinstance(attachment, dict): - continue - - file_path = attachment.get("file_path", "") - if not file_path: - continue - - # Normaliser le chemin - if not os.path.isabs(file_path): - file_path = os.path.join(attachments_dir, os.path.basename(file_path)) - - if not os.path.exists(file_path): - file_name = os.path.basename(file_path) - diagnostic["problemes"].append(f"Fichier attachĂ© manquant: {file_name}") - else: - diagnostic["etat_fichiers"]["attachments/"] = "manquant" - diagnostic["problemes"].append("RĂ©pertoire attachments/ manquant") - - except Exception as e: - diagnostic["problemes"].append(f"Erreur dans attachments_info.json: {str(e)}") - diagnostic["suggestions"].append("RĂ©parer attachments_info.json avec --repair") - diagnostic["etat_fichiers"]["attachments_info.json"] = "corrompu" - else: - diagnostic["etat_fichiers"]["attachments_info.json"] = "manquant" - diagnostic["problemes"].append("Fichier attachments_info.json manquant") - diagnostic["suggestions"].append("CrĂ©er attachments_info.json avec --repair") - - # VĂ©rifier le rĂ©pertoire rapport - if os.path.exists(rapport_dir): - diagnostic["etat_fichiers"]["rapport/"] = "prĂ©sent" - - rapport_json = os.path.join(rapport_dir, "ticket_analysis.json") - rapport_md = os.path.join(rapport_dir, "ticket_analysis.md") - - if os.path.exists(rapport_json): - diagnostic["etat_fichiers"]["rapport/ticket_analysis.json"] = "prĂ©sent" - else: - diagnostic["etat_fichiers"]["rapport/ticket_analysis.json"] = "manquant" - diagnostic["problemes"].append("Rapport JSON manquant") - - if os.path.exists(rapport_md): - diagnostic["etat_fichiers"]["rapport/ticket_analysis.md"] = "prĂ©sent" - else: - diagnostic["etat_fichiers"]["rapport/ticket_analysis.md"] = "manquant" - diagnostic["problemes"].append("Rapport Markdown manquant") - else: - diagnostic["etat_fichiers"]["rapport/"] = "manquant" - - # Ajouter des suggestions globales si nĂ©cessaires - if len(diagnostic["problemes"]) > 3: - diagnostic["suggestions"].insert(0, "Utiliser l'option --repair pour essayer de corriger tous les problèmes automatiquement") - - # Afficher le rĂ©sumĂ© du diagnostic - print(f"\nRĂ©sumĂ© du diagnostic pour {os.path.basename(ticket_dir)}:") - print(f"- Problèmes identifiĂ©s: {len(diagnostic['problemes'])}") - - for i, probleme in enumerate(diagnostic["problemes"]): - print(f" {i+1}. {probleme}") - - print("\nSuggestions:") - for suggestion in diagnostic["suggestions"]: - print(f"- {suggestion}") - - return diagnostic - -def main(): - """ - Point d'entrĂ©e principal du script. - """ - # Analyser les arguments - if len(sys.argv) < 2: - print("Usage: python post_process.py [options]") - print("Options:") - print(" --fix-all Corriger les accents dans tous les fichiers JSON et Markdown") - print(" --fix-md Corriger uniquement les fichiers Markdown") - print(" --repair RĂ©parer un ticket corrompu") - print(" --debug Activer le mode dĂ©bogage") - print(" --diagnose Diagnostiquer les problèmes du ticket") - print(" --help Afficher cette aide") - sys.exit(1) - - # Afficher l'aide - if "--help" in sys.argv: - print("Usage: python post_process.py [options]") - print("Options:") - print(" --fix-all Corriger les accents dans tous les fichiers JSON et Markdown") - print(" --fix-md Corriger uniquement les fichiers Markdown") - print(" --repair RĂ©parer un ticket corrompu") - print(" --debug Activer le mode dĂ©bogage") - print(" --diagnose Diagnostiquer les problèmes du ticket") - print(" --help Afficher cette aide") - sys.exit(0) - - ticket_dir = sys.argv[1] - fix_all = "--fix-all" in sys.argv - fix_md = "--fix-md" in sys.argv - repair = "--repair" in sys.argv - debug = "--debug" in sys.argv - diagnose = "--diagnose" in sys.argv - - # VĂ©rifier que le rĂ©pertoire existe - if not os.path.isdir(ticket_dir): - print(f"ERREUR: RĂ©pertoire non trouvĂ©: {ticket_dir}") - sys.exit(1) - - # Option de diagnostic du ticket - if diagnose: - diagnostiquer_ticket(ticket_dir) - sys.exit(0) - - # Option de rĂ©paration du ticket - if repair: - success = reparer_ticket(ticket_dir) - if not success: - print("La rĂ©paration du ticket a Ă©chouĂ©.") - sys.exit(1) - print("Ticket rĂ©parĂ© avec succès!") - sys.exit(0) - - # Option de correction des accents dans les fichiers Markdown uniquement - if fix_md: - rapport_dir = os.path.join(ticket_dir, "rapport") - corrected = False - - # Corriger les fichiers Markdown du rĂ©pertoire rapport - if os.path.exists(rapport_dir): - for root, _, files in os.walk(rapport_dir): - for file in files: - if file.endswith(".md"): - md_file = os.path.join(root, file) - corriger_markdown_accents(md_file) - corrected = True - - # Corriger les fichiers Markdown Ă  la racine du ticket - for file in os.listdir(ticket_dir): - if file.endswith(".md"): - md_file = os.path.join(ticket_dir, file) - corriger_markdown_accents(md_file) - corrected = True - - if corrected: - print("Correction des accents terminĂ©e dans les fichiers Markdown.") - else: - print("Aucun fichier Markdown trouvĂ©.") - sys.exit(0) - - # Transformation standard des messages - messages_file = os.path.join(ticket_dir, "messages.json") - if not os.path.exists(messages_file): - print(f"Fichier non trouvĂ©: {messages_file}") - sys.exit(1) - - try: - # Transformer les messages - transformer_messages(messages_file, debug=debug) - print(f"Post-traitement terminĂ© pour {messages_file}") - - # Corriger les accents dans tous les fichiers si demandĂ© - if fix_all: - rapport_dir = os.path.join(ticket_dir, "rapport") - if os.path.exists(rapport_dir): - # Corriger les fichiers JSON - for root, _, files in os.walk(rapport_dir): - for file in files: - if file.endswith(".json"): - json_file = os.path.join(root, file) - corriger_json_accents(json_file) - - # Corriger les fichiers Markdown - for root, _, files in os.walk(rapport_dir): - for file in files: - if file.endswith(".md"): - md_file = os.path.join(root, file) - corriger_markdown_accents(md_file) - - # Corriger les fichiers Markdown Ă  la racine du ticket - for file in os.listdir(ticket_dir): - if file.endswith(".md"): - md_file = os.path.join(ticket_dir, file) - corriger_markdown_accents(md_file) - - print("Correction des accents terminĂ©e dans tous les fichiers.") - except Exception as e: - print(f"ERREUR lors du post-traitement: {str(e)}") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 5dd5943..0000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -requests>=2.28.0 -mistralai>=0.0.7 \ No newline at end of file diff --git a/scripts/analyze_image_contexte.py b/scripts/analyze_image_contexte.py deleted file mode 100644 index 2378636..0000000 --- a/scripts/analyze_image_contexte.py +++ /dev/null @@ -1,384 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script d'analyse d'image avec contexte pour les tickets de support. -Extrait des informations pertinentes d'une image en fonction du contexte du ticket. -""" - -import os -import sys -import json -import argparse -import logging -from typing import Dict, Any, Optional - -# Configuration du logger -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler("analyze_image.log"), - logging.StreamHandler() - ] -) -logger = logging.getLogger("analyze_image") - -try: - from llm import Pixtral -except ImportError: - logger.error("Module LLM non trouvĂ©. Veuillez vous assurer que le rĂ©pertoire parent est dans PYTHONPATH.") - sys.exit(1) - -class ImageAnalyzer: - """ - Analyseur d'image qui extrait des informations pertinentes en fonction du contexte. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'analyseur d'image. - - Args: - api_key: ClĂ© API pour le modèle de vision - """ - self.llm = Pixtral(api_key=api_key) - - # Configurer le modèle de vision - try: - self.llm.model = "pixtral-12b-2409" - self.llm.temperature = 0.3 - self.llm.max_tokens = 1024 - except Exception as e: - logger.warning(f"Impossible de configurer le modèle: {e}") - - self.historique = [] - - def ajouter_historique(self, action: str, entree: str, resultat: str) -> None: - """ - Ajoute une entrĂ©e Ă  l'historique des actions. - - Args: - action: Type d'action effectuĂ©e - entree: EntrĂ©e de l'action - resultat: RĂ©sultat de l'action - """ - self.historique.append({ - "action": action, - "entree": entree, - "resultat": resultat - }) - - def analyser_image(self, image_path: str, contexte: Optional[str] = None) -> Dict[str, Any]: - """ - Analyse une image en fonction du contexte donnĂ©. - - Args: - image_path: Chemin vers l'image Ă  analyser - contexte: Contexte du ticket pour aider Ă  l'analyse - - Returns: - RĂ©sultat de l'analyse de l'image - """ - if not os.path.exists(image_path): - logger.error(f"Image introuvable: {image_path}") - return { - "success": False, - "erreur": "Image introuvable", - "path": image_path - } - - # VĂ©rifier que le fichier est une image - _, extension = os.path.splitext(image_path) - if extension.lower() not in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']: - logger.error(f"Format de fichier non supportĂ©: {extension}") - return { - "success": False, - "erreur": f"Format de fichier non supportĂ©: {extension}", - "path": image_path - } - - # PrĂ©parer le prompt pour l'analyse - prompt_base = """ - Tu es un expert en analyse technique d'interfaces utilisateur et de captures d'Ă©cran. - - Analyse cette image en dĂ©tail et extrait les informations suivantes: - - 1. Type d'image: capture d'Ă©cran, photo, schĂ©ma, etc. - 2. Interface visible: nom du logiciel, type d'interface, fonctionnalitĂ©s visibles - 3. ÉlĂ©ments importants: boutons, menus, messages d'erreur, donnĂ©es visibles - 4. Problème potentiel: erreurs, anomalies, incohĂ©rences visibles - 5. Contexte technique: environnement logiciel, version potentielle, plateforme - - Pour les captures d'Ă©cran, identifie prĂ©cisĂ©ment: - - Le nom exact de la fenĂŞtre/dialogue - - Les champs/formulaires visibles - - Les valeurs/donnĂ©es affichĂ©es - - Les messages d'erreur ou d'avertissement - - Les boutons/actions disponibles - - RĂ©ponds de manière structurĂ©e en format Markdown avec des sections claires. - Sois prĂ©cis et factuel, en te concentrant sur les Ă©lĂ©ments techniques visibles. - """ - - # Ajouter le contexte si disponible - if contexte: - prompt_base += f""" - - CONTEXTE DU TICKET: - {contexte} - - En tenant compte du contexte ci-dessus, explique Ă©galement: - - En quoi cette image est pertinente pour le problème dĂ©crit - - Quels Ă©lĂ©ments de l'image correspondent au problème mentionnĂ© - - Comment cette image peut aider Ă  rĂ©soudre le problème - """ - - try: - # Appeler le modèle de vision - try: - resultat = self.llm.analyze_image(image_path, prompt_base) - self.ajouter_historique("analyze_image", os.path.basename(image_path), "Analyse effectuĂ©e") - except Exception as e: - logger.error(f"Erreur lors de l'appel au modèle de vision: {str(e)}") - return { - "success": False, - "erreur": f"Erreur lors de l'appel au modèle de vision: {str(e)}", - "path": image_path - } - - # Extraire le contenu de la rĂ©ponse - contenu = resultat.get("content", "") - if not contenu: - logger.error("RĂ©ponse vide du modèle de vision") - return { - "success": False, - "erreur": "RĂ©ponse vide du modèle de vision", - "path": image_path - } - - # CrĂ©er le rĂ©sultat final - resultat_analyse = { - "success": True, - "path": image_path, - "analyse": contenu, - "contexte_fourni": bool(contexte) - } - - # Essayer d'extraire des informations structurĂ©es Ă  partir de l'analyse - try: - # Rechercher le type d'image - import re - type_match = re.search(r"Type d['']image\s*:\s*([^\n\.]+)", contenu, re.IGNORECASE) - if type_match: - resultat_analyse["type_image"] = type_match.group(1).strip() - - # Rechercher l'interface - interface_match = re.search(r'Interface\s*:\s*([^\n\.]+)', contenu, re.IGNORECASE) - interface_match2 = re.search(r'Interface visible\s*:\s*([^\n\.]+)', contenu, re.IGNORECASE) - if interface_match: - resultat_analyse["interface"] = interface_match.group(1).strip() - elif interface_match2: - resultat_analyse["interface"] = interface_match2.group(1).strip() - - # Rechercher le problème - probleme_match = re.search(r'Problème\s*:\s*([^\n\.]+)', contenu, re.IGNORECASE) - probleme_match2 = re.search(r'Problème potentiel\s*:\s*([^\n\.]+)', contenu, re.IGNORECASE) - if probleme_match: - resultat_analyse["probleme"] = probleme_match.group(1).strip() - elif probleme_match2: - resultat_analyse["probleme"] = probleme_match2.group(1).strip() - except Exception as e: - logger.warning(f"Impossible d'extraire des informations structurĂ©es: {str(e)}") - - return resultat_analyse - - except Exception as e: - logger.error(f"Erreur lors de l'analyse de l'image {image_path}: {str(e)}") - return { - "success": False, - "erreur": str(e), - "path": image_path - } - - def generer_rapport_markdown(self, analyse: Dict[str, Any]) -> str: - """ - GĂ©nère un rapport Markdown Ă  partir de l'analyse d'image. - - Args: - analyse: RĂ©sultat de l'analyse d'image - - Returns: - Rapport au format Markdown - """ - if not analyse.get("success", False): - return f"# Échec de l'analyse d'image\n\nErreur: {analyse.get('erreur', 'Inconnue')}\n\nImage: {analyse.get('path', 'Inconnue')}" - - # En-tĂŞte du rapport - image_path = analyse.get("path", "Inconnue") - image_name = os.path.basename(image_path) - - rapport = f"# Analyse de l'image: {image_name}\n\n" - - # Ajouter l'analyse brute - rapport += analyse.get("analyse", "Aucune analyse disponible") - - # Ajouter des mĂ©tadonnĂ©es - rapport += "\n\n## MĂ©tadonnĂ©es\n\n" - rapport += f"- **Chemin de l'image**: `{image_path}`\n" - rapport += f"- **Contexte fourni**: {'Oui' if analyse.get('contexte_fourni', False) else 'Non'}\n" - - if "type_image" in analyse: - rapport += f"- **Type d'image dĂ©tectĂ©**: {analyse['type_image']}\n" - - if "interface" in analyse: - rapport += f"- **Interface identifiĂ©e**: {analyse['interface']}\n" - - if "probleme" in analyse: - rapport += f"- **Problème dĂ©tectĂ©**: {analyse['probleme']}\n" - - # Ajouter les paramètres du modèle - rapport += "\n## Paramètres du modèle\n\n" - rapport += f"- **Modèle**: {getattr(self.llm, 'model', 'pixtral-12b-2409')}\n" - rapport += f"- **TempĂ©rature**: {getattr(self.llm, 'temperature', 0.3)}\n" - - return rapport - -def charger_config(): - """ - Charge la configuration depuis config.json. - - Returns: - Configuration chargĂ©e - """ - config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config.json") - - if not os.path.exists(config_path): - logger.warning(f"Fichier de configuration non trouvĂ©: {config_path}") - return {"llm": {"api_key": None}} - - try: - with open(config_path, 'r', encoding='utf-8') as f: - config = json.load(f) - return config - except Exception as e: - logger.error(f"Erreur lors du chargement de la configuration: {str(e)}") - return {"llm": {"api_key": None}} - -def main(): - """ - Point d'entrĂ©e du script. - """ - parser = argparse.ArgumentParser(description="Analyse une image en fonction du contexte du ticket.") - parser.add_argument("--image", "-i", required=True, help="Chemin vers l'image Ă  analyser") - parser.add_argument("--contexte", "-c", help="Chemin vers un fichier contenant le contexte du ticket") - parser.add_argument("--ticket-info", "-t", help="Chemin vers un fichier ticket_info.json pour extraire le contexte") - parser.add_argument("--output", "-o", help="Chemin du fichier de sortie pour le rapport Markdown (par dĂ©faut: _analyse.md)") - parser.add_argument("--format", "-f", choices=["json", "md", "both"], default="both", - help="Format de sortie (json, md, both)") - parser.add_argument("--verbose", "-v", action="store_true", help="Afficher plus d'informations") - - args = parser.parse_args() - - # Configurer le niveau de log - if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - # VĂ©rifier que l'image existe - if not os.path.exists(args.image): - logger.error(f"Image non trouvĂ©e: {args.image}") - sys.exit(1) - - # Charger le contexte si disponible - contexte = None - - if args.contexte and os.path.exists(args.contexte): - try: - with open(args.contexte, 'r', encoding='utf-8') as f: - contexte = f.read() - logger.info(f"Contexte chargĂ© depuis {args.contexte}") - except Exception as e: - logger.warning(f"Impossible de charger le contexte depuis {args.contexte}: {str(e)}") - - # Extraire le contexte depuis ticket_info.json si disponible - if not contexte and args.ticket_info and os.path.exists(args.ticket_info): - try: - with open(args.ticket_info, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - - if isinstance(ticket_info, dict): - contexte = f""" - TICKET: {ticket_info.get('code', 'Inconnu')} - {ticket_info.get('name', 'Sans titre')} - - DESCRIPTION: - {ticket_info.get('description', 'Aucune description')} - """ - logger.info(f"Contexte extrait depuis {args.ticket_info}") - except Exception as e: - logger.warning(f"Impossible de charger le contexte depuis {args.ticket_info}: {str(e)}") - - # DĂ©terminer les chemins de sortie - if not args.output: - output_base = os.path.splitext(args.image)[0] - output_md = f"{output_base}_analyse.md" - output_json = f"{output_base}_analyse.json" - else: - output_base = os.path.splitext(args.output)[0] - output_md = f"{output_base}.md" - output_json = f"{output_base}.json" - - # Charger la configuration - config = charger_config() - api_key = config.get("llm", {}).get("api_key") - - # Initialiser l'analyseur d'image - analyzer = ImageAnalyzer(api_key=api_key) - - try: - # Analyser l'image - resultat = analyzer.analyser_image(args.image, contexte) - - if not resultat.get("success", False): - logger.error(f"Échec de l'analyse: {resultat.get('erreur', 'Erreur inconnue')}") - sys.exit(1) - - # GĂ©nĂ©rer le rapport Markdown - rapport_md = analyzer.generer_rapport_markdown(resultat) - - # Sauvegarder les rĂ©sultats selon le format demandĂ© - if args.format in ["json", "both"]: - with open(output_json, 'w', encoding='utf-8') as f: - json.dump(resultat, f, indent=2, ensure_ascii=False) - logger.info(f"RĂ©sultat JSON sauvegardĂ©: {output_json}") - - if args.format in ["md", "both"]: - with open(output_md, 'w', encoding='utf-8') as f: - f.write(rapport_md) - logger.info(f"Rapport Markdown sauvegardĂ©: {output_md}") - - # Afficher un rĂ©sumĂ© - print("\nRĂ©sumĂ© de l'analyse:") - print(f"Image: {os.path.basename(args.image)}") - - if "type_image" in resultat: - print(f"Type d'image: {resultat['type_image']}") - - if "interface" in resultat: - print(f"Interface: {resultat['interface']}") - - if "probleme" in resultat: - print(f"Problème: {resultat['probleme']}") - - if args.format in ["json", "both"]: - print(f"RĂ©sultat JSON: {output_json}") - - if args.format in ["md", "both"]: - print(f"Rapport Markdown: {output_md}") - - except Exception as e: - logger.error(f"Erreur lors de l'analyse: {str(e)}") - import traceback - logger.debug(f"DĂ©tails: {traceback.format_exc()}") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/scripts/analyze_ticket.py b/scripts/analyze_ticket.py deleted file mode 100644 index 8f266ba..0000000 --- a/scripts/analyze_ticket.py +++ /dev/null @@ -1,444 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script d'analyse de ticket pour extraire les informations essentielles -et gĂ©nĂ©rer un rapport d'analyse complet. -""" - -import os -import sys -import json -import argparse -import logging -from typing import Dict, List, Any, Optional - -# Configuration du logger -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler("analyze_ticket.log"), - logging.StreamHandler() - ] -) -logger = logging.getLogger("analyze_ticket") - -try: - from llm import Mistral -except ImportError: - logger.error("Module LLM non trouvĂ©. Veuillez vous assurer que le rĂ©pertoire parent est dans PYTHONPATH.") - sys.exit(1) - -class TicketAnalyzer: - """ - Agent d'analyse de ticket qui extrait les informations pertinentes. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'agent d'analyse de ticket. - - Args: - api_key: ClĂ© API pour le LLM - """ - self.llm = Mistral(api_key=api_key) - self.llm.set_model("mistral-medium") - self.llm.set_temperature(0.3) - self.llm.set_max_tokens(1000) - - # DĂ©finir le prompt système par dĂ©faut - self.system_prompt = """ - Tu es un expert en analyse de tickets de support technique. - - Ton objectif est d'analyser un ticket de support pour: - 1. Identifier le problème principal - 2. RĂ©sumer la solution (si prĂ©sente) - 3. Extraire les informations clĂ©s - 4. CatĂ©goriser le problème et sa gravitĂ© - 5. Évaluer la qualitĂ© de la rĂ©solution - - Utilise un ton professionnel et factuel. - Concentre-toi uniquement sur les informations pertinentes. - Ne spĂ©cule pas au-delĂ  de ce qui est prĂ©sent dans les donnĂ©es. - - Si une information n'est pas disponible, indique-le clairement. - """ - - self.historique = [] - - def ajouter_historique(self, action: str, entree: str, resultat: str) -> None: - """ - Ajoute une entrĂ©e Ă  l'historique des actions. - - Args: - action: Type d'action effectuĂ©e - entree: EntrĂ©e de l'action - resultat: RĂ©sultat de l'action - """ - self.historique.append({ - "action": action, - "entree": entree, - "resultat": resultat - }) - - def analyser_ticket(self, messages: List[Dict[str, Any]], infos_images: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: - """ - Analyse un ticket Ă  partir de ses messages et informations d'images. - - Args: - messages: Liste des messages du ticket - infos_images: Informations sur les images analysĂ©es (optionnel) - - Returns: - RĂ©sultats de l'analyse du ticket - """ - if not messages: - logger.warning("Aucun message Ă  analyser") - return { - "success": False, - "erreur": "Aucun message Ă  analyser" - } - - logger.info(f"Analyse de ticket avec {len(messages)} messages") - - # Extraire les informations du ticket depuis le premier message (contexte) - ticket_info = {} - if messages and messages[0].get("role") == "system" and messages[0].get("type") == "contexte": - ticket_info = { - "id": messages[0].get("id", ""), - "code": messages[0].get("code", ""), - "name": messages[0].get("name", ""), - "description": messages[0].get("description", ""), - "date_create": messages[0].get("date_create", "") - } - - # Retirer le message de contexte pour l'analyse - actual_messages = messages[1:] - else: - actual_messages = messages - - # PrĂ©parer le prompt pour l'analyse - prompt = f""" - Analyse ce ticket de support: - - TICKET: {ticket_info.get('code', 'N/A')} - {ticket_info.get('name', 'Sans titre')} - DATE: {ticket_info.get('date_create', 'Inconnue')} - - DESCRIPTION: - {ticket_info.get('description', 'Aucune description')} - - MESSAGES: - """ - - # Ajouter les messages - for i, msg in enumerate(actual_messages): - role = msg.get("role", "Inconnu") - date = msg.get("date", "") - body = msg.get("body", "") - - prompt += f"\n--- MESSAGE {i+1} ({role}, {date}) ---\n{body}\n" - - # Ajouter les informations sur les images si disponibles - if infos_images: - prompt += "\n\nIMAGES ANALYSÉES:\n" - - for image_path, analyse in infos_images.get("analyses", {}).items(): - if analyse.get("pertinente", False): - prompt += f"- {image_path}: {analyse.get('description', 'Pas de description')} ({analyse.get('type_image', 'type inconnu')})\n" - - # Demander une analyse structurĂ©e - prompt += """ - - Fais une analyse complète et structurĂ©e du ticket avec les sections suivantes: - - 1. PROBLĂME: RĂ©sume clairement le problème principal en 1-2 phrases - 2. CATÉGORIE: CatĂ©gorise le problème (bug, demande de fonctionnalitĂ©, question, etc.) - 3. GRAVITÉ: Évalue la gravitĂ© (Critique, ÉlevĂ©e, Moyenne, Faible) - 4. SOLUTION: RĂ©sume la solution fournie ou indique qu'aucune solution n'a Ă©tĂ© fournie - 5. EFFICACITÉ: Évalue si la solution a rĂ©solu le problème (RĂ©solue, Partiellement rĂ©solue, Non rĂ©solue, Inconnue) - 6. RÉSUMÉ: Fournis un rĂ©sumĂ© complet de l'incident en 3-5 phrases - 7. POINTS CLÉS: Liste les 3-5 points les plus importants Ă  retenir de ce ticket - - RĂ©ponds en format Markdown bien structurĂ©. - """ - - try: - # Effectuer l'analyse avec le LLM - resultat = self.llm.generate_text(prompt, system_prompt=self.system_prompt) - self.ajouter_historique("analyze_ticket", f"{len(messages)} messages", "Analyse effectuĂ©e") - - # Extraire le contenu - analyse_texte = resultat.get("content", "") - - # Extraire les diffĂ©rentes sections - sections = {} - - current_section = None - current_content = [] - - for line in analyse_texte.split("\n"): - # DĂ©tecter les en-tĂŞtes de section - if line.startswith("# "): - if current_section: - sections[current_section] = "\n".join(current_content).strip() - current_section = line[2:].strip().lower() - current_content = [] - elif line.startswith("## "): - if current_section: - sections[current_section] = "\n".join(current_content).strip() - current_section = line[3:].strip().lower() - current_content = [] - elif ":" in line and not "://" in line and not current_section: - # Cas des lignes "SECTION: contenu" sans formatage Markdown - parts = line.split(":", 1) - if len(parts) == 2 and parts[0].strip().upper() == parts[0].strip(): - current_section = parts[0].strip().lower() - current_content = [parts[1].strip()] - else: - if current_section: - current_content.append(line) - else: - if current_section: - current_content.append(line) - - # Ajouter la dernière section - if current_section: - sections[current_section] = "\n".join(current_content).strip() - - # Si on n'a pas pu extraire les sections, utiliser tout le texte - if not sections: - sections = { - "analyse_complete": analyse_texte - } - - # CrĂ©er le rĂ©sultat final - resultat_analyse = { - "success": True, - "ticket_info": ticket_info, - "sections": sections, - "analyse_brute": analyse_texte, - "nb_messages": len(actual_messages) - } - - logger.info("Analyse de ticket terminĂ©e avec succès") - return resultat_analyse - - except Exception as e: - erreur = f"Erreur lors de l'analyse du ticket: {str(e)}" - logger.error(erreur) - return { - "success": False, - "erreur": erreur - } - - def generer_rapport_markdown(self, analyse: Dict[str, Any]) -> str: - """ - GĂ©nère un rapport Markdown Ă  partir de l'analyse du ticket. - - Args: - analyse: RĂ©sultat de l'analyse du ticket - - Returns: - Rapport au format Markdown - """ - if not analyse.get("success", False): - return f"# Échec de l'analyse\n\nErreur: {analyse.get('erreur', 'Inconnue')}" - - ticket_info = analyse.get("ticket_info", {}) - sections = analyse.get("sections", {}) - - # En-tĂŞte du rapport - rapport = f"# Rapport d'analyse de ticket\n\n" - rapport += f"**Ticket**: {ticket_info.get('code', 'N/A')} - {ticket_info.get('name', 'Sans titre')}\n" - rapport += f"**Date**: {ticket_info.get('date_create', 'Inconnue')}\n" - rapport += f"**Messages analysĂ©s**: {analyse.get('nb_messages', 0)}\n\n" - - # RĂ©cupĂ©rer les sections principales - problem = sections.get("problème", sections.get("probleme", "")) - category = sections.get("catĂ©gorie", sections.get("categorie", "")) - severity = sections.get("gravitĂ©", sections.get("gravite", "")) - solution = sections.get("solution", "") - efficacy = sections.get("efficacitĂ©", sections.get("efficacite", "")) - summary = sections.get("rĂ©sumĂ©", sections.get("resume", "")) - key_points = sections.get("points clĂ©s", sections.get("points cles", "")) - - # Ajouter les sections au rapport - if problem: - rapport += f"## Problème\n\n{problem}\n\n" - - if category or severity: - rapport += "## Classification\n\n" - if category: - rapport += f"**CatĂ©gorie**: {category}\n\n" - if severity: - rapport += f"**GravitĂ©**: {severity}\n\n" - - if solution: - rapport += f"## Solution\n\n{solution}\n\n" - - if efficacy: - rapport += f"**EfficacitĂ©**: {efficacy}\n\n" - - if summary: - rapport += f"## RĂ©sumĂ©\n\n{summary}\n\n" - - if key_points: - rapport += f"## Points clĂ©s\n\n{key_points}\n\n" - - # Ajouter les autres sections qui n'auraient pas Ă©tĂ© traitĂ©es - for name, content in sections.items(): - if name not in ["problème", "probleme", "catĂ©gorie", "categorie", - "gravitĂ©", "gravite", "solution", "efficacitĂ©", - "efficacite", "rĂ©sumĂ©", "resume", "points clĂ©s", - "points cles", "analyse_complete"]: - rapport += f"## {name.title()}\n\n{content}\n\n" - - # Ajouter le rapport complet si on n'a pas pu extraire les sections - if "analyse_complete" in sections and len(sections) == 1: - rapport += f"## Analyse complète\n\n{sections['analyse_complete']}\n\n" - - # Ajouter les paramètres de l'analyse - rapport += "## Paramètres de l'analyse\n\n" - rapport += f"- **Modèle**: {self.llm.get_model()}\n" - rapport += f"- **TempĂ©rature**: {self.llm.get_temperature()}\n" - - return rapport - -def charger_config(): - """ - Charge la configuration depuis config.json. - - Returns: - Configuration chargĂ©e - """ - config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config.json") - - if not os.path.exists(config_path): - logger.warning(f"Fichier de configuration non trouvĂ©: {config_path}") - return {"llm": {"api_key": None}} - - try: - with open(config_path, 'r', encoding='utf-8') as f: - config = json.load(f) - return config - except Exception as e: - logger.error(f"Erreur lors du chargement de la configuration: {str(e)}") - return {"llm": {"api_key": None}} - -def main(): - """ - Point d'entrĂ©e du script. - """ - parser = argparse.ArgumentParser(description="Analyse un ticket de support.") - parser.add_argument("--messages", "-m", required=True, help="Chemin vers le fichier messages.json") - parser.add_argument("--images-rapport", "-i", help="Chemin vers le rapport d'analyse d'images (filter_report.json)") - parser.add_argument("--output", "-o", help="RĂ©pertoire de sortie pour les rapports") - parser.add_argument("--format", "-f", choices=["json", "md", "both"], default="both", - help="Format de sortie (json, md, both)") - parser.add_argument("--verbose", "-v", action="store_true", help="Afficher plus d'informations") - - args = parser.parse_args() - - # Configurer le niveau de log - if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - # VĂ©rifier que le fichier messages existe - if not os.path.exists(args.messages): - logger.error(f"Fichier de messages non trouvĂ©: {args.messages}") - sys.exit(1) - - # Charger les messages - try: - with open(args.messages, 'r', encoding='utf-8') as f: - messages = json.load(f) - - if not isinstance(messages, list): - logger.error(f"Format de fichier messages.json invalide. Une liste est attendue.") - sys.exit(1) - except Exception as e: - logger.error(f"Erreur lors du chargement des messages: {str(e)}") - sys.exit(1) - - # Charger les informations sur les images si disponibles - images_info = None - if args.images_rapport and os.path.exists(args.images_rapport): - try: - with open(args.images_rapport, 'r', encoding='utf-8') as f: - images_info = json.load(f) - logger.info(f"Informations sur les images chargĂ©es: {args.images_rapport}") - except Exception as e: - logger.warning(f"Impossible de charger les informations sur les images: {str(e)}") - - # DĂ©terminer le rĂ©pertoire de sortie - output_dir = args.output - if not output_dir: - # Par dĂ©faut, utiliser le mĂŞme rĂ©pertoire que le fichier messages - output_dir = os.path.dirname(args.messages) - if not output_dir: - output_dir = "." - - # CrĂ©er le rĂ©pertoire de sortie s'il n'existe pas - rapport_dir = os.path.join(output_dir, "rapport") - os.makedirs(rapport_dir, exist_ok=True) - - # Charger la configuration - config = charger_config() - api_key = config.get("llm", {}).get("api_key") - - # Initialiser l'analyseur de ticket - analyzer = TicketAnalyzer(api_key=api_key) - - try: - # Analyser le ticket - resultat = analyzer.analyser_ticket(messages, images_info) - - if not resultat.get("success", False): - logger.error(f"Échec de l'analyse: {resultat.get('erreur', 'Erreur inconnue')}") - sys.exit(1) - - # GĂ©nĂ©rer le rapport Markdown - rapport_md = analyzer.generer_rapport_markdown(resultat) - - # Sauvegarder les rĂ©sultats selon le format demandĂ© - if args.format in ["json", "both"]: - json_path = os.path.join(rapport_dir, "ticket_analysis.json") - with open(json_path, 'w', encoding='utf-8') as f: - json.dump(resultat, f, indent=2, ensure_ascii=False) - logger.info(f"Rapport JSON sauvegardĂ©: {json_path}") - - if args.format in ["md", "both"]: - md_path = os.path.join(rapport_dir, "ticket_analysis.md") - with open(md_path, 'w', encoding='utf-8') as f: - f.write(rapport_md) - logger.info(f"Rapport Markdown sauvegardĂ©: {md_path}") - - # Afficher un rĂ©sumĂ© - print("\nRĂ©sumĂ© de l'analyse:") - print(f"Ticket: {resultat.get('ticket_info', {}).get('code', 'N/A')} - {resultat.get('ticket_info', {}).get('name', 'Sans titre')}") - print(f"Messages analysĂ©s: {resultat.get('nb_messages', 0)}") - print(f"Sections extraites: {len(resultat.get('sections', {}))}") - - # Afficher un extrait du problème et de la solution - sections = resultat.get("sections", {}) - probleme = sections.get("problème", sections.get("probleme", "")) - solution = sections.get("solution", "") - - if probleme: - probleme_court = probleme[:150] + "..." if len(probleme) > 150 else probleme - print(f"\nProblème: {probleme_court}") - - if solution: - solution_court = solution[:150] + "..." if len(solution) > 150 else solution - print(f"\nSolution: {solution_court}") - - print(f"\nRappport complet sauvegardĂ© dans: {rapport_dir}") - - except Exception as e: - logger.error(f"Erreur lors de l'analyse: {str(e)}") - import traceback - logger.debug(f"DĂ©tails: {traceback.format_exc()}") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/scripts/extract_question_reponse.py b/scripts/extract_question_reponse.py deleted file mode 100644 index 1196a14..0000000 --- a/scripts/extract_question_reponse.py +++ /dev/null @@ -1,534 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script d'extraction des questions et rĂ©ponses d'un ticket. -GĂ©nère un tableau Markdown avec les questions et rĂ©ponses identifiĂ©es. -""" - -import os -import sys -import json -import argparse -import logging -import re -from typing import Dict, List, Any, Optional - -# Configuration du logger -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler("extract_qr.log"), - logging.StreamHandler() - ] -) -logger = logging.getLogger("extract_qr") - -try: - from llm import Mistral -except ImportError: - logger.error("Module LLM non trouvĂ©. Veuillez vous assurer que le rĂ©pertoire parent est dans PYTHONPATH.") - sys.exit(1) - -class QuestionReponseExtractor: - """ - Agent d'extraction des questions et rĂ©ponses d'un ticket. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'agent d'extraction de questions-rĂ©ponses. - - Args: - api_key: ClĂ© API pour le LLM - """ - self.llm = Mistral(api_key=api_key) - - # Configurer le LLM - try: - self.llm.model = "mistral-medium" - self.llm.temperature = 0.3 - self.llm.max_tokens = 2000 - except Exception as e: - logger.warning(f"Impossible de configurer le modèle: {e}") - - # DĂ©finir le prompt système par dĂ©faut - self.system_prompt = """ - Tu es un expert en analyse de conversations de support technique. - - Votre mission est d'identifier avec prĂ©cision: - 1. Le rĂ´le de chaque intervenant (client ou support technique) - 2. La nature de chaque message (question, rĂ©ponse, information additionnelle) - 3. Le contenu essentiel de chaque message en Ă©liminant les formules de politesse, - signatures, mentions lĂ©gales et autres Ă©lĂ©ments non pertinents - - Pour l'identification client/support: - - Support: Signatures avec noms d'entreprise fournissant le logiciel, domaines email - comme @cbao.fr, @odoo.com, mentions "support technique", etc. - - Client: Utilisateurs finaux qui signalent des problèmes ou posent des questions - - Pour la classification en question/rĂ©ponse: - - Questions: Demandes explicites (avec "?"), demandes implicites de rĂ©solution - de problèmes, descriptions de bugs ou dysfonctionnements - - RĂ©ponses: Explications techniques, solutions proposĂ©es, instructions fournies - par le support - - Concentre-toi uniquement sur le contenu technique utile en ignorant tous les - Ă©lĂ©ments superflus qui n'apportent pas d'information sur le problème ou sa solution. - """ - - self.historique = [] - - def ajouter_historique(self, action: str, entree: str, resultat: str) -> None: - """ - Ajoute une entrĂ©e Ă  l'historique des actions. - - Args: - action: Type d'action effectuĂ©e - entree: EntrĂ©e de l'action - resultat: RĂ©sultat de l'action - """ - self.historique.append({ - "action": action, - "entree": entree, - "resultat": resultat - }) - - def nettoyer_contenu(self, texte: str) -> str: - """ - Nettoie le contenu en supprimant signatures, mentions lĂ©gales, etc. - - Args: - texte: Texte brut Ă  nettoyer - - Returns: - Texte nettoyĂ© des Ă©lĂ©ments non pertinents - """ - # Si l'entrĂ©e n'est pas une chaĂ®ne, convertir en chaĂ®ne ou retourner vide - if not isinstance(texte, str): - if texte is None: - return "" - try: - texte = str(texte) - except: - return "" - - # DĂ©tecter et supprimer les balises HTML avec regex robuste - try: - # Première passe - balises standard - texte_nettoye = re.sub(r']*>', ' ', texte, flags=re.IGNORECASE) - - # Deuxième passe - balises restantes, y compris les mal formĂ©es - texte_nettoye = re.sub(r'<[^>]*>', ' ', texte_nettoye) - - # Troisième passe pour les balises qui pourraient avoir Ă©chappĂ© - texte_nettoye = re.sub(r'<[^>]*$', ' ', texte_nettoye) # Balises incomplètes Ă  la fin - except Exception as e: - logger.warning(f"Erreur lors du nettoyage HTML: {e}") - texte_nettoye = texte - - # Remplacer les rĂ©fĂ©rences aux images - texte_nettoye = re.sub(r'\[Image:[^\]]+\]', '[Image]', texte_nettoye) - texte_nettoye = re.sub(r']+>', '[Image]', texte_nettoye, flags=re.IGNORECASE) - - # Supprimer les Ă©lĂ©ments courants non pertinents - patterns_a_supprimer = [ - r'Cordialement,[\s\S]*?$', - r'Bien cordialement,[\s\S]*?$', - r'Bonne rĂ©ception[\s\S]*?$', - r'Ă€ votre disposition[\s\S]*?$', - r'Support technique[\s\S]*?$', - r'L\'objectif du Support Technique[\s\S]*?$', - r'Notre service est ouvert[\s\S]*?$', - r'Dès rĂ©ception[\s\S]*?$', - r'ConfidentialitĂ©[\s\S]*?$', - r'Ce message Ă©lectronique[\s\S]*?$', - r'Droit Ă  la dĂ©connexion[\s\S]*?$', - r'Afin d\'assurer une meilleure traçabilitĂ©[\s\S]*?$', - r'tĂ©l\s*:\s*[\d\s\+]+', - r'mobile\s*:\s*[\d\s\+]+', - r'www\.[^\s]+\.[a-z]{2,3}', - r'\*{10,}.*?\*{10,}', # Lignes de sĂ©paration avec astĂ©risques - r'----.*?----', # Lignes de sĂ©paration avec tirets - ] - - for pattern in patterns_a_supprimer: - texte_nettoye = re.sub(pattern, '', texte_nettoye, flags=re.IGNORECASE) - - # Supprimer les lignes multiples vides et espaces multiples - texte_nettoye = re.sub(r'\n\s*\n', '\n', texte_nettoye) - texte_nettoye = re.sub(r'\s+', ' ', texte_nettoye) - - # Convertir les entitĂ©s HTML - html_entities = { - ' ': ' ', '<': '<', '>': '>', '&': '&', - '"': '"', ''': "'", '€': '€', '©': '©', - '®': '®', 'é': 'Ă©', 'è': 'è', 'à': 'Ă ', - 'ç': 'ç', 'ê': 'ĂŞ', 'â': 'â', 'î': 'Ă®', - 'ô': 'Ă´', 'û': 'Ă»' - } - - for entity, char in html_entities.items(): - texte_nettoye = texte_nettoye.replace(entity, char) - - return texte_nettoye.strip() - - def detecter_role(self, message: Dict[str, Any]) -> str: - """ - DĂ©tecte si un message provient du client ou du support. - - Args: - message: Dictionnaire contenant les informations du message - - Returns: - "Client" ou "Support" - """ - # VĂ©rifier le champ 'role' s'il existe dĂ©jĂ  - if "role" in message and message["role"] in ["Client", "Support"]: - return message["role"] - - # Indices de support dans l'email - domaines_support = ["@cbao.fr", "@odoo.com", "support@", "ticket.support"] - indices_nom_support = ["support", "cbao", "technique", "odoo"] - - email = message.get("email_from", "").lower() - # Nettoyer le format "Nom " - if "<" in email and ">" in email: - match = re.search(r'<([^>]+)>', email) - if match: - email = match.group(1).lower() - - # VĂ©rifier le domaine email - if any(domaine in email for domaine in domaines_support): - return "Support" - - # VĂ©rifier le nom d'auteur - auteur = "" - if "author_id" in message and isinstance(message["author_id"], list) and len(message["author_id"]) > 1: - auteur = str(message["author_id"][1]).lower() - elif "auteur" in message: - auteur = str(message["auteur"]).lower() - - if any(indice in auteur for indice in indices_nom_support): - return "Support" - - # Par dĂ©faut, considĂ©rer comme client - return "Client" - - def extraire_questions_reponses(self, messages: List[Dict[str, Any]]) -> Dict[str, Any]: - """ - Extrait les questions et rĂ©ponses d'une liste de messages. - - Args: - messages: Liste des messages du ticket - - Returns: - Dictionnaire avec les questions et rĂ©ponses extraites - """ - if not messages: - logger.warning("Aucun message Ă  analyser") - return { - "success": False, - "erreur": "Aucun message Ă  analyser", - "paires_qr": [] - } - - logger.info(f"Extraction des questions et rĂ©ponses de {len(messages)} messages") - - # PrĂ©paration des messages - messages_prepares = [] - for msg in messages: - # Nettoyer le contenu - contenu = msg.get("body", "") or msg.get("contenu", "") - contenu_nettoye = self.nettoyer_contenu(contenu) - - # DĂ©tecter le rĂ´le - role = self.detecter_role(msg) - - # Ajouter le message prĂ©parĂ© si non vide après nettoyage - if contenu_nettoye.strip(): - messages_prepares.append({ - "id": msg.get("id", "") or msg.get("ID", ""), - "date": msg.get("date", ""), - "role": role, - "body": contenu_nettoye - }) - - # S'il n'y a pas assez de messages pour une conversation - if len(messages_prepares) < 2: - logger.warning("Pas assez de messages pour une conversation") - return { - "success": True, - "paires_qr": [], - "nb_questions": 0, - "nb_reponses": 0 - } - - # Trier par date si disponible - messages_prepares.sort(key=lambda x: x.get("date", "")) - - # PrĂ©parer l'entrĂ©e pour le LLM - messages_for_llm = [] - for i, msg in enumerate(messages_prepares): - messages_for_llm.append({ - "numero": i + 1, - "role": msg.get("role", "Inconnu"), - "date": msg.get("date", ""), - "contenu": msg.get("body", "") - }) - - # PrĂ©parer le prompt pour extraire les paires Q/R - prompt = """ - Analyse la conversation suivante et identifie toutes les paires de questions et rĂ©ponses. - - Pour chaque message: - 1. Identifie s'il s'agit d'une question, d'une rĂ©ponse ou d'une information. - 2. Extrais le contenu essentiel en ignorant les formules de politesse et les signatures. - - Ensuite, forme des paires de questions-rĂ©ponses en associant chaque question avec sa rĂ©ponse correspondante. - - RĂ©ponds en utilisant la structure suivante: - - ``` - MESSAGE 1: - - RĂ´le: [Client/Support] - - Type: [Question/RĂ©ponse/Information] - - Contenu essentiel: [Contenu essentiel du message] - - MESSAGE 2: - ... - - PAIRE 1: - - Question (Client): [Question posĂ©e] - - RĂ©ponse (Support): [RĂ©ponse donnĂ©e] - - PAIRE 2: - ... - ``` - - Si une question n'a pas de rĂ©ponse, indique-le. - """ - - try: - # Appeler le LLM pour l'analyse - from json import dumps - resultat = self.llm.chat_completion([ - {"role": "system", "content": self.system_prompt}, - {"role": "user", "content": prompt + "\n\nConversation:\n" + dumps(messages_for_llm, indent=2)} - ]) - - contenu = resultat.get("choices", [{}])[0].get("message", {}).get("content", "") - self.ajouter_historique("analyze_messages", f"{len(messages)} messages", "Analyse effectuĂ©e") - - # Traiter la rĂ©ponse pour extraire les messages analysĂ©s - messages_analyses = [] - pattern_messages = r"MESSAGE (\d+):\s*- RĂ´le: (Client|Support)\s*- Type: (Question|RĂ©ponse|Information)\s*- Contenu essentiel: (.*?)(?=MESSAGE \d+:|PAIRE \d+:|$)" - for match in re.finditer(pattern_messages, contenu, re.DOTALL): - num = int(match.group(1)) - role = match.group(2) - type_msg = match.group(3) - contenu_essentiel = match.group(4).strip() - - # Trouver le message correspondant - msg_idx = num - 1 - msg_id = "" - msg_date = "" - - if 0 <= msg_idx < len(messages_for_llm): - original_idx = messages_for_llm[msg_idx]["numero"] - 1 - if 0 <= original_idx < len(messages_prepares): - msg_id = messages_prepares[original_idx].get("id", "") - msg_date = messages_prepares[original_idx].get("date", "") - - messages_analyses.append({ - "id": msg_id, - "date": msg_date, - "role": role, - "type": type_msg, - "contenu": contenu_essentiel - }) - - # Extraire les paires QR - paires_qr = [] - pattern_paires = r"PAIRE (\d+):\s*- Question \((Client|Support)\): (.*?)(?:\s*- RĂ©ponse \((Client|Support)\): (.*?))?(?=PAIRE \d+:|$)" - for match in re.finditer(pattern_paires, contenu, re.DOTALL): - num = match.group(1) - q_role = match.group(2) - question = match.group(3).strip() - r_role = match.group(4) if match.group(4) else "" - reponse = match.group(5).strip() if match.group(5) else "" - - paires_qr.append({ - "numero": num, - "question": { - "role": q_role, - "contenu": question - }, - "reponse": { - "role": r_role, - "contenu": reponse - } if reponse else None - }) - - return { - "success": True, - "messages_analyses": messages_analyses, - "paires_qr": paires_qr, - "nb_questions": len(paires_qr), - "nb_reponses": sum(1 for p in paires_qr if p.get("reponse")) - } - - except Exception as e: - erreur = f"Erreur lors de l'extraction des questions et rĂ©ponses: {str(e)}" - logger.error(erreur) - return { - "success": False, - "erreur": erreur, - "paires_qr": [] - } - - def generer_tableau_markdown(self, paires_qr: List[Dict[str, Any]]) -> str: - """ - GĂ©nère un tableau Markdown avec les questions et rĂ©ponses. - - Args: - paires_qr: Liste de paires question/rĂ©ponse - - Returns: - Tableau Markdown formatĂ© - """ - # CrĂ©er le tableau - markdown = ["# Analyse des Questions et RĂ©ponses\n"] - markdown.append("| Question | RĂ©ponse |") - markdown.append("|---------|---------|") - - if not paires_qr: - # Si aucune paire n'a Ă©tĂ© trouvĂ©e, laisser le tableau vide - pass - else: - for paire in paires_qr: - question = paire.get("question", {}) - reponse = paire.get("reponse", {}) - - q_role = question.get("role", "Client") - q_contenu = question.get("contenu", "") - - if reponse: - r_role = reponse.get("role", "Support") - r_contenu = reponse.get("contenu", "") - - markdown.append(f"| **{q_role}**: {q_contenu} | **{r_role}**: {r_contenu} |") - else: - markdown.append(f"| **{q_role}**: {q_contenu} | *Pas de rĂ©ponse* |") - - # Ajouter les informations sur les paramètres LLM utilisĂ©s - markdown.append("\n## Paramètres LLM utilisĂ©s\n") - - markdown.append(f"- **Type de LLM**: Mistral") - markdown.append(f"- **Modèle**: {getattr(self.llm, 'model', 'mistral-medium')}") - markdown.append(f"- **TempĂ©rature**: {getattr(self.llm, 'temperature', 0.3)}") - markdown.append(f"- **Tokens max**: {getattr(self.llm, 'max_tokens', 2000)}") - - return "\n".join(markdown) - -def charger_config(): - """ - Charge la configuration depuis config.json. - - Returns: - Configuration chargĂ©e - """ - config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config.json") - - if not os.path.exists(config_path): - logger.warning(f"Fichier de configuration non trouvĂ©: {config_path}") - return {"llm": {"api_key": None}} - - try: - with open(config_path, 'r', encoding='utf-8') as f: - config = json.load(f) - return config - except Exception as e: - logger.error(f"Erreur lors du chargement de la configuration: {str(e)}") - return {"llm": {"api_key": None}} - -def main(): - """ - Point d'entrĂ©e du script. - """ - parser = argparse.ArgumentParser(description="Extrait les questions et rĂ©ponses d'un ticket de support.") - parser.add_argument("--messages", "-m", required=True, help="Chemin vers le fichier messages.json") - parser.add_argument("--output", "-o", help="Chemin du fichier de sortie pour le tableau Markdown (par dĂ©faut: /questions_reponses.md)") - parser.add_argument("--verbose", "-v", action="store_true", help="Afficher plus d'informations") - - args = parser.parse_args() - - # Configurer le niveau de log - if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - # VĂ©rifier que le fichier messages existe - if not os.path.exists(args.messages): - logger.error(f"Fichier de messages non trouvĂ©: {args.messages}") - sys.exit(1) - - # Charger les messages - try: - with open(args.messages, 'r', encoding='utf-8') as f: - messages = json.load(f) - - if not isinstance(messages, list): - logger.error(f"Format de fichier messages.json invalide. Une liste est attendue.") - sys.exit(1) - except Exception as e: - logger.error(f"Erreur lors du chargement des messages: {str(e)}") - sys.exit(1) - - # DĂ©terminer le chemin de sortie - output_path = args.output - if not output_path: - # Par dĂ©faut, utiliser le mĂŞme rĂ©pertoire que le fichier messages - output_dir = os.path.dirname(args.messages) - if not output_dir: - output_dir = "." - output_path = os.path.join(output_dir, "questions_reponses.md") - - # Charger la configuration - config = charger_config() - api_key = config.get("llm", {}).get("api_key") - - # Initialiser l'extracteur de questions-rĂ©ponses - extractor = QuestionReponseExtractor(api_key=api_key) - - try: - # Extraire les questions et rĂ©ponses - resultats = extractor.extraire_questions_reponses(messages) - - if not resultats.get("success", False): - logger.error(f"Échec de l'extraction: {resultats.get('erreur', 'Erreur inconnue')}") - sys.exit(1) - - # GĂ©nĂ©rer le tableau Markdown - tableau_md = extractor.generer_tableau_markdown(resultats.get("paires_qr", [])) - - # Sauvegarder le tableau - with open(output_path, 'w', encoding='utf-8') as f: - f.write(tableau_md) - - logger.info(f"Tableau Markdown sauvegardĂ©: {output_path}") - - # Afficher un rĂ©sumĂ© - print("\nRĂ©sumĂ© de l'extraction:") - print(f"Messages analysĂ©s: {len(messages)}") - print(f"Questions extraites: {resultats.get('nb_questions', 0)}") - print(f"RĂ©ponses extraites: {resultats.get('nb_reponses', 0)}") - print(f"Tableau Markdown sauvegardĂ©: {output_path}") - - except Exception as e: - logger.error(f"Erreur lors de l'extraction: {str(e)}") - import traceback - logger.debug(f"DĂ©tails: {traceback.format_exc()}") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/scripts/extract_ticket.py b/scripts/extract_ticket.py deleted file mode 100644 index e89d6a4..0000000 --- a/scripts/extract_ticket.py +++ /dev/null @@ -1,504 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script d'extraction et de prĂ©traitement des tickets. -Nettoie les donnĂ©es et sĂ©pare les pièces jointes des messages. -""" - -import os -import sys -import json -import re -import shutil -import argparse -import unicodedata -from typing import Dict, List, Any, Optional -from bs4 import BeautifulSoup -import logging - -# Configuration du logger -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler("extract_ticket.log"), - logging.StreamHandler() - ] -) -logger = logging.getLogger("extract_ticket") - -def nettoyer_html(texte: str) -> str: - """ - Nettoie le contenu HTML en utilisant BeautifulSoup. - - Args: - texte: Texte HTML Ă  nettoyer - - Returns: - Texte nettoyĂ© - """ - if not texte: - return "" - - if not isinstance(texte, str): - try: - texte = str(texte) - except Exception as e: - logger.warning(f"Impossible de convertir en texte: {e}") - return "" - - # Utiliser BeautifulSoup pour le nettoyage - try: - soup = BeautifulSoup(texte, 'html.parser') - texte_nettoye = soup.get_text(separator=' ') - except Exception as e: - logger.warning(f"Erreur lors du nettoyage HTML avec BeautifulSoup: {e}") - # Fallback Ă  regex si BeautifulSoup Ă©choue - try: - texte_nettoye = re.sub(r'<[^>]+>', ' ', texte) - except Exception as e: - logger.warning(f"Erreur lors du nettoyage HTML avec regex: {e}") - texte_nettoye = texte - - # Remplacer les rĂ©fĂ©rences aux images - texte_nettoye = re.sub(r'\[Image:[^\]]+\]', '[Image]', texte_nettoye) - - # Supprimer les Ă©lĂ©ments courants non pertinents - patterns_a_supprimer = [ - r'Cordialement,[\s\S]*?$', - r'Bien cordialement,[\s\S]*?$', - r'Bonne rĂ©ception[\s\S]*?$', - r'Ă€ votre disposition[\s\S]*?$', - r'Support technique[\s\S]*?$', - r'L\'objectif du Support Technique[\s\S]*?$', - r'Notre service est ouvert[\s\S]*?$', - r'Dès rĂ©ception[\s\S]*?$', - r'ConfidentialitĂ©[\s\S]*?$', - r'Ce message Ă©lectronique[\s\S]*?$', - r'Droit Ă  la dĂ©connexion[\s\S]*?$', - r'Afin d\'assurer une meilleure traçabilitĂ©[\s\S]*?$', - r'tĂ©l\s*:\s*[\d\s\+]+', - r'mobile\s*:\s*[\d\s\+]+', - r'www\.[^\s]+\.[a-z]{2,3}', - ] - - for pattern in patterns_a_supprimer: - texte_nettoye = re.sub(pattern, '', texte_nettoye, flags=re.IGNORECASE) - - # Supprimer les lignes multiples vides - texte_nettoye = re.sub(r'\n\s*\n', '\n', texte_nettoye) - - # Supprimer les espaces multiples - texte_nettoye = re.sub(r'\s+', ' ', texte_nettoye) - - # Normaliser les caractères accentuĂ©s - texte_nettoye = normaliser_accents(texte_nettoye) - - return texte_nettoye.strip() - -def normaliser_accents(texte: str) -> str: - """ - Normalise les caractères accentuĂ©s pour Ă©viter les problèmes d'encodage. - - Args: - texte: Texte Ă  normaliser - - Returns: - Texte avec caractères accentuĂ©s normalisĂ©s - """ - if not isinstance(texte, str): - if texte is None: - return "" - try: - texte = str(texte) - except: - return "" - - # Convertir les caractères spĂ©ciaux HTML - special_chars = { - 'á': 'á', 'é': 'Ă©', 'í': 'Ă­', 'ó': 'Ăł', 'ú': 'Ăş', - 'Á': 'Ă', 'É': 'É', 'Í': 'ĂŤ', 'Ó': 'Ă“', 'Ú': 'Ăš', - 'à': 'Ă ', 'è': 'è', 'ì': 'ì', 'ò': 'ò', 'ù': 'Ăą', - 'À': 'Ă€', 'È': 'Ă', 'Ì': 'ĂŚ', 'Ò': 'Ă’', 'Ù': 'Ă™', - 'â': 'â', 'ê': 'ĂŞ', 'î': 'Ă®', 'ô': 'Ă´', 'û': 'Ă»', - 'Â': 'Ă‚', 'Ê': 'ĂŠ', 'Î': 'ĂŽ', 'Ô': 'Ă”', 'Û': 'Ă›', - 'ã': 'ĂŁ', '&etilde;': 'áş˝', 'ĩ': 'Ä©', 'õ': 'õ', 'ũ': 'Ĺ©', - 'Ã': 'Ă', '&Etilde;': 'Ẽ', 'Ĩ': 'Ĩ', 'Õ': 'Ă•', 'Ũ': 'Ũ', - 'ä': 'ä', 'ë': 'Ă«', 'ï': 'ĂŻ', 'ö': 'ö', 'ü': 'ĂĽ', - 'Ä': 'Ă„', 'Ë': 'Ă‹', 'Ï': 'ĂŹ', 'Ö': 'Ă–', 'Ü': 'Ăś', - 'ç': 'ç', 'Ç': 'Ç', 'ñ': 'ñ', 'Ñ': 'Ă‘', - ' ': ' ', '<': '<', '>': '>', '&': '&', '"': '"', ''': "'", - '€': '€', '©': '©', '®': '®', '™': '™' - } - - for html, char in special_chars.items(): - texte = texte.replace(html, char) - - # Normaliser les caractères composĂ©s - return unicodedata.normalize('NFC', texte) - -def detecter_role(message: Dict[str, Any]) -> str: - """ - DĂ©tecte si un message provient du client ou du support. - - Args: - message: Dictionnaire contenant les informations du message - - Returns: - "Client" ou "Support" - """ - # VĂ©rifier le champ 'role' s'il existe dĂ©jĂ  - if "role" in message and message["role"] in ["Client", "Support"]: - return message["role"] - - # Indices de support dans l'email - domaines_support = ["@cbao.fr", "@odoo.com", "support@", "ticket.support"] - indices_nom_support = ["support", "cbao", "technique", "odoo"] - - email = message.get("email_from", "").lower() - # Nettoyer le format "Nom " - if "<" in email and ">" in email: - match = re.search(r'<([^>]+)>', email) - if match: - email = match.group(1).lower() - - # VĂ©rifier le domaine email - if any(domaine in email for domaine in domaines_support): - return "Support" - - # VĂ©rifier le nom d'auteur - auteur = "" - if "author_id" in message and isinstance(message["author_id"], list) and len(message["author_id"]) > 1: - auteur = str(message["author_id"][1]).lower() - elif "auteur" in message: - auteur = str(message["auteur"]).lower() - - if any(indice in auteur for indice in indices_nom_support): - return "Support" - - # Par dĂ©faut, considĂ©rer comme client - return "Client" - -def pretraiter_ticket(input_dir: str, output_dir: str) -> Dict[str, Any]: - """ - PrĂ©traite les donnĂ©es d'un ticket et les sĂ©pare en fichiers distincts. - - Args: - input_dir: RĂ©pertoire contenant les donnĂ©es brutes du ticket - output_dir: RĂ©pertoire oĂą sauvegarder les donnĂ©es prĂ©traitĂ©es - - Returns: - Rapport de prĂ©traitement avec les fichiers gĂ©nĂ©rĂ©s - """ - logger.info(f"PrĂ©traitement du ticket: {input_dir} -> {output_dir}") - - # CrĂ©er le rĂ©pertoire de sortie s'il n'existe pas - os.makedirs(output_dir, exist_ok=True) - - # CrĂ©er les sous-rĂ©pertoires - attachments_dir = os.path.join(output_dir, "attachments") - os.makedirs(attachments_dir, exist_ok=True) - - # Chemins des fichiers d'entrĂ©e - ticket_info_path = os.path.join(input_dir, "ticket_info.json") - messages_path = os.path.join(input_dir, "messages.json") - messages_backup_path = os.path.join(input_dir, "messages.json.backup") - - # Rapport de prĂ©traitement - rapport = { - "ticket_id": os.path.basename(input_dir), - "fichiers_generes": [], - "erreurs": [] - } - - # PrĂ©traiter ticket_info.json - if os.path.exists(ticket_info_path): - try: - with open(ticket_info_path, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - - # Nettoyer la description - if isinstance(ticket_info, dict) and "description" in ticket_info: - ticket_info["description"] = nettoyer_html(ticket_info["description"]) - - # Sauvegarder dans le rĂ©pertoire de sortie - output_ticket_info_path = os.path.join(output_dir, "ticket_info.json") - with open(output_ticket_info_path, 'w', encoding='utf-8') as f: - json.dump(ticket_info, f, indent=2, ensure_ascii=False) - - rapport["fichiers_generes"].append("ticket_info.json") - logger.info(f"Ticket info prĂ©traitĂ© et sauvegardĂ©: {output_ticket_info_path}") - - except Exception as e: - erreur = f"Erreur lors du prĂ©traitement de ticket_info.json: {str(e)}" - rapport["erreurs"].append(erreur) - logger.error(erreur) - else: - erreur = f"Fichier ticket_info.json non trouvĂ© dans {input_dir}" - rapport["erreurs"].append(erreur) - logger.warning(erreur) - - # PrĂ©traiter messages.json - messages_content = None - - # D'abord essayer messages.json - if os.path.exists(messages_path): - try: - with open(messages_path, 'r', encoding='utf-8') as f: - messages_content = f.read() - except Exception as e: - logger.warning(f"Impossible de lire messages.json: {str(e)}") - - # Si messages.json est vide ou corrompu, essayer la sauvegarde - if not messages_content and os.path.exists(messages_backup_path): - try: - with open(messages_backup_path, 'r', encoding='utf-8') as f: - messages_content = f.read() - logger.info("Utilisation de messages.json.backup comme source") - except Exception as e: - erreur = f"Impossible de lire messages.json.backup: {str(e)}" - rapport["erreurs"].append(erreur) - logger.error(erreur) - - # Traiter les messages si nous avons un contenu valide - if messages_content: - try: - messages = json.loads(messages_content) - - # CrĂ©er une version amĂ©liorĂ©e des messages - processed_messages = [] - - # DĂ©terminer le code du ticket Ă  partir du nom du rĂ©pertoire - ticket_code = os.path.basename(input_dir) - if ticket_code.startswith("ticket_"): - ticket_code = ticket_code[7:] # Extraire le code sans "ticket_" - - # Extraire les informations du ticket si disponibles - ticket_info_dict = {} - if os.path.exists(ticket_info_path): - try: - with open(ticket_info_path, 'r', encoding='utf-8') as f: - ticket_info_dict = json.load(f) - except Exception: - pass - - # CrĂ©er le message de contexte avec les informations du ticket - ticket_name = ticket_info_dict.get("name", f"Ticket {ticket_code}") - ticket_description = ticket_info_dict.get("description", "") - ticket_date = ticket_info_dict.get("create_date", "") - - # Nettoyer les informations du ticket - ticket_name = normaliser_accents(ticket_name) - ticket_description = nettoyer_html(ticket_description) - - ticket_context = { - "id": "ticket_info", - "name": ticket_name, - "code": ticket_code, - "description": ticket_description, - "date_create": ticket_date, - "role": "system", - "type": "contexte", - "body": f"TICKET {ticket_code}: {ticket_name}.\n\nDESCRIPTION: {ticket_description or 'Aucune description disponible.'}" - } - processed_messages.append(ticket_context) - - # PrĂ©traiter chaque message - attachments_info = [] - valid_messages = 0 - - for msg in messages: - if not isinstance(msg, dict): - continue - - # Ignorer les messages vides - body = msg.get("body", "") - if not body or not isinstance(body, str): - continue - - # DĂ©tecter le rĂ´le - role = detecter_role(msg) - message_type = "Question" if role == "Client" else "RĂ©ponse" - - # Nettoyer le contenu - contenu_nettoye = nettoyer_html(body) - if not contenu_nettoye: - continue - - # Normaliser les champs textuels - email_from = normaliser_accents(msg.get("email_from", "")) - subject = normaliser_accents(msg.get("subject", "")) - - # GĂ©rer l'identifiant du message - msg_id = msg.get("id", f"msg_{valid_messages+1}") - if not isinstance(msg_id, str): - try: - msg_id = str(msg_id) - except: - msg_id = f"msg_{valid_messages+1}" - - # RĂ©cupĂ©rer les autres champs de manière sĂ©curisĂ©e - author_id = msg.get("author_id", [0, ""]) - if not isinstance(author_id, list): - author_id = [0, ""] - - date = msg.get("date", "") - if not isinstance(date, str): - try: - date = str(date) - except: - date = "" - - # Traiter les pièces jointes si prĂ©sentes - if "attachments" in msg and isinstance(msg["attachments"], list): - for attachment in msg["attachments"]: - if not isinstance(attachment, dict): - continue - - attachment_data = attachment.get("datas") - attachment_name = attachment.get("name", "") - attachment_type = attachment.get("mimetype", "") - - if attachment_data and attachment_name: - # GĂ©nĂ©rer un nom de fichier unique - attachment_id = attachment.get("id", len(attachments_info) + 1) - safe_name = f"{attachment_id}_{attachment_name}" - file_path = os.path.join(attachments_dir, safe_name) - - # Traiter diffĂ©remment selon le type de pièce jointe - if attachment_type.startswith("image/"): - try: - # Sauvegarder l'image - import base64 - with open(file_path, 'wb') as f: - f.write(base64.b64decode(attachment_data)) - - # Ajouter l'information Ă  la liste des pièces jointes - attachments_info.append({ - "id": attachment_id, - "name": attachment_name, - "mimetype": attachment_type, - "message_id": msg_id, - "date": date, - "file_path": file_path - }) - - logger.info(f"Pièce jointe sauvegardĂ©e: {file_path}") - except Exception as e: - logger.warning(f"Erreur lors de la sauvegarde de la pièce jointe {attachment_name}: {str(e)}") - - # CrĂ©er le message transformĂ© - processed_message = { - "id": msg_id, - "author_id": author_id, - "role": role, - "type": message_type, - "date": date, - "email_from": email_from, - "subject": subject, - "body": contenu_nettoye - } - - processed_messages.append(processed_message) - valid_messages += 1 - - # Trier par date (sauf le premier message qui est le contexte) - try: - processed_messages[1:] = sorted(processed_messages[1:], key=lambda x: x.get("date", "")) - except Exception as e: - logger.warning(f"Impossible de trier les messages par date: {e}") - - # Sauvegarder les messages prĂ©traitĂ©s - output_messages_path = os.path.join(output_dir, "messages.json") - with open(output_messages_path, 'w', encoding='utf-8') as f: - json.dump(processed_messages, f, indent=2, ensure_ascii=False) - - rapport["fichiers_generes"].append("messages.json") - logger.info(f"Messages prĂ©traitĂ©s et sauvegardĂ©s: {output_messages_path} ({valid_messages} messages)") - - # Sauvegarder les informations sur les pièces jointes - if attachments_info: - output_attachments_info_path = os.path.join(output_dir, "attachments_info.json") - with open(output_attachments_info_path, 'w', encoding='utf-8') as f: - json.dump(attachments_info, f, indent=2, ensure_ascii=False) - - rapport["fichiers_generes"].append("attachments_info.json") - rapport["nb_attachments"] = len(attachments_info) - logger.info(f"Informations sur les pièces jointes sauvegardĂ©es: {output_attachments_info_path} ({len(attachments_info)} pièces jointes)") - - except Exception as e: - erreur = f"Erreur lors du prĂ©traitement des messages: {str(e)}" - rapport["erreurs"].append(erreur) - logger.error(erreur) - else: - erreur = "Aucun fichier messages.json ou messages.json.backup trouvĂ© ou lisible" - rapport["erreurs"].append(erreur) - logger.error(erreur) - - # Sauvegarder le rapport de prĂ©traitement - rapport_path = os.path.join(output_dir, "pretraitement_rapport.json") - with open(rapport_path, 'w', encoding='utf-8') as f: - json.dump(rapport, f, indent=2, ensure_ascii=False) - - logger.info(f"Rapport de prĂ©traitement sauvegardĂ©: {rapport_path}") - - return rapport - -def main(): - """ - Point d'entrĂ©e du script. - """ - parser = argparse.ArgumentParser(description="PrĂ©traite les donnĂ©es d'un ticket.") - parser.add_argument("input_dir", help="RĂ©pertoire contenant les donnĂ©es brutes du ticket") - parser.add_argument("--output-dir", help="RĂ©pertoire oĂą sauvegarder les donnĂ©es prĂ©traitĂ©es (par dĂ©faut: _processed)") - parser.add_argument("--verbose", "-v", action="store_true", help="Afficher plus d'informations") - - args = parser.parse_args() - - # Configurer le niveau de log - if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - # DĂ©terminer le rĂ©pertoire de sortie - input_dir = args.input_dir - if not os.path.isdir(input_dir): - logger.error(f"Le rĂ©pertoire d'entrĂ©e n'existe pas: {input_dir}") - sys.exit(1) - - output_dir = args.output_dir - if not output_dir: - # Par dĂ©faut, ajouter "_processed" au nom du rĂ©pertoire d'entrĂ©e - if input_dir.endswith("/"): - input_dir = input_dir[:-1] - output_dir = input_dir + "_processed" - - # PrĂ©traiter le ticket - try: - rapport = pretraiter_ticket(input_dir, output_dir) - - # Afficher un rĂ©sumĂ© - print("\nRĂ©sumĂ© du prĂ©traitement:") - print(f"Ticket: {rapport['ticket_id']}") - print(f"Fichiers gĂ©nĂ©rĂ©s: {len(rapport['fichiers_generes'])}") - for fichier in rapport['fichiers_generes']: - print(f" - {fichier}") - - if "nb_attachments" in rapport: - print(f"Pièces jointes: {rapport['nb_attachments']}") - - if rapport['erreurs']: - print(f"Erreurs: {len(rapport['erreurs'])}") - for erreur in rapport['erreurs']: - print(f" - {erreur}") - else: - print("Aucune erreur") - - print(f"\nPrĂ©traitement terminĂ©. DonnĂ©es sauvegardĂ©es dans: {output_dir}") - - except Exception as e: - logger.error(f"Erreur lors du prĂ©traitement: {str(e)}") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/scripts/filter_images.py b/scripts/filter_images.py deleted file mode 100644 index f0b783d..0000000 --- a/scripts/filter_images.py +++ /dev/null @@ -1,380 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script de filtrage des images pertinentes dans un ticket. -Identifie et sĂ©pare les images utiles des images non pertinentes. -""" - -import os -import sys -import json -import argparse -import logging -import datetime -import re -from typing import Dict, List, Any, Optional - -# Configuration du logger -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler("filter_images.log"), - logging.StreamHandler() - ] -) -logger = logging.getLogger("filter_images") - -try: - from llm import Pixtral # Importer le modèle d'analyse d'images -except ImportError: - logger.error("Module LLM non trouvĂ©. Veuillez vous assurer que le rĂ©pertoire parent est dans PYTHONPATH.") - sys.exit(1) - -class ImageFilterAgent: - """ - Agent responsable du filtrage des images pertinentes. - """ - def __init__(self, api_key: Optional[str] = None): - """ - Initialise l'agent de filtrage d'images. - - Args: - api_key: ClĂ© API pour le modèle de vision - """ - self.llm = Pixtral(api_key=api_key) - # Configurer le modèle de vision - self.llm.set_model("pixtral-12b-2409") - self.llm.set_temperature(0.2) - self.llm.set_max_tokens(500) - self.historique = [] - - def ajouter_historique(self, action: str, entree: str, resultat: str) -> None: - """ - Ajoute une entrĂ©e Ă  l'historique des actions. - - Args: - action: Type d'action effectuĂ©e - entree: EntrĂ©e de l'action - resultat: RĂ©sultat de l'action - """ - self.historique.append({ - "action": action, - "entree": entree, - "resultat": resultat, - "timestamp": datetime.datetime.now().isoformat() - }) - - def est_image_pertinente(self, image_path: str, contexte: Optional[str] = None) -> Dict[str, Any]: - """ - DĂ©termine si une image est pertinente pour l'analyse du ticket. - - Args: - image_path: Chemin vers l'image Ă  analyser - contexte: Contexte du ticket pour aider Ă  l'analyse - - Returns: - RĂ©sultat de l'analyse avec la pertinence et le type d'image - """ - if not os.path.exists(image_path): - logger.warning(f"Image introuvable: {image_path}") - return { - "pertinente": False, - "type_image": "inconnue", - "description": "Image introuvable", - "erreur": "Fichier non trouvĂ©" - } - - try: - # PrĂ©parer le prompt pour l'analyse - prompt_base = """ - Tu es un expert en analyse d'images techniques pour le support informatique. - - Analyse cette image et dĂ©termine si elle est pertinente pour comprendre le problème technique dĂ©crit. - - Une image pertinente est: - - Une capture d'Ă©cran montrant une interface, une erreur, ou une fonctionnalitĂ© logicielle - - Un schĂ©ma technique ou une illustration du problème - - Une photo d'un Ă©quipement ou d'un matĂ©riel en lien avec le ticket - - Une image non pertinente est: - - Un logo, une signature, ou une image dĂ©corative - - Une photo de personne sans lien avec le problème technique - - Une image gĂ©nĂ©rique non liĂ©e au contexte du ticket - - RĂ©ponds au format JSON avec les champs suivants: - - pertinente: boolean (true/false) - - type_image: string (capture_ecran, schĂ©ma, photo_Ă©quipement, logo, autre) - - description: string (description courte de ce que l'image montre) - - confiance: integer (niveau de confiance de 0 Ă  100) - - justification: string (pourquoi cette image est pertinente ou non) - """ - - # Ajouter le contexte si disponible - if contexte: - prompt_base += f"\n\nContexte du ticket:\n{contexte}" - - # Analyser l'image avec le modèle de vision - try: - resultat = self.llm.analyze_image(image_path, prompt_base) - self.ajouter_historique("analyze_image", os.path.basename(image_path), "Analyse effectuĂ©e") - except Exception as e: - logger.error(f"Erreur lors de l'appel au modèle de vision: {str(e)}") - return { - "pertinente": False, - "type_image": "inconnue", - "description": "Erreur d'analyse", - "erreur": str(e) - } - - # Extraire le JSON de la rĂ©ponse - json_match = re.search(r'```json\s*(.*?)\s*```', resultat.get("content", ""), re.DOTALL) - - if json_match: - try: - analyse = json.loads(json_match.group(1)) - return analyse - except Exception as e: - logger.error(f"Erreur lors du parsing JSON: {str(e)}") - else: - # Essayer de trouver un JSON sans les backticks - try: - # Nettoyer la rĂ©ponse pour essayer d'extraire le JSON - content = resultat.get("content", "") - # Trouver les accolades ouvrantes et fermantes - start_idx = content.find('{') - end_idx = content.rfind('}') - - if start_idx != -1 and end_idx != -1: - json_str = content[start_idx:end_idx+1] - analyse = json.loads(json_str) - return analyse - except Exception as e: - logger.error(f"Impossible d'extraire le JSON de la rĂ©ponse: {str(e)}") - - # Si on n'a pas pu extraire le JSON, analyser manuellement la rĂ©ponse - content = resultat.get("content", "").lower() - est_pertinente = "pertinente" in content and not "non pertinente" in content - - return { - "pertinente": est_pertinente, - "type_image": "inconnue" if not est_pertinente else "autre", - "description": "Analyse non structurĂ©e disponible", - "confiance": 50, - "reponse_brute": resultat.get("content", "") - } - - except Exception as e: - logger.error(f"Erreur lors de l'analyse de l'image {image_path}: {str(e)}") - return { - "pertinente": False, - "type_image": "inconnue", - "description": "Erreur lors de l'analyse", - "erreur": str(e) - } - - def filtrer_images(self, images_paths: List[str], contexte: Optional[str] = None) -> Dict[str, Any]: - """ - Analyse et filtre une liste d'images pour identifier celles qui sont pertinentes. - - Args: - images_paths: Liste des chemins vers les images Ă  analyser - contexte: Contexte du ticket pour aider Ă  l'analyse - - Returns: - Rapport de filtrage avec les images pertinentes et non pertinentes - """ - logger.info(f"Filtrage de {len(images_paths)} images...") - - resultats = { - "images_pertinentes": [], - "images_non_pertinentes": [], - "erreurs": [], - "analyses": {} - } - - for image_path in images_paths: - logger.info(f"Analyse de l'image: {os.path.basename(image_path)}") - - # VĂ©rifier que le fichier existe et est une image - if not os.path.exists(image_path): - logger.warning(f"Image introuvable: {image_path}") - resultats["erreurs"].append(f"Image introuvable: {image_path}") - continue - - # VĂ©rifier l'extension pour s'assurer que c'est une image - _, extension = os.path.splitext(image_path) - if extension.lower() not in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']: - logger.warning(f"Format de fichier non supportĂ©: {image_path}") - resultats["erreurs"].append(f"Format de fichier non supportĂ©: {image_path}") - continue - - # Analyser l'image - analyse = self.est_image_pertinente(image_path, contexte) - - # Ajouter Ă  la catĂ©gorie appropriĂ©e - if "erreur" in analyse: - resultats["erreurs"].append(f"Erreur d'analyse pour {os.path.basename(image_path)}: {analyse['erreur']}") - resultats["analyses"][os.path.basename(image_path)] = analyse - elif analyse.get("pertinente", False): - resultats["images_pertinentes"].append(image_path) - resultats["analyses"][os.path.basename(image_path)] = analyse - logger.info(f"Image pertinente: {os.path.basename(image_path)} - {analyse.get('type_image', 'type inconnu')}") - else: - resultats["images_non_pertinentes"].append(image_path) - resultats["analyses"][os.path.basename(image_path)] = analyse - logger.info(f"Image non pertinente: {os.path.basename(image_path)}") - - logger.info(f"Filtrage terminĂ©. {len(resultats['images_pertinentes'])} images pertinentes, {len(resultats['images_non_pertinentes'])} non pertinentes, {len(resultats['erreurs'])} erreurs.") - return resultats - -def charger_config(): - """ - Charge la configuration depuis config.json. - - Returns: - Configuration chargĂ©e - """ - config_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config.json") - - if not os.path.exists(config_path): - logger.warning(f"Fichier de configuration non trouvĂ©: {config_path}") - return {"llm": {"api_key": None}} - - try: - with open(config_path, 'r', encoding='utf-8') as f: - config = json.load(f) - return config - except Exception as e: - logger.error(f"Erreur lors du chargement de la configuration: {str(e)}") - return {"llm": {"api_key": None}} - -def main(): - """ - Point d'entrĂ©e du script. - """ - parser = argparse.ArgumentParser(description="Filtre les images pertinentes dans un ticket.") - parser.add_argument("--images", "-i", nargs="+", help="Liste des chemins vers les images Ă  filtrer") - parser.add_argument("--contexte", "-c", help="Fichier JSON contenant le contexte du ticket") - parser.add_argument("--dossier-ticket", "-d", help="Dossier du ticket contenant attachments/ et ticket_info.json") - parser.add_argument("--output", "-o", help="Chemin du fichier de sortie pour le rapport JSON (par dĂ©faut: filter_report.json)") - parser.add_argument("--verbose", "-v", action="store_true", help="Afficher plus d'informations") - - args = parser.parse_args() - - # Configurer le niveau de log - if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - # Charger la configuration - config = charger_config() - api_key = config.get("llm", {}).get("api_key") - - # Initialiser l'agent de filtrage - agent = ImageFilterAgent(api_key=api_key) - - # DĂ©terminer les images Ă  filtrer - images_paths = [] - contexte = None - - if args.images: - images_paths = args.images - elif args.dossier_ticket: - # Chercher dans le dossier attachments/ du ticket - attachments_dir = os.path.join(args.dossier_ticket, "attachments") - if os.path.isdir(attachments_dir): - # RĂ©cupĂ©rer toutes les images du dossier - for filename in os.listdir(attachments_dir): - file_path = os.path.join(attachments_dir, filename) - _, extension = os.path.splitext(filename) - if os.path.isfile(file_path) and extension.lower() in ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']: - images_paths.append(file_path) - - # Charger le contexte du ticket - ticket_info_path = os.path.join(args.dossier_ticket, "ticket_info.json") - if os.path.exists(ticket_info_path): - try: - with open(ticket_info_path, 'r', encoding='utf-8') as f: - ticket_info = json.load(f) - - # CrĂ©er un contexte Ă  partir des informations du ticket - contexte = f""" - TICKET: {ticket_info.get('code', 'Inconnu')} - {ticket_info.get('name', 'Sans titre')} - - DESCRIPTION: - {ticket_info.get('description', 'Aucune description')} - """ - except Exception as e: - logger.warning(f"Impossible de charger le contexte depuis ticket_info.json: {str(e)}") - - # Charger le contexte explicite si fourni - if args.contexte: - try: - with open(args.contexte, 'r', encoding='utf-8') as f: - if args.contexte.endswith('.json'): - contexte_data = json.load(f) - if isinstance(contexte_data, dict): - contexte = f""" - TICKET: {contexte_data.get('code', 'Inconnu')} - {contexte_data.get('name', 'Sans titre')} - - DESCRIPTION: - {contexte_data.get('description', 'Aucune description')} - """ - else: - contexte = str(contexte_data) - else: - contexte = f.read() - except Exception as e: - logger.warning(f"Impossible de charger le contexte depuis {args.contexte}: {str(e)}") - - # VĂ©rifier que nous avons des images Ă  traiter - if not images_paths: - logger.error("Aucune image Ă  filtrer. Utilisez --images ou --dossier-ticket pour spĂ©cifier les images.") - sys.exit(1) - - # Filtrer les images - try: - resultats = agent.filtrer_images(images_paths, contexte) - - # DĂ©terminer le chemin de sortie - output_path = args.output - if not output_path: - if args.dossier_ticket: - output_path = os.path.join(args.dossier_ticket, "filter_report.json") - else: - output_path = "filter_report.json" - - # Sauvegarder le rapport - with open(output_path, 'w', encoding='utf-8') as f: - json.dump(resultats, f, indent=2, ensure_ascii=False) - - logger.info(f"Rapport de filtrage sauvegardĂ©: {output_path}") - - # Afficher un rĂ©sumĂ© - print("\nRĂ©sumĂ© du filtrage:") - print(f"Images analysĂ©es: {len(images_paths)}") - print(f"Images pertinentes: {len(resultats['images_pertinentes'])}") - print(f"Images non pertinentes: {len(resultats['images_non_pertinentes'])}") - print(f"Erreurs: {len(resultats['erreurs'])}") - - if resultats['images_pertinentes']: - print("\nImages pertinentes:") - for img in resultats['images_pertinentes']: - img_name = os.path.basename(img) - img_type = resultats['analyses'].get(img_name, {}).get('type_image', 'type inconnu') - print(f" - {img_name} ({img_type})") - - if resultats['erreurs']: - print("\nErreurs:") - for err in resultats['erreurs']: - print(f" - {err}") - - print(f"\nRapport complet sauvegardĂ© dans: {output_path}") - - except Exception as e: - logger.error(f"Erreur lors du filtrage des images: {str(e)}") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/scripts/processus_complet.py b/scripts/processus_complet.py deleted file mode 100644 index 8bc77f5..0000000 --- a/scripts/processus_complet.py +++ /dev/null @@ -1,383 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Script principal d'orchestration du processus d'analyse de tickets. -Ce script permet d'exĂ©cuter toutes les Ă©tapes du traitement ou des Ă©tapes individuelles. -""" - -import os -import sys -import json -import argparse -import subprocess -import logging -from typing import Dict, List, Any, Optional -import shutil - -# Configuration du logger -logging.basicConfig( - level=logging.INFO, - format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler("processus_complet.log"), - logging.StreamHandler() - ] -) -logger = logging.getLogger("processus_complet") - -def executer_commande(commande: List[str], description: str) -> bool: - """ - ExĂ©cute une commande système et gère les erreurs. - - Args: - commande: Liste des Ă©lĂ©ments de la commande Ă  exĂ©cuter - description: Description de la commande pour le journal - - Returns: - True si la commande s'est exĂ©cutĂ©e avec succès, False sinon - """ - try: - logger.info(f"ExĂ©cution: {description}") - logger.debug(f"Commande: {' '.join(commande)}") - - resultat = subprocess.run(commande, check=True, capture_output=True, text=True) - - logger.info(f"Succès: {description}") - logger.debug(f"Sortie: {resultat.stdout}") - - return True - except subprocess.CalledProcessError as e: - logger.error(f"Échec: {description}") - logger.error(f"Code de sortie: {e.returncode}") - logger.error(f"Erreur: {e.stderr}") - return False - except Exception as e: - logger.error(f"Erreur lors de l'exĂ©cution de la commande: {str(e)}") - return False - -def etape_extraction(ticket_dir: str, output_dir: str) -> bool: - """ - ExĂ©cute l'Ă©tape d'extraction des donnĂ©es du ticket. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es brutes du ticket - output_dir: RĂ©pertoire oĂą sauvegarder les donnĂ©es extraites - - Returns: - True si l'extraction a rĂ©ussi, False sinon - """ - script_path = os.path.join("scripts", "extract_ticket.py") - - if not os.path.exists(script_path): - logger.error(f"Script d'extraction non trouvĂ©: {script_path}") - return False - - commande = [ - sys.executable, - script_path, - ticket_dir, - "--output-dir", output_dir, - "--verbose" - ] - - return executer_commande(commande, "Extraction des donnĂ©es du ticket") - -def etape_filtrage_images(ticket_dir: str) -> bool: - """ - ExĂ©cute l'Ă©tape de filtrage des images pertinentes. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es du ticket - - Returns: - True si le filtrage a rĂ©ussi, False sinon - """ - script_path = os.path.join("scripts", "filter_images.py") - - if not os.path.exists(script_path): - logger.error(f"Script de filtrage d'images non trouvĂ©: {script_path}") - return False - - commande = [ - sys.executable, - script_path, - "--dossier-ticket", ticket_dir, - "--output", os.path.join(ticket_dir, "filter_report.json"), - "--verbose" - ] - - return executer_commande(commande, "Filtrage des images pertinentes") - -def etape_analyse_images(ticket_dir: str, rapport_filtrage: str) -> bool: - """ - ExĂ©cute l'Ă©tape d'analyse des images pertinentes. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es du ticket - rapport_filtrage: Chemin vers le rapport de filtrage d'images - - Returns: - True si l'analyse a rĂ©ussi, False sinon - """ - script_path = os.path.join("scripts", "analyze_image_contexte.py") - ticket_info_path = os.path.join(ticket_dir, "ticket_info.json") - - if not os.path.exists(script_path): - logger.error(f"Script d'analyse d'images non trouvĂ©: {script_path}") - return False - - # Charger le rapport de filtrage - try: - with open(rapport_filtrage, 'r', encoding='utf-8') as f: - filtre_data = json.load(f) - - images_pertinentes = filtre_data.get("images_pertinentes", []) - if not images_pertinentes: - logger.info("Aucune image pertinente Ă  analyser") - return True - except Exception as e: - logger.error(f"Erreur lors du chargement du rapport de filtrage: {str(e)}") - return False - - # CrĂ©er le rĂ©pertoire pour les rapports d'analyse d'images - images_analyses_dir = os.path.join(ticket_dir, "images_analyses") - os.makedirs(images_analyses_dir, exist_ok=True) - - # Analyser chaque image pertinente - succes = True - for image_path in images_pertinentes: - image_name = os.path.basename(image_path) - output_base = os.path.join(images_analyses_dir, image_name) - - commande = [ - sys.executable, - script_path, - "--image", image_path, - "--ticket-info", ticket_info_path, - "--output", output_base + "_analyse", - "--verbose" - ] - - if not executer_commande(commande, f"Analyse de l'image {image_name}"): - succes = False - - return succes - -def etape_analyse_ticket(ticket_dir: str, rapport_filtrage: str) -> bool: - """ - ExĂ©cute l'Ă©tape d'analyse du contenu du ticket. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es du ticket - rapport_filtrage: Chemin vers le rapport de filtrage d'images - - Returns: - True si l'analyse a rĂ©ussi, False sinon - """ - script_path = os.path.join("scripts", "analyze_ticket.py") - messages_path = os.path.join(ticket_dir, "messages.json") - - if not os.path.exists(script_path): - logger.error(f"Script d'analyse de ticket non trouvĂ©: {script_path}") - return False - - commande = [ - sys.executable, - script_path, - "--messages", messages_path, - "--images-rapport", rapport_filtrage, - "--output", ticket_dir, - "--verbose" - ] - - return executer_commande(commande, "Analyse du contenu du ticket") - -def etape_questions_reponses(ticket_dir: str) -> bool: - """ - ExĂ©cute l'Ă©tape d'extraction des questions et rĂ©ponses. - - Args: - ticket_dir: RĂ©pertoire contenant les donnĂ©es du ticket - - Returns: - True si l'extraction a rĂ©ussi, False sinon - """ - script_path = os.path.join("scripts", "extract_question_reponse.py") - messages_path = os.path.join(ticket_dir, "messages.json") - output_path = os.path.join(ticket_dir, "questions_reponses.md") - - if not os.path.exists(script_path): - logger.error(f"Script d'extraction des questions-rĂ©ponses non trouvĂ©: {script_path}") - return False - - commande = [ - sys.executable, - script_path, - "--messages", messages_path, - "--output", output_path, - "--verbose" - ] - - return executer_commande(commande, "Extraction des questions et rĂ©ponses") - -def processus_complet(ticket_code: str, dossier_source: str = None, dossier_sortie: str = None) -> bool: - """ - ExĂ©cute le processus complet d'analyse d'un ticket. - - Args: - ticket_code: Code du ticket Ă  analyser - dossier_source: Dossier contenant les tickets bruts (par dĂ©faut: output/) - dossier_sortie: Dossier oĂą sauvegarder les rĂ©sultats (par dĂ©faut: output_processed/) - - Returns: - True si le processus s'est exĂ©cutĂ© avec succès, False sinon - """ - # DĂ©finir les dossiers par dĂ©faut si non spĂ©cifiĂ©s - if dossier_source is None: - dossier_source = "output" - - if dossier_sortie is None: - dossier_sortie = "output_processed" - - # Construire les chemins - ticket_dir_source = os.path.join(dossier_source, f"ticket_{ticket_code}") - ticket_dir_sortie = os.path.join(dossier_sortie, f"ticket_{ticket_code}") - - # VĂ©rifier que le dossier source existe - if not os.path.exists(ticket_dir_source): - logger.error(f"Dossier source non trouvĂ©: {ticket_dir_source}") - return False - - # CrĂ©er le dossier de sortie s'il n'existe pas - os.makedirs(ticket_dir_sortie, exist_ok=True) - - # 1. Extraction des donnĂ©es - if not etape_extraction(ticket_dir_source, ticket_dir_sortie): - logger.error("Échec de l'Ă©tape d'extraction") - return False - - # 2. Filtrage des images - if not etape_filtrage_images(ticket_dir_sortie): - logger.error("Échec de l'Ă©tape de filtrage des images") - return False - - # 3. Analyse des images pertinentes - rapport_filtrage = os.path.join(ticket_dir_sortie, "filter_report.json") - if not etape_analyse_images(ticket_dir_sortie, rapport_filtrage): - logger.error("Échec de l'Ă©tape d'analyse des images") - return False - - # 4. Analyse du contenu du ticket - if not etape_analyse_ticket(ticket_dir_sortie, rapport_filtrage): - logger.error("Échec de l'Ă©tape d'analyse du ticket") - return False - - # 5. Extraction des questions et rĂ©ponses - if not etape_questions_reponses(ticket_dir_sortie): - logger.error("Échec de l'Ă©tape d'extraction des questions et rĂ©ponses") - return False - - logger.info(f"Processus complet terminĂ© avec succès pour le ticket {ticket_code}") - logger.info(f"RĂ©sultats disponibles dans: {ticket_dir_sortie}") - - return True - -def main(): - """ - Point d'entrĂ©e du script. - """ - parser = argparse.ArgumentParser(description="ExĂ©cute le processus d'analyse de tickets de support.") - parser.add_argument("--ticket", "-t", required=True, help="Code du ticket Ă  analyser (ex: T0167)") - parser.add_argument("--source", "-s", help="Dossier source contenant les tickets bruts (par dĂ©faut: output/)") - parser.add_argument("--output", "-o", help="Dossier de sortie pour les rĂ©sultats (par dĂ©faut: output_processed/)") - parser.add_argument("--etapes", "-e", choices=["extraction", "filtrage", "analyse_images", "analyse_ticket", "questions_reponses", "tout"], - default="tout", help="Étapes Ă  exĂ©cuter") - parser.add_argument("--verbose", "-v", action="store_true", help="Afficher plus d'informations") - - args = parser.parse_args() - - # Configurer le niveau de log - if args.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - # RĂ©cupĂ©rer le code du ticket - ticket_code = args.ticket - if ticket_code.startswith("ticket_"): - ticket_code = ticket_code[7:] - - # DĂ©finir les dossiers source et sortie - dossier_source = args.source or "output" - dossier_sortie = args.output or "output_processed" - - # Construire les chemins - ticket_dir_source = os.path.join(dossier_source, f"ticket_{ticket_code}") - ticket_dir_sortie = os.path.join(dossier_sortie, f"ticket_{ticket_code}") - - # VĂ©rifier que le dossier source existe - if not os.path.exists(ticket_dir_source): - logger.error(f"Dossier source non trouvĂ©: {ticket_dir_source}") - sys.exit(1) - - # ExĂ©cuter les Ă©tapes demandĂ©es - if args.etapes == "tout": - if processus_complet(ticket_code, dossier_source, dossier_sortie): - print(f"Processus complet terminĂ© avec succès pour le ticket {ticket_code}") - print(f"RĂ©sultats disponibles dans: {ticket_dir_sortie}") - else: - print(f"Échec du processus pour le ticket {ticket_code}") - sys.exit(1) - else: - # CrĂ©er le dossier de sortie s'il n'existe pas - os.makedirs(ticket_dir_sortie, exist_ok=True) - - # ExĂ©cuter l'Ă©tape spĂ©cifique - if args.etapes == "extraction": - if etape_extraction(ticket_dir_source, ticket_dir_sortie): - print("Étape d'extraction terminĂ©e avec succès") - else: - print("Échec de l'Ă©tape d'extraction") - sys.exit(1) - - elif args.etapes == "filtrage": - if etape_filtrage_images(ticket_dir_sortie): - print("Étape de filtrage des images terminĂ©e avec succès") - else: - print("Échec de l'Ă©tape de filtrage des images") - sys.exit(1) - - elif args.etapes == "analyse_images": - rapport_filtrage = os.path.join(ticket_dir_sortie, "filter_report.json") - if not os.path.exists(rapport_filtrage): - logger.error(f"Rapport de filtrage non trouvĂ©: {rapport_filtrage}") - print("Veuillez d'abord exĂ©cuter l'Ă©tape de filtrage des images") - sys.exit(1) - - if etape_analyse_images(ticket_dir_sortie, rapport_filtrage): - print("Étape d'analyse des images terminĂ©e avec succès") - else: - print("Échec de l'Ă©tape d'analyse des images") - sys.exit(1) - - elif args.etapes == "analyse_ticket": - rapport_filtrage = os.path.join(ticket_dir_sortie, "filter_report.json") - if not os.path.exists(rapport_filtrage): - logger.error(f"Rapport de filtrage non trouvĂ©: {rapport_filtrage}") - print("Veuillez d'abord exĂ©cuter l'Ă©tape de filtrage des images") - sys.exit(1) - - if etape_analyse_ticket(ticket_dir_sortie, rapport_filtrage): - print("Étape d'analyse du ticket terminĂ©e avec succès") - else: - print("Échec de l'Ă©tape d'analyse du ticket") - sys.exit(1) - - elif args.etapes == "questions_reponses": - if etape_questions_reponses(ticket_dir_sortie): - print("Étape d'extraction des questions et rĂ©ponses terminĂ©e avec succès") - else: - print("Échec de l'Ă©tape d'extraction des questions et rĂ©ponses") - sys.exit(1) - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/utils/__init__.py b/utils/__init__.py deleted file mode 100644 index c7b84af..0000000 --- a/utils/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -from .ticket_analyzer import TicketAnalyzer -from .ticket_manager import TicketManager - -__all__ = ['TicketAnalyzer', 'TicketManager'] \ No newline at end of file diff --git a/utils/__pycache__/__init__.cpython-312.pyc b/utils/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 4122d5736f9013b936b49af25bb2c9f7571ff4f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 302 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 s)#zW*l*aULRK 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 None: - """ - Applique les paramètres globaux Ă  tous les agents. - """ - if not self.llm_params: - return - - print(f"Application des paramètres globaux LLM: {self.llm_params}") - self.agent_filtre.appliquer_parametres_globaux(self.llm_params) - self.agent_analyse.appliquer_parametres_globaux(self.llm_params) - self.agent_qr.appliquer_parametres_globaux(self.llm_params) - - def filtrer_images(self, images_paths: List[str]) -> List[str]: - """ - Filtre les images pour ne conserver que celles pertinentes. - - Args: - images_paths: Liste des chemins d'images Ă  filtrer - - Returns: - Liste des chemins d'images pertinentes - """ - images_pertinentes = [] - - for image_path in images_paths: - # Enregistrer le dĂ©but de l'action - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - entry = { - "timestamp": timestamp, - "action": "filter_image", - "agent": self.agent_filtre.nom, - "llm": {"model": self.agent_filtre.llm.model}, - "parametres_llm": self.agent_filtre.obtenir_parametres_llm(), - "image_path": image_path - } - - # ExĂ©cuter le filtrage d'image - resultat = self.agent_filtre.executer(image_path) - - # Ajouter le rĂ©sultat Ă  l'entrĂ©e - entry["response"] = resultat - - # Ajouter au journal - self.entries.append(entry) - - # Conserver l'image si pertinente - if resultat.get("pertinente", False): - images_pertinentes.append(image_path) - - return images_pertinentes - - def analyser_images(self, images_paths: List[str], contexte_ticket: Optional[str] = None) -> List[Dict[str, Any]]: - """ - Analyse les images pertinentes en dĂ©tail. - - Args: - images_paths: Liste des chemins d'images Ă  analyser - contexte_ticket: Contexte du ticket pour une analyse plus pertinente - - Returns: - Liste des rĂ©sultats d'analyse - """ - resultats_analyses = [] - - for image_path in images_paths: - # Enregistrer le dĂ©but de l'action - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - entry = { - "timestamp": timestamp, - "action": "analyze_image", - "agent": self.agent_analyse.nom, - "llm": {"model": self.agent_analyse.llm.model}, - "parametres_llm": self.agent_analyse.obtenir_parametres_llm(), - "image_path": image_path - } - - # ExĂ©cuter l'analyse d'image - resultat = self.agent_analyse.executer(image_path, contexte_ticket) - - # Ajouter le rĂ©sultat Ă  l'entrĂ©e - entry["response"] = resultat.get("content", "") - if "usage" in resultat: - entry["tokens"] = resultat["usage"] - - # Ajouter au journal - self.entries.append(entry) - - # Ajouter aux rĂ©sultats - if "error" not in resultat: - resultats_analyses.append({ - "image_path": image_path, - "analyse": resultat.get("content", ""), - "usage": resultat.get("usage", {}), - "parametres_llm": self.agent_analyse.generer_rapport_parametres() - }) - - return resultats_analyses - - def extraire_questions_reponses(self, messages: List[Dict[str, Any]], output_path: Optional[str] = None) -> Dict[str, Any]: - """ - Extrait les questions et rĂ©ponses des messages du ticket. - - Args: - messages: Liste des messages du ticket - output_path: Chemin oĂą sauvegarder le tableau Markdown (optionnel) - - Returns: - RĂ©sultat de l'extraction avec tableau Markdown - """ - # Enregistrer le dĂ©but de l'action - timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - entry = { - "timestamp": timestamp, - "action": "extract_questions_reponses", - "agent": self.agent_qr.nom, - "llm": {"model": self.agent_qr.llm.model}, - "parametres_llm": self.agent_qr.obtenir_parametres_llm() - } - - # ExĂ©cuter l'extraction des questions/rĂ©ponses - resultat = self.agent_qr.executer(messages, output_path) - - # Ajouter le rĂ©sultat Ă  l'entrĂ©e - entry["response"] = resultat - - # Ajouter au journal - self.entries.append(entry) - - return resultat - - def generer_rapport(self, output_path: str) -> Dict[str, str]: - """ - GĂ©nère un rapport complet d'analyse au format JSON et Markdown. - - Args: - output_path: Chemin oĂą sauvegarder le rapport - - Returns: - Dictionnaire avec les chemins des fichiers gĂ©nĂ©rĂ©s - """ - # CrĂ©er le rĂ©pertoire de sortie si nĂ©cessaire - os.makedirs(output_path, exist_ok=True) - - # Chemins des fichiers de sortie - json_path = os.path.join(output_path, "ticket_analysis.json") - md_path = os.path.join(output_path, "ticket_analysis.md") - - # Sauvegarder au format JSON - with open(json_path, "w", encoding="utf-8") as f: - json.dump({"entries": self.entries}, f, indent=2, ensure_ascii=False) - - # GĂ©nĂ©rer le contenu Markdown - md_content = self._generer_markdown() - - # Normaliser les accents dans le contenu Markdown avant de l'Ă©crire - md_content = normaliser_accents(md_content) - - # Sauvegarder au format Markdown - with open(md_path, "w", encoding="utf-8") as f: - f.write(md_content) - - return { - "json": json_path, - "markdown": md_path - } - - def _generer_markdown(self) -> str: - """ - GĂ©nère le contenu Markdown Ă  partir des entrĂ©es du journal. - - Returns: - Contenu Markdown formatĂ© - """ - contenu = ["# Analyse de ticket de support\n"] - - # Statistiques - stats = self._calculer_statistiques() - contenu.append("## Statistiques\n") - contenu.append(f"- Images analysĂ©es: {stats['images_total']} ({stats['images_pertinentes']} pertinentes)") - contenu.append(f"- Questions identifiĂ©es: {stats['questions']}") - contenu.append(f"- RĂ©ponses identifiĂ©es: {stats['reponses']}") - contenu.append("\n") - - # Paramètres LLM globaux - if self.llm_params: - contenu.append("## Paramètres LLM globaux\n") - for param, valeur in self.llm_params.items(): - contenu.append(f"- **{param}**: {valeur}") - contenu.append("\n") - - # Paramètres LLM utilisĂ©s - contenu.append("## Paramètres LLM par agent\n") - - # Filtre d'images - agent_filtre_params = self.agent_filtre.obtenir_parametres_llm() - contenu.append("### Agent de filtrage d'images\n") - contenu.append(f"- **Type de LLM**: {self.agent_filtre.llm.__class__.__name__}") - contenu.append(f"- **Modèle**: {agent_filtre_params.get('model', 'Non spĂ©cifiĂ©')}") - contenu.append(f"- **TempĂ©rature**: {agent_filtre_params.get('temperature', 'Non spĂ©cifiĂ©e')}") - contenu.append(f"- **Tokens max**: {agent_filtre_params.get('max_tokens', 'Non spĂ©cifiĂ©')}") - - # Analyse d'images - agent_analyse_params = self.agent_analyse.obtenir_parametres_llm() - contenu.append("\n### Agent d'analyse d'images\n") - contenu.append(f"- **Type de LLM**: {self.agent_analyse.llm.__class__.__name__}") - contenu.append(f"- **Modèle**: {agent_analyse_params.get('model', 'Non spĂ©cifiĂ©')}") - contenu.append(f"- **TempĂ©rature**: {agent_analyse_params.get('temperature', 'Non spĂ©cifiĂ©e')}") - contenu.append(f"- **Tokens max**: {agent_analyse_params.get('max_tokens', 'Non spĂ©cifiĂ©')}") - - # Questions-rĂ©ponses - agent_qr_params = self.agent_qr.obtenir_parametres_llm() - contenu.append("\n### Agent d'extraction questions-rĂ©ponses\n") - contenu.append(f"- **Type de LLM**: {self.agent_qr.llm.__class__.__name__}") - contenu.append(f"- **Modèle**: {agent_qr_params.get('model', 'Non spĂ©cifiĂ©')}") - contenu.append(f"- **TempĂ©rature**: {agent_qr_params.get('temperature', 'Non spĂ©cifiĂ©e')}") - contenu.append(f"- **Tokens max**: {agent_qr_params.get('max_tokens', 'Non spĂ©cifiĂ©')}") - contenu.append("\n") - - # Actions chronologiques - contenu.append("## Journal d'actions\n") - - for entry in self.entries: - timestamp = entry.get("timestamp", "") - action = entry.get("action", "") - agent = entry.get("agent", "") - model = entry.get("llm", {}).get("model", "") - - # En-tĂŞte de l'action - contenu.append(f"### {timestamp} - {agent} ({model})") - contenu.append(f"**Action**: {action}") - - # DĂ©tails spĂ©cifiques selon le type d'action - if action == "filter_image": - image_path = entry.get("image_path", "") - response = entry.get("response", {}) - pertinente = response.get("pertinente", False) - type_image = response.get("type_image", "inconnue") - description = response.get("description", "") - - contenu.append(f"**Image**: {os.path.basename(image_path)}") - contenu.append(f"**RĂ©sultat**: {'Pertinente' if pertinente else 'Non pertinente'}") - contenu.append(f"**Type**: {type_image}") - contenu.append(f"**Description**: {description}") - - # Paramètres LLM utilisĂ©s - params_llm = response.get("parametres_llm", {}) - if params_llm: - contenu.append("\n**Paramètres LLM utilisĂ©s:**") - temp = params_llm.get("parametres", {}).get("temperature", "N/A") - contenu.append(f"- TempĂ©rature: {temp}") - - elif action == "analyze_image": - image_path = entry.get("image_path", "") - response = entry.get("response", "") - - contenu.append(f"**Image analysĂ©e**: {os.path.basename(image_path)}") - contenu.append("\n**Analyse**:") - contenu.append(f"```\n{response}\n```") - - elif action == "extract_questions_reponses": - response = entry.get("response", {}) - tableau_md = response.get("tableau_md", "") - - contenu.append(f"**Questions**: {response.get('nb_questions', 0)}") - contenu.append(f"**RĂ©ponses**: {response.get('nb_reponses', 0)}") - contenu.append("\n") - contenu.append(tableau_md) - - # Paramètres LLM spĂ©cifiques Ă  cette action - params_llm = entry.get("parametres_llm", {}) - if params_llm and action != "filter_image": # Pour Ă©viter la duplication avec le filtre d'image - contenu.append("\n**Paramètres LLM utilisĂ©s:**") - for key, value in params_llm.items(): - if key != "system_prompt": # Éviter d'afficher le prompt système ici - contenu.append(f"- **{key}**: {value}") - - # Tokens utilisĂ©s - if "tokens" in entry: - tokens = entry["tokens"] - contenu.append("\n**Tokens utilisĂ©s**:") - contenu.append(f"- Prompt: {tokens.get('prompt_tokens', 0)}") - contenu.append(f"- Completion: {tokens.get('completion_tokens', 0)}") - contenu.append(f"- Total: {tokens.get('total_tokens', 0)}") - - contenu.append("\n---\n") - - return "\n".join(contenu) - - def _calculer_statistiques(self) -> Dict[str, int]: - """ - Calcule les statistiques Ă  partir des entrĂ©es du journal. - - Returns: - Dictionnaire de statistiques - """ - stats = { - "images_total": 0, - "images_pertinentes": 0, - "questions": 0, - "reponses": 0 - } - - for entry in self.entries: - action = entry.get("action", "") - - if action == "filter_image": - stats["images_total"] += 1 - if entry.get("response", {}).get("pertinente", False): - stats["images_pertinentes"] += 1 - - elif action == "extract_questions_reponses": - stats["questions"] = entry.get("response", {}).get("nb_questions", 0) - stats["reponses"] = entry.get("response", {}).get("nb_reponses", 0) - - return stats \ No newline at end of file diff --git a/utils/ticket_manager.py b/utils/ticket_manager.py deleted file mode 100644 index aae8481..0000000 --- a/utils/ticket_manager.py +++ /dev/null @@ -1,408 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- - -""" -Module pour gĂ©rer l'extraction de tickets depuis Odoo. -Cette version est simplifiĂ©e et indĂ©pendante de odoo_toolkit. -""" - -import os -import json -import base64 -from typing import Dict, List, Any, Optional -import requests -from agents import AgentFiltreImages, AgentAnalyseImage, AgentQuestionReponse - -class TicketManager: - """ - Gestionnaire de tickets pour extraire des donnĂ©es depuis Odoo. - """ - - def __init__(self, url: str, db: str, username: str, api_key: str): - """ - Initialise le gestionnaire de tickets avec les paramètres de connexion. - - Args: - url: URL du serveur Odoo - db: Nom de la base de donnĂ©es - username: Nom d'utilisateur - api_key: ClĂ© API ou mot de passe - """ - self.url = url - self.db = db - self.username = username - self.api_key = api_key - self.uid = None - self.session_id = None - self.model_name = "project.task" # Modèle par dĂ©faut pour les tickets - - def login(self) -> bool: - """ - Établit la connexion au serveur Odoo. - - Returns: - True si la connexion rĂ©ussit, False sinon - """ - try: - # Point d'entrĂ©e pour le login - login_url = f"{self.url}/web/session/authenticate" - - # DonnĂ©es pour la requĂŞte de login - login_data = { - "jsonrpc": "2.0", - "params": { - "db": self.db, - "login": self.username, - "password": self.api_key - } - } - - # Effectuer la requĂŞte - response = requests.post(login_url, json=login_data) - response.raise_for_status() - - # Extraire les rĂ©sultats - result = response.json() - if result.get("error"): - print(f"Erreur de connexion: {result['error']['message']}") - return False - - # RĂ©cupĂ©rer l'ID utilisateur et la session - self.uid = result.get("result", {}).get("uid") - self.session_id = response.cookies.get("session_id") - - if not self.uid: - print("Erreur: Impossible de rĂ©cupĂ©rer l'ID utilisateur") - return False - - print(f"ConnectĂ© avec succès Ă  {self.url} (User ID: {self.uid})") - return True - - except Exception as e: - print(f"Erreur de connexion: {str(e)}") - return False - - def _ensure_connection(self) -> bool: - """ - VĂ©rifie que la connexion est Ă©tablie, tente de se reconnecter si nĂ©cessaire. - - Returns: - True si la connexion est disponible, False sinon - """ - if not self.uid or not self.session_id: - return self.login() - return True - - def _rpc_call(self, endpoint: str, params: Dict[str, Any]) -> Dict[str, Any]: - """ - Effectue un appel RPC vers le serveur Odoo. - - Args: - endpoint: Point d'entrĂ©e de l'API (/web/dataset/call_kw, etc.) - params: Paramètres de la requĂŞte - - Returns: - RĂ©sultat de la requĂŞte - """ - if not self._ensure_connection(): - return {"error": "Non connectĂ©"} - - try: - # PrĂ©parer la requĂŞte - full_url = f"{self.url}{endpoint}" - headers = {"Content-Type": "application/json"} - - # DonnĂ©es de la requĂŞte - data = { - "jsonrpc": "2.0", - "method": "call", - "params": params - } - - # Effectuer la requĂŞte - response = requests.post( - full_url, - json=data, - headers=headers, - cookies={"session_id": self.session_id} if self.session_id else None - ) - response.raise_for_status() - - # Traiter la rĂ©ponse - result = response.json() - if result.get("error"): - return {"error": result["error"]["message"]} - - return result.get("result", {}) - - except Exception as e: - return {"error": str(e)} - - def search_read(self, model: str, domain: List, fields: List[str], limit: int = 0) -> List[Dict[str, Any]]: - """ - Recherche et lit des enregistrements selon un domaine. - - Args: - model: Nom du modèle - domain: Domaine de recherche - fields: Champs Ă  rĂ©cupĂ©rer - limit: Nombre max de rĂ©sultats (0 pour illimitĂ©) - - Returns: - Liste des enregistrements trouvĂ©s - """ - params = { - "model": model, - "method": "search_read", - "args": [domain, fields], - "kwargs": {"limit": limit} - } - - result = self._rpc_call("/web/dataset/call_kw", params) - if isinstance(result, dict) and "error" in result: - print(f"Erreur lors de la recherche: {result['error']}") - return [] - - return result if isinstance(result, list) else [] - - def read(self, model: str, ids: List[int], fields: List[str]) -> List[Dict[str, Any]]: - """ - Lit des enregistrements par leurs IDs. - - Args: - model: Nom du modèle - ids: Liste des IDs Ă  lire - fields: Champs Ă  rĂ©cupĂ©rer - - Returns: - Liste des enregistrements lus - """ - params = { - "model": model, - "method": "read", - "args": [ids, fields], - "kwargs": {} - } - - result = self._rpc_call("/web/dataset/call_kw", params) - if isinstance(result, dict) and "error" in result: - print(f"Erreur lors de la lecture: {result['error']}") - return [] - - return result if isinstance(result, list) else [] - - def get_ticket_by_code(self, ticket_code: str) -> Dict[str, Any]: - """ - RĂ©cupère un ticket par son code. - - Args: - ticket_code: Code du ticket Ă  rĂ©cupĂ©rer - - Returns: - DonnĂ©es du ticket ou dictionnaire vide si non trouvĂ© - """ - # Rechercher l'ID du ticket par son code - tickets = self.search_read( - model=self.model_name, - domain=[("code", "=", ticket_code)], - fields=["id"], - limit=1 - ) - - if not tickets: - print(f"Aucun ticket trouvĂ© avec le code {ticket_code}") - return {} - - # RĂ©cupĂ©rer toutes les donnĂ©es du ticket - ticket_id = tickets[0]["id"] - return self.get_ticket_by_id(ticket_id) - - def get_ticket_by_id(self, ticket_id: int) -> Dict[str, Any]: - """ - RĂ©cupère un ticket par son ID. - - Args: - ticket_id: ID du ticket Ă  rĂ©cupĂ©rer - - Returns: - DonnĂ©es du ticket ou dictionnaire vide si non trouvĂ© - """ - # RĂ©cupĂ©rer les champs disponibles pour le modèle - fields_info = self._get_model_fields(self.model_name) - - # Lire les donnĂ©es du ticket - tickets = self.read( - model=self.model_name, - ids=[ticket_id], - fields=fields_info - ) - - if not tickets: - print(f"Aucun ticket trouvĂ© avec l'ID {ticket_id}") - return {} - - return tickets[0] - - def _get_model_fields(self, model_name: str) -> List[str]: - """ - RĂ©cupère la liste des champs disponibles pour un modèle. - - Args: - model_name: Nom du modèle - - Returns: - Liste des noms de champs - """ - params = { - "model": model_name, - "method": "fields_get", - "args": [], - "kwargs": {"attributes": ["name", "type"]} - } - - result = self._rpc_call("/web/dataset/call_kw", params) - if "error" in result: - print(f"Erreur lors de la rĂ©cupĂ©ration des champs: {result['error']}") - return [] - - # Filtrer les types de champs problĂ©matiques - invalid_types = ["many2many", "binary"] - valid_fields = [ - field for field, info in result.items() - if info.get("type") not in invalid_types - ] - - return valid_fields - - def get_ticket_messages(self, ticket_id: int) -> List[Dict[str, Any]]: - """ - RĂ©cupère les messages d'un ticket. - - Args: - ticket_id: ID du ticket - - Returns: - Liste des messages du ticket - """ - # D'abord rĂ©cupĂ©rer les IDs des messages - ticket = self.read( - model=self.model_name, - ids=[ticket_id], - fields=["message_ids"] - ) - - if not ticket or "message_ids" not in ticket[0]: - print(f"Impossible de rĂ©cupĂ©rer les messages pour le ticket {ticket_id}") - return [] - - message_ids = ticket[0]["message_ids"] - - # RĂ©cupĂ©rer les dĂ©tails des messages - messages = self.read( - model="mail.message", - ids=message_ids, - fields=["id", "body", "date", "author_id", "email_from", "subject", "parent_id"] - ) - - return messages - - def get_ticket_attachments(self, ticket_id: int, download_path: Optional[str] = None) -> List[Dict[str, Any]]: - """ - RĂ©cupère les pièces jointes d'un ticket, avec option de tĂ©lĂ©chargement. - - Args: - ticket_id: ID du ticket - download_path: Chemin oĂą tĂ©lĂ©charger les pièces jointes (optionnel) - - Returns: - Liste des informations sur les pièces jointes - """ - # Rechercher les pièces jointes liĂ©es au ticket - attachments = self.search_read( - model="ir.attachment", - domain=[("res_model", "=", self.model_name), ("res_id", "=", ticket_id)], - fields=["id", "name", "mimetype", "create_date", "datas"] - ) - - if not attachments: - print(f"Aucune pièce jointe trouvĂ©e pour le ticket {ticket_id}") - return [] - - if download_path: - # CrĂ©er le rĂ©pertoire si nĂ©cessaire - os.makedirs(download_path, exist_ok=True) - - # TĂ©lĂ©charger chaque pièce jointe - for attachment in attachments: - if "datas" in attachment and attachment["datas"]: - # DĂ©chiffrer les donnĂ©es base64 - binary_data = base64.b64decode(attachment["datas"]) - - # Nettoyer le nom de fichier - safe_name = attachment["name"].replace("/", "_").replace("\\", "_") - file_path = os.path.join(download_path, f"{attachment['id']}_{safe_name}") - - # Sauvegarder le fichier - with open(file_path, "wb") as f: - f.write(binary_data) - - # Remplacer les donnĂ©es binaires par le chemin du fichier - attachment["file_path"] = file_path - del attachment["datas"] - - return attachments - - def extract_ticket_data(self, ticket_id: int, output_dir: str) -> Dict[str, Any]: - """ - Extrait toutes les donnĂ©es d'un ticket, y compris messages et pièces jointes. - - Args: - ticket_id: ID du ticket - output_dir: RĂ©pertoire de sortie - - Returns: - Dictionnaire avec toutes les donnĂ©es du ticket - """ - # CrĂ©er le rĂ©pertoire de sortie - os.makedirs(output_dir, exist_ok=True) - - # RĂ©cupĂ©rer les donnĂ©es du ticket - ticket = self.get_ticket_by_id(ticket_id) - if not ticket: - return {"error": f"Ticket {ticket_id} non trouvĂ©"} - - # Sauvegarder les donnĂ©es du ticket - ticket_path = os.path.join(output_dir, "ticket_info.json") - with open(ticket_path, "w", encoding="utf-8") as f: - json.dump(ticket, f, indent=2, ensure_ascii=False) - - # RĂ©cupĂ©rer et sauvegarder les messages - messages = self.get_ticket_messages(ticket_id) - messages_path = os.path.join(output_dir, "messages.json") - with open(messages_path, "w", encoding="utf-8") as f: - json.dump(messages, f, indent=2, ensure_ascii=False) - - # RĂ©cupĂ©rer et sauvegarder les pièces jointes - attachments_dir = os.path.join(output_dir, "attachments") - attachments = self.get_ticket_attachments(ticket_id, attachments_dir) - attachments_path = os.path.join(output_dir, "attachments_info.json") - with open(attachments_path, "w", encoding="utf-8") as f: - json.dump(attachments, f, indent=2, ensure_ascii=False) - - # Compiler toutes les informations - result = { - "ticket": ticket, - "messages": messages, - "attachments": [ - {k: v for k, v in a.items() if k != "datas"} - for a in attachments - ], - "files": { - "ticket_info": ticket_path, - "messages": messages_path, - "attachments_info": attachments_path, - "attachments_dir": attachments_dir - } - } - - return result \ No newline at end of file diff --git a/venv/bin/Activate.ps1 b/venv/bin/Activate.ps1 deleted file mode 100644 index b49d77b..0000000 --- a/venv/bin/Activate.ps1 +++ /dev/null @@ -1,247 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove VIRTUAL_ENV_PROMPT altogether. - if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { - Remove-Item -Path env:VIRTUAL_ENV_PROMPT - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } - $env:VIRTUAL_ENV_PROMPT = $Prompt -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/venv/bin/activate b/venv/bin/activate deleted file mode 100644 index 62061a8..0000000 --- a/venv/bin/activate +++ /dev/null @@ -1,70 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# You cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # Call hash to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - hash -r 2> /dev/null - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - unset VIRTUAL_ENV_PROMPT - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -# on Windows, a path can contain colons and backslashes and has to be converted: -if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then - # transform D:\path\to\venv to /d/path/to/venv on MSYS - # and to /cygdrive/d/path/to/venv on Cygwin - export VIRTUAL_ENV=$(cygpath /home/fgras-ca/llm-ticket3/venv) -else - # use the path as-is - export VIRTUAL_ENV=/home/fgras-ca/llm-ticket3/venv -fi - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/"bin":$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1='(venv) '"${PS1:-}" - export PS1 - VIRTUAL_ENV_PROMPT='(venv) ' - export VIRTUAL_ENV_PROMPT -fi - -# Call hash to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -hash -r 2> /dev/null diff --git a/venv/bin/activate.csh b/venv/bin/activate.csh deleted file mode 100644 index 608952b..0000000 --- a/venv/bin/activate.csh +++ /dev/null @@ -1,27 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. - -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV /home/fgras-ca/llm-ticket3/venv - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/"bin":$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = '(venv) '"$prompt" - setenv VIRTUAL_ENV_PROMPT '(venv) ' -endif - -alias pydoc python -m pydoc - -rehash diff --git a/venv/bin/activate.fish b/venv/bin/activate.fish deleted file mode 100644 index 478275d..0000000 --- a/venv/bin/activate.fish +++ /dev/null @@ -1,69 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/). You cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - set -e _OLD_FISH_PROMPT_OVERRIDE - # prevents error when using nested fish instances (Issue #93858) - if functions -q _old_fish_prompt - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - end - - set -e VIRTUAL_ENV - set -e VIRTUAL_ENV_PROMPT - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV /home/fgras-ca/llm-ticket3/venv - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/"bin $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) '(venv) ' (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" - set -gx VIRTUAL_ENV_PROMPT '(venv) ' -end diff --git a/venv/bin/httpx b/venv/bin/httpx deleted file mode 100755 index 5884ee2..0000000 --- a/venv/bin/httpx +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/fgras-ca/llm-ticket3/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from httpx import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv/bin/normalizer b/venv/bin/normalizer deleted file mode 100755 index a55484d..0000000 --- a/venv/bin/normalizer +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/fgras-ca/llm-ticket3/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from charset_normalizer import cli -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(cli.cli_detect()) diff --git a/venv/bin/pip b/venv/bin/pip deleted file mode 100755 index ae8d173..0000000 --- a/venv/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/fgras-ca/llm-ticket3/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv/bin/pip3 b/venv/bin/pip3 deleted file mode 100755 index ae8d173..0000000 --- a/venv/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/fgras-ca/llm-ticket3/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv/bin/pip3.12 b/venv/bin/pip3.12 deleted file mode 100755 index ae8d173..0000000 --- a/venv/bin/pip3.12 +++ /dev/null @@ -1,8 +0,0 @@ -#!/home/fgras-ca/llm-ticket3/venv/bin/python3 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/venv/bin/python b/venv/bin/python deleted file mode 120000 index b8a0adb..0000000 --- a/venv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/venv/bin/python3 b/venv/bin/python3 deleted file mode 120000 index ae65fda..0000000 --- a/venv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -/usr/bin/python3 \ No newline at end of file diff --git a/venv/bin/python3.12 b/venv/bin/python3.12 deleted file mode 120000 index b8a0adb..0000000 --- a/venv/bin/python3.12 +++ /dev/null @@ -1 +0,0 @@ -python3 \ No newline at end of file diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/AUTHORS b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/AUTHORS deleted file mode 100644 index 84c8d7e..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Original Author ---------------- -SĂ©bastien Alix , diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/LICENSE b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/LICENSE deleted file mode 100644 index 65c5ca8..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/METADATA b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/METADATA deleted file mode 100644 index 4e5afba..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/METADATA +++ /dev/null @@ -1,163 +0,0 @@ -Metadata-Version: 2.1 -Name: OdooRPC -Version: 0.10.1 -Summary: OdooRPC is a Python package providing an easy way to pilot your Odoo servers through RPC. -Home-page: https://github.com/OCA/odoorpc -Author: Sebastien Alix -Author-email: seb@usr-src.org -License: LGPL v3 -Keywords: openerp odoo server rpc client xml-rpc xmlrpc jsonrpc json-rpc odoorpc oerplib communication lib library python service web webservice -Classifier: Intended Audience :: Developers -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.4 -Classifier: Programming Language :: Python :: 3.5 -Classifier: Programming Language :: Python :: 3.6 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Framework :: Odoo -Description-Content-Type: text/x-rst -License-File: LICENSE -License-File: AUTHORS - -======= -OdooRPC -======= - -.. image:: https://img.shields.io/pypi/v/OdooRPC.svg - :target: https://pypi.python.org/pypi/OdooRPC/ - :alt: Latest Version - -.. image:: https://travis-ci.org/OCA/odoorpc.svg?branch=master - :target: https://travis-ci.org/OCA/odoorpc - :alt: Build Status - -.. image:: https://img.shields.io/pypi/pyversions/OdooRPC.svg - :target: https://pypi.python.org/pypi/OdooRPC/ - :alt: Supported Python versions - -.. image:: https://img.shields.io/pypi/l/OdooRPC.svg - :target: https://pypi.python.org/pypi/OdooRPC/ - :alt: License - -**OdooRPC** is a Python package providing an easy way to -pilot your **Odoo** servers through `RPC`. - -Features supported: - - access to all data model methods (even ``browse``) with an API similar - to the server-side API, - - use named parameters with model methods, - - user context automatically sent providing support for - internationalization, - - browse records, - - execute workflows, - - manage databases, - - reports downloading, - - JSON-RPC protocol (SSL supported), - -How does it work? See below: - -.. code-block:: python - - import odoorpc - - # Prepare the connection to the server - odoo = odoorpc.ODOO('localhost', port=8069) - - # Check available databases - print(odoo.db.list()) - - # Login - odoo.login('db_name', 'user', 'passwd') - - # Current user - user = odoo.env.user - print(user.name) # name of the user connected - print(user.company_id.name) # the name of its company - - # Simple 'raw' query - user_data = odoo.execute('res.users', 'read', [user.id]) - print(user_data) - - # Use all methods of a model - if 'sale.order' in odoo.env: - Order = odoo.env['sale.order'] - order_ids = Order.search([]) - for order in Order.browse(order_ids): - print(order.name) - products = [line.product_id.name for line in order.order_line] - print(products) - - # Update data through a record - user.name = "Brian Jones" - -See the documentation for more details and features. - -Supported Odoo server versions -============================== - -`OdooRPC` is tested on all major releases of `Odoo` (starting from 8.0). - -Supported Python versions -========================= - -`OdooRPC` support Python 2.7, 3.7+. - -License -======= - -This software is made available under the `LGPL v3` license. - -Generate the documentation -========================== - -To generate the documentation, you have to install `Sphinx` documentation -generator:: - - pip install sphinx - -Then, you can use the ``build_doc`` option of the ``setup.py``:: - - python setup.py build_doc - -The generated documentation will be in the ``./doc/build/html`` directory. - -Changes in this version -======================= - -Consult the ``CHANGELOG`` file. - -Bug Tracker -=========== - -Bugs are tracked on `GitHub Issues -`_. In case of trouble, please -check there if your issue has already been reported. If you spotted it first, -help us smash it by providing detailed and welcomed feedback. - -Credits -======= - -Contributors ------------- - -* SĂ©bastien Alix - -Do not contact contributors directly about support or help with technical issues. - -Maintainer ----------- - -.. image:: https://odoo-community.org/logo.png - :alt: Odoo Community Association - :target: https://odoo-community.org - -This package is maintained by the OCA. - -OCA, or the Odoo Community Association, is a nonprofit organization whose -mission is to support the collaborative development of Odoo features and -promote its widespread use. diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/RECORD b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/RECORD deleted file mode 100644 index 46a22ea..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/RECORD +++ /dev/null @@ -1,34 +0,0 @@ -OdooRPC-0.10.1.dist-info/AUTHORS,sha256=Kjdl6zj2iQulcwF4iADsfzyuusIPWLKsRK9rM2Bh4TY,95 -OdooRPC-0.10.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -OdooRPC-0.10.1.dist-info/LICENSE,sha256=2n6rt7r999OuXp8iOqW9we7ORaxWncIbOwN1ILRGR2g,7651 -OdooRPC-0.10.1.dist-info/METADATA,sha256=UuFVcRgJiOT8MOZ9sREZ4ebCik2JUuM8yckCO1HP9so,4803 -OdooRPC-0.10.1.dist-info/RECORD,, -OdooRPC-0.10.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -OdooRPC-0.10.1.dist-info/WHEEL,sha256=m9WAupmBd2JGDsXWQGJgMGXIWbQY3F5c2xBJbBhq0nY,110 -OdooRPC-0.10.1.dist-info/top_level.txt,sha256=qdAy2XwLvCFM_VdG79vIgP3UV43zLZmvNqbdk4L1b6E,8 -odoorpc/__init__.py,sha256=Zk5CzvWtqvlGWNupLWb8OJQh69KdB9Mv8wfnmfTHVf8,2495 -odoorpc/__pycache__/__init__.cpython-312.pyc,, -odoorpc/__pycache__/db.cpython-312.pyc,, -odoorpc/__pycache__/env.cpython-312.pyc,, -odoorpc/__pycache__/error.cpython-312.pyc,, -odoorpc/__pycache__/fields.cpython-312.pyc,, -odoorpc/__pycache__/models.cpython-312.pyc,, -odoorpc/__pycache__/odoo.cpython-312.pyc,, -odoorpc/__pycache__/report.cpython-312.pyc,, -odoorpc/__pycache__/session.cpython-312.pyc,, -odoorpc/__pycache__/tools.cpython-312.pyc,, -odoorpc/db.py,sha256=cBZzZvnNc5lBC-InKFfRGTBH4psG5mZJ8UOl0GDXt9k,10178 -odoorpc/env.py,sha256=ncP9TnvCwtrD4aHcsv4rSeMXaXTUNajUgYAwQeAWXwQ,10119 -odoorpc/error.py,sha256=QkGjqv5Y0aHxvtuV7oRiFbNhAXz8AK1srmMRLIc0gfU,3284 -odoorpc/fields.py,sha256=Kf5af_m0TDz0k4lKFJLv75YUsu8ClwUOcsKWbTv8EHU,27004 -odoorpc/models.py,sha256=4gsHOcqp8vhN4N9U66B5cnleSbf5gO93gqn7jEZN7Lc,15034 -odoorpc/odoo.py,sha256=UQWQCJppn05XDOgpAdMRKXZEHH6Dv-LkFd6heJaAZ1w,22740 -odoorpc/report.py,sha256=zF_XJDNyDmRDiMVjjQZtgnTBg4iFZZakrw6nUvE8U5k,7396 -odoorpc/rpc/__init__.py,sha256=DFNJYDtwlCHo1d6xBAKV4bXziVoBJLJ8b-Bu85xIgvs,9465 -odoorpc/rpc/__pycache__/__init__.cpython-312.pyc,, -odoorpc/rpc/__pycache__/error.cpython-312.pyc,, -odoorpc/rpc/__pycache__/jsonrpclib.cpython-312.pyc,, -odoorpc/rpc/error.py,sha256=LOb2kvZmXNGy5ZWw6W6UKWvF75YqmcVvL017budrnts,349 -odoorpc/rpc/jsonrpclib.py,sha256=oY0eChMXUinC5YFjUcUO5ZWqt4ar9Dq2X0TJiFnpGb0,5342 -odoorpc/session.py,sha256=YXGVVTKCZMzGCwxoGGeo_XDO04JK2rojrji7o9TuWC8,5567 -odoorpc/tools.py,sha256=yYvMIreEDgZKSoQhZYD6W4xZpY2XppbTnttqHMR1i2w,3539 diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/REQUESTED b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/WHEEL b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/WHEEL deleted file mode 100644 index 4657450..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/WHEEL +++ /dev/null @@ -1,6 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.41.1) -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any - diff --git a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/top_level.txt b/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/top_level.txt deleted file mode 100644 index 40035b8..0000000 --- a/venv/lib/python3.12/site-packages/OdooRPC-0.10.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -odoorpc diff --git a/venv/lib/python3.12/site-packages/README.rst b/venv/lib/python3.12/site-packages/README.rst deleted file mode 100644 index 741f2ad..0000000 --- a/venv/lib/python3.12/site-packages/README.rst +++ /dev/null @@ -1 +0,0 @@ -This is a dummy package designed to prevent namesquatting on PyPI. You should install `beautifulsoup4 `_ instead. diff --git a/venv/lib/python3.12/site-packages/__pycache__/six.cpython-312.pyc b/venv/lib/python3.12/site-packages/__pycache__/six.cpython-312.pyc deleted file mode 100644 index 0a619307cd3ffc679114c13388fca1046d3466db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41400 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≪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 ZDc6N%+46kZ!JDm, Samuel Colvin , Zac Hatfield-Dodds -License-File: LICENSE -Classifier: Development Status :: 4 - Beta -Classifier: Environment :: Console -Classifier: Environment :: MacOS X -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: License :: OSI Approved :: MIT License -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: Unix -Classifier: Programming Language :: Python :: 3 :: Only -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: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Typing :: Typed -Requires-Python: >=3.8 -Requires-Dist: typing-extensions>=4.0.0; python_version < '3.9' -Description-Content-Type: text/markdown - -# annotated-types - -[![CI](https://github.com/annotated-types/annotated-types/workflows/CI/badge.svg?event=push)](https://github.com/annotated-types/annotated-types/actions?query=event%3Apush+branch%3Amain+workflow%3ACI) -[![pypi](https://img.shields.io/pypi/v/annotated-types.svg)](https://pypi.python.org/pypi/annotated-types) -[![versions](https://img.shields.io/pypi/pyversions/annotated-types.svg)](https://github.com/annotated-types/annotated-types) -[![license](https://img.shields.io/github/license/annotated-types/annotated-types.svg)](https://github.com/annotated-types/annotated-types/blob/main/LICENSE) - -[PEP-593](https://peps.python.org/pep-0593/) added `typing.Annotated` as a way of -adding context-specific metadata to existing types, and specifies that -`Annotated[T, x]` _should_ be treated as `T` by any tool or library without special -logic for `x`. - -This package provides metadata objects which can be used to represent common -constraints such as upper and lower bounds on scalar values and collection sizes, -a `Predicate` marker for runtime checks, and -descriptions of how we intend these metadata to be interpreted. In some cases, -we also note alternative representations which do not require this package. - -## Install - -```bash -pip install annotated-types -``` - -## Examples - -```python -from typing import Annotated -from annotated_types import Gt, Len, Predicate - -class MyClass: - age: Annotated[int, Gt(18)] # Valid: 19, 20, ... - # Invalid: 17, 18, "19", 19.0, ... - factors: list[Annotated[int, Predicate(is_prime)]] # Valid: 2, 3, 5, 7, 11, ... - # Invalid: 4, 8, -2, 5.0, "prime", ... - - my_list: Annotated[list[int], Len(0, 10)] # Valid: [], [10, 20, 30, 40, 50] - # Invalid: (1, 2), ["abc"], [0] * 20 -``` - -## Documentation - -_While `annotated-types` avoids runtime checks for performance, users should not -construct invalid combinations such as `MultipleOf("non-numeric")` or `Annotated[int, Len(3)]`. -Downstream implementors may choose to raise an error, emit a warning, silently ignore -a metadata item, etc., if the metadata objects described below are used with an -incompatible type - or for any other reason!_ - -### Gt, Ge, Lt, Le - -Express inclusive and/or exclusive bounds on orderable values - which may be numbers, -dates, times, strings, sets, etc. Note that the boundary value need not be of the -same type that was annotated, so long as they can be compared: `Annotated[int, Gt(1.5)]` -is fine, for example, and implies that the value is an integer x such that `x > 1.5`. - -We suggest that implementors may also interpret `functools.partial(operator.le, 1.5)` -as being equivalent to `Gt(1.5)`, for users who wish to avoid a runtime dependency on -the `annotated-types` package. - -To be explicit, these types have the following meanings: - -* `Gt(x)` - value must be "Greater Than" `x` - equivalent to exclusive minimum -* `Ge(x)` - value must be "Greater than or Equal" to `x` - equivalent to inclusive minimum -* `Lt(x)` - value must be "Less Than" `x` - equivalent to exclusive maximum -* `Le(x)` - value must be "Less than or Equal" to `x` - equivalent to inclusive maximum - -### Interval - -`Interval(gt, ge, lt, le)` allows you to specify an upper and lower bound with a single -metadata object. `None` attributes should be ignored, and non-`None` attributes -treated as per the single bounds above. - -### MultipleOf - -`MultipleOf(multiple_of=x)` might be interpreted in two ways: - -1. Python semantics, implying `value % multiple_of == 0`, or -2. [JSONschema semantics](https://json-schema.org/draft/2020-12/json-schema-validation.html#rfc.section.6.2.1), - where `int(value / multiple_of) == value / multiple_of`. - -We encourage users to be aware of these two common interpretations and their -distinct behaviours, especially since very large or non-integer numbers make -it easy to cause silent data corruption due to floating-point imprecision. - -We encourage libraries to carefully document which interpretation they implement. - -### MinLen, MaxLen, Len - -`Len()` implies that `min_length <= len(value) <= max_length` - lower and upper bounds are inclusive. - -As well as `Len()` which can optionally include upper and lower bounds, we also -provide `MinLen(x)` and `MaxLen(y)` which are equivalent to `Len(min_length=x)` -and `Len(max_length=y)` respectively. - -`Len`, `MinLen`, and `MaxLen` may be used with any type which supports `len(value)`. - -Examples of usage: - -* `Annotated[list, MaxLen(10)]` (or `Annotated[list, Len(max_length=10))`) - list must have a length of 10 or less -* `Annotated[str, MaxLen(10)]` - string must have a length of 10 or less -* `Annotated[list, MinLen(3))` (or `Annotated[list, Len(min_length=3))`) - list must have a length of 3 or more -* `Annotated[list, Len(4, 6)]` - list must have a length of 4, 5, or 6 -* `Annotated[list, Len(8, 8)]` - list must have a length of exactly 8 - -#### Changed in v0.4.0 - -* `min_inclusive` has been renamed to `min_length`, no change in meaning -* `max_exclusive` has been renamed to `max_length`, upper bound is now **inclusive** instead of **exclusive** -* The recommendation that slices are interpreted as `Len` has been removed due to ambiguity and different semantic - meaning of the upper bound in slices vs. `Len` - -See [issue #23](https://github.com/annotated-types/annotated-types/issues/23) for discussion. - -### Timezone - -`Timezone` can be used with a `datetime` or a `time` to express which timezones -are allowed. `Annotated[datetime, Timezone(None)]` must be a naive datetime. -`Timezone[...]` ([literal ellipsis](https://docs.python.org/3/library/constants.html#Ellipsis)) -expresses that any timezone-aware datetime is allowed. You may also pass a specific -timezone string or [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) -object such as `Timezone(timezone.utc)` or `Timezone("Africa/Abidjan")` to express that you only -allow a specific timezone, though we note that this is often a symptom of fragile design. - -#### Changed in v0.x.x - -* `Timezone` accepts [`tzinfo`](https://docs.python.org/3/library/datetime.html#tzinfo-objects) objects instead of - `timezone`, extending compatibility to [`zoneinfo`](https://docs.python.org/3/library/zoneinfo.html) and third party libraries. - -### Unit - -`Unit(unit: str)` expresses that the annotated numeric value is the magnitude of -a quantity with the specified unit. For example, `Annotated[float, Unit("m/s")]` -would be a float representing a velocity in meters per second. - -Please note that `annotated_types` itself makes no attempt to parse or validate -the unit string in any way. That is left entirely to downstream libraries, -such as [`pint`](https://pint.readthedocs.io) or -[`astropy.units`](https://docs.astropy.org/en/stable/units/). - -An example of how a library might use this metadata: - -```python -from annotated_types import Unit -from typing import Annotated, TypeVar, Callable, Any, get_origin, get_args - -# given a type annotated with a unit: -Meters = Annotated[float, Unit("m")] - - -# you can cast the annotation to a specific unit type with any -# callable that accepts a string and returns the desired type -T = TypeVar("T") -def cast_unit(tp: Any, unit_cls: Callable[[str], T]) -> T | None: - if get_origin(tp) is Annotated: - for arg in get_args(tp): - if isinstance(arg, Unit): - return unit_cls(arg.unit) - return None - - -# using `pint` -import pint -pint_unit = cast_unit(Meters, pint.Unit) - - -# using `astropy.units` -import astropy.units as u -astropy_unit = cast_unit(Meters, u.Unit) -``` - -### Predicate - -`Predicate(func: Callable)` expresses that `func(value)` is truthy for valid values. -Users should prefer the statically inspectable metadata above, but if you need -the full power and flexibility of arbitrary runtime predicates... here it is. - -For some common constraints, we provide generic types: - -* `IsLower = Annotated[T, Predicate(str.islower)]` -* `IsUpper = Annotated[T, Predicate(str.isupper)]` -* `IsDigit = Annotated[T, Predicate(str.isdigit)]` -* `IsFinite = Annotated[T, Predicate(math.isfinite)]` -* `IsNotFinite = Annotated[T, Predicate(Not(math.isfinite))]` -* `IsNan = Annotated[T, Predicate(math.isnan)]` -* `IsNotNan = Annotated[T, Predicate(Not(math.isnan))]` -* `IsInfinite = Annotated[T, Predicate(math.isinf)]` -* `IsNotInfinite = Annotated[T, Predicate(Not(math.isinf))]` - -so that you can write e.g. `x: IsFinite[float] = 2.0` instead of the longer -(but exactly equivalent) `x: Annotated[float, Predicate(math.isfinite)] = 2.0`. - -Some libraries might have special logic to handle known or understandable predicates, -for example by checking for `str.isdigit` and using its presence to both call custom -logic to enforce digit-only strings, and customise some generated external schema. -Users are therefore encouraged to avoid indirection like `lambda s: s.lower()`, in -favor of introspectable methods such as `str.lower` or `re.compile("pattern").search`. - -To enable basic negation of commonly used predicates like `math.isnan` without introducing introspection that makes it impossible for implementers to introspect the predicate we provide a `Not` wrapper that simply negates the predicate in an introspectable manner. Several of the predicates listed above are created in this manner. - -We do not specify what behaviour should be expected for predicates that raise -an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently -skip invalid constraints, or statically raise an error; or it might try calling it -and then propagate or discard the resulting -`TypeError: descriptor 'isdigit' for 'str' objects doesn't apply to a 'int' object` -exception. We encourage libraries to document the behaviour they choose. - -### Doc - -`doc()` can be used to add documentation information in `Annotated`, for function and method parameters, variables, class attributes, return types, and any place where `Annotated` can be used. - -It expects a value that can be statically analyzed, as the main use case is for static analysis, editors, documentation generators, and similar tools. - -It returns a `DocInfo` class with a single attribute `documentation` containing the value passed to `doc()`. - -This is the early adopter's alternative form of the [`typing-doc` proposal](https://github.com/tiangolo/fastapi/blob/typing-doc/typing_doc.md). - -### Integrating downstream types with `GroupedMetadata` - -Implementers may choose to provide a convenience wrapper that groups multiple pieces of metadata. -This can help reduce verbosity and cognitive overhead for users. -For example, an implementer like Pydantic might provide a `Field` or `Meta` type that accepts keyword arguments and transforms these into low-level metadata: - -```python -from dataclasses import dataclass -from typing import Iterator -from annotated_types import GroupedMetadata, Ge - -@dataclass -class Field(GroupedMetadata): - ge: int | None = None - description: str | None = None - - def __iter__(self) -> Iterator[object]: - # Iterating over a GroupedMetadata object should yield annotated-types - # constraint metadata objects which describe it as fully as possible, - # and may include other unknown objects too. - if self.ge is not None: - yield Ge(self.ge) - if self.description is not None: - yield Description(self.description) -``` - -Libraries consuming annotated-types constraints should check for `GroupedMetadata` and unpack it by iterating over the object and treating the results as if they had been "unpacked" in the `Annotated` type. The same logic should be applied to the [PEP 646 `Unpack` type](https://peps.python.org/pep-0646/), so that `Annotated[T, Field(...)]`, `Annotated[T, Unpack[Field(...)]]` and `Annotated[T, *Field(...)]` are all treated consistently. - -Libraries consuming annotated-types should also ignore any metadata they do not recongize that came from unpacking a `GroupedMetadata`, just like they ignore unrecognized metadata in `Annotated` itself. - -Our own `annotated_types.Interval` class is a `GroupedMetadata` which unpacks itself into `Gt`, `Lt`, etc., so this is not an abstract concern. Similarly, `annotated_types.Len` is a `GroupedMetadata` which unpacks itself into `MinLen` (optionally) and `MaxLen`. - -### Consuming metadata - -We intend to not be prescriptive as to _how_ the metadata and constraints are used, but as an example of how one might parse constraints from types annotations see our [implementation in `test_main.py`](https://github.com/annotated-types/annotated-types/blob/f59cf6d1b5255a0fe359b93896759a180bec30ae/tests/test_main.py#L94-L103). - -It is up to the implementer to determine how this metadata is used. -You could use the metadata for runtime type checking, for generating schemas or to generate example data, amongst other use cases. - -## Design & History - -This package was designed at the PyCon 2022 sprints by the maintainers of Pydantic -and Hypothesis, with the goal of making it as easy as possible for end-users to -provide more informative annotations for use by runtime libraries. - -It is deliberately minimal, and following PEP-593 allows considerable downstream -discretion in what (if anything!) they choose to support. Nonetheless, we expect -that staying simple and covering _only_ the most common use-cases will give users -and maintainers the best experience we can. If you'd like more constraints for your -types - follow our lead, by defining them and documenting them downstream! diff --git a/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/RECORD b/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/RECORD deleted file mode 100644 index a66e278..0000000 --- a/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/RECORD +++ /dev/null @@ -1,10 +0,0 @@ -annotated_types-0.7.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -annotated_types-0.7.0.dist-info/METADATA,sha256=7ltqxksJJ0wCYFGBNIQCWTlWQGeAH0hRFdnK3CB895E,15046 -annotated_types-0.7.0.dist-info/RECORD,, -annotated_types-0.7.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87 -annotated_types-0.7.0.dist-info/licenses/LICENSE,sha256=_hBJiEsaDZNCkB6I4H8ykl0ksxIdmXK2poBfuYJLCV0,1083 -annotated_types/__init__.py,sha256=RynLsRKUEGI0KimXydlD1fZEfEzWwDo0Uon3zOKhG1Q,13819 -annotated_types/__pycache__/__init__.cpython-312.pyc,, -annotated_types/__pycache__/test_cases.cpython-312.pyc,, -annotated_types/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -annotated_types/test_cases.py,sha256=zHFX6EpcMbGJ8FzBYDbO56bPwx_DYIVSKbZM-4B3_lg,6421 diff --git a/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/WHEEL b/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/WHEEL deleted file mode 100644 index 516596c..0000000 --- a/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.24.2 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE b/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE deleted file mode 100644 index d99323a..0000000 --- a/venv/lib/python3.12/site-packages/annotated_types-0.7.0.dist-info/licenses/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2022 the contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/venv/lib/python3.12/site-packages/annotated_types/__init__.py b/venv/lib/python3.12/site-packages/annotated_types/__init__.py deleted file mode 100644 index 74e0dee..0000000 --- a/venv/lib/python3.12/site-packages/annotated_types/__init__.py +++ /dev/null @@ -1,432 +0,0 @@ -import math -import sys -import types -from dataclasses import dataclass -from datetime import tzinfo -from typing import TYPE_CHECKING, Any, Callable, Iterator, Optional, SupportsFloat, SupportsIndex, TypeVar, Union - -if sys.version_info < (3, 8): - from typing_extensions import Protocol, runtime_checkable -else: - from typing import Protocol, runtime_checkable - -if sys.version_info < (3, 9): - from typing_extensions import Annotated, Literal -else: - from typing import Annotated, Literal - -if sys.version_info < (3, 10): - EllipsisType = type(Ellipsis) - KW_ONLY = {} - SLOTS = {} -else: - from types import EllipsisType - - KW_ONLY = {"kw_only": True} - SLOTS = {"slots": True} - - -__all__ = ( - 'BaseMetadata', - 'GroupedMetadata', - 'Gt', - 'Ge', - 'Lt', - 'Le', - 'Interval', - 'MultipleOf', - 'MinLen', - 'MaxLen', - 'Len', - 'Timezone', - 'Predicate', - 'LowerCase', - 'UpperCase', - 'IsDigits', - 'IsFinite', - 'IsNotFinite', - 'IsNan', - 'IsNotNan', - 'IsInfinite', - 'IsNotInfinite', - 'doc', - 'DocInfo', - '__version__', -) - -__version__ = '0.7.0' - - -T = TypeVar('T') - - -# arguments that start with __ are considered -# positional only -# see https://peps.python.org/pep-0484/#positional-only-arguments - - -class SupportsGt(Protocol): - def __gt__(self: T, __other: T) -> bool: - ... - - -class SupportsGe(Protocol): - def __ge__(self: T, __other: T) -> bool: - ... - - -class SupportsLt(Protocol): - def __lt__(self: T, __other: T) -> bool: - ... - - -class SupportsLe(Protocol): - def __le__(self: T, __other: T) -> bool: - ... - - -class SupportsMod(Protocol): - def __mod__(self: T, __other: T) -> T: - ... - - -class SupportsDiv(Protocol): - def __div__(self: T, __other: T) -> T: - ... - - -class BaseMetadata: - """Base class for all metadata. - - This exists mainly so that implementers - can do `isinstance(..., BaseMetadata)` while traversing field annotations. - """ - - __slots__ = () - - -@dataclass(frozen=True, **SLOTS) -class Gt(BaseMetadata): - """Gt(gt=x) implies that the value must be greater than x. - - It can be used with any type that supports the ``>`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - gt: SupportsGt - - -@dataclass(frozen=True, **SLOTS) -class Ge(BaseMetadata): - """Ge(ge=x) implies that the value must be greater than or equal to x. - - It can be used with any type that supports the ``>=`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - ge: SupportsGe - - -@dataclass(frozen=True, **SLOTS) -class Lt(BaseMetadata): - """Lt(lt=x) implies that the value must be less than x. - - It can be used with any type that supports the ``<`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - lt: SupportsLt - - -@dataclass(frozen=True, **SLOTS) -class Le(BaseMetadata): - """Le(le=x) implies that the value must be less than or equal to x. - - It can be used with any type that supports the ``<=`` operator, - including numbers, dates and times, strings, sets, and so on. - """ - - le: SupportsLe - - -@runtime_checkable -class GroupedMetadata(Protocol): - """A grouping of multiple objects, like typing.Unpack. - - `GroupedMetadata` on its own is not metadata and has no meaning. - All of the constraints and metadata should be fully expressable - in terms of the `BaseMetadata`'s returned by `GroupedMetadata.__iter__()`. - - Concrete implementations should override `GroupedMetadata.__iter__()` - to add their own metadata. - For example: - - >>> @dataclass - >>> class Field(GroupedMetadata): - >>> gt: float | None = None - >>> description: str | None = None - ... - >>> def __iter__(self) -> Iterable[object]: - >>> if self.gt is not None: - >>> yield Gt(self.gt) - >>> if self.description is not None: - >>> yield Description(self.gt) - - Also see the implementation of `Interval` below for an example. - - Parsers should recognize this and unpack it so that it can be used - both with and without unpacking: - - - `Annotated[int, Field(...)]` (parser must unpack Field) - - `Annotated[int, *Field(...)]` (PEP-646) - """ # noqa: trailing-whitespace - - @property - def __is_annotated_types_grouped_metadata__(self) -> Literal[True]: - return True - - def __iter__(self) -> Iterator[object]: - ... - - if not TYPE_CHECKING: - __slots__ = () # allow subclasses to use slots - - def __init_subclass__(cls, *args: Any, **kwargs: Any) -> None: - # Basic ABC like functionality without the complexity of an ABC - super().__init_subclass__(*args, **kwargs) - if cls.__iter__ is GroupedMetadata.__iter__: - raise TypeError("Can't subclass GroupedMetadata without implementing __iter__") - - def __iter__(self) -> Iterator[object]: # noqa: F811 - raise NotImplementedError # more helpful than "None has no attribute..." type errors - - -@dataclass(frozen=True, **KW_ONLY, **SLOTS) -class Interval(GroupedMetadata): - """Interval can express inclusive or exclusive bounds with a single object. - - It accepts keyword arguments ``gt``, ``ge``, ``lt``, and/or ``le``, which - are interpreted the same way as the single-bound constraints. - """ - - gt: Union[SupportsGt, None] = None - ge: Union[SupportsGe, None] = None - lt: Union[SupportsLt, None] = None - le: Union[SupportsLe, None] = None - - def __iter__(self) -> Iterator[BaseMetadata]: - """Unpack an Interval into zero or more single-bounds.""" - if self.gt is not None: - yield Gt(self.gt) - if self.ge is not None: - yield Ge(self.ge) - if self.lt is not None: - yield Lt(self.lt) - if self.le is not None: - yield Le(self.le) - - -@dataclass(frozen=True, **SLOTS) -class MultipleOf(BaseMetadata): - """MultipleOf(multiple_of=x) might be interpreted in two ways: - - 1. Python semantics, implying ``value % multiple_of == 0``, or - 2. JSONschema semantics, where ``int(value / multiple_of) == value / multiple_of`` - - We encourage users to be aware of these two common interpretations, - and libraries to carefully document which they implement. - """ - - multiple_of: Union[SupportsDiv, SupportsMod] - - -@dataclass(frozen=True, **SLOTS) -class MinLen(BaseMetadata): - """ - MinLen() implies minimum inclusive length, - e.g. ``len(value) >= min_length``. - """ - - min_length: Annotated[int, Ge(0)] - - -@dataclass(frozen=True, **SLOTS) -class MaxLen(BaseMetadata): - """ - MaxLen() implies maximum inclusive length, - e.g. ``len(value) <= max_length``. - """ - - max_length: Annotated[int, Ge(0)] - - -@dataclass(frozen=True, **SLOTS) -class Len(GroupedMetadata): - """ - Len() implies that ``min_length <= len(value) <= max_length``. - - Upper bound may be omitted or ``None`` to indicate no upper length bound. - """ - - min_length: Annotated[int, Ge(0)] = 0 - max_length: Optional[Annotated[int, Ge(0)]] = None - - def __iter__(self) -> Iterator[BaseMetadata]: - """Unpack a Len into zone or more single-bounds.""" - if self.min_length > 0: - yield MinLen(self.min_length) - if self.max_length is not None: - yield MaxLen(self.max_length) - - -@dataclass(frozen=True, **SLOTS) -class Timezone(BaseMetadata): - """Timezone(tz=...) requires a datetime to be aware (or ``tz=None``, naive). - - ``Annotated[datetime, Timezone(None)]`` must be a naive datetime. - ``Timezone[...]`` (the ellipsis literal) expresses that the datetime must be - tz-aware but any timezone is allowed. - - You may also pass a specific timezone string or tzinfo object such as - ``Timezone(timezone.utc)`` or ``Timezone("Africa/Abidjan")`` to express that - you only allow a specific timezone, though we note that this is often - a symptom of poor design. - """ - - tz: Union[str, tzinfo, EllipsisType, None] - - -@dataclass(frozen=True, **SLOTS) -class Unit(BaseMetadata): - """Indicates that the value is a physical quantity with the specified unit. - - It is intended for usage with numeric types, where the value represents the - magnitude of the quantity. For example, ``distance: Annotated[float, Unit('m')]`` - or ``speed: Annotated[float, Unit('m/s')]``. - - Interpretation of the unit string is left to the discretion of the consumer. - It is suggested to follow conventions established by python libraries that work - with physical quantities, such as - - - ``pint`` : - - ``astropy.units``: - - For indicating a quantity with a certain dimensionality but without a specific unit - it is recommended to use square brackets, e.g. `Annotated[float, Unit('[time]')]`. - Note, however, ``annotated_types`` itself makes no use of the unit string. - """ - - unit: str - - -@dataclass(frozen=True, **SLOTS) -class Predicate(BaseMetadata): - """``Predicate(func: Callable)`` implies `func(value)` is truthy for valid values. - - Users should prefer statically inspectable metadata, but if you need the full - power and flexibility of arbitrary runtime predicates... here it is. - - We provide a few predefined predicates for common string constraints: - ``IsLower = Predicate(str.islower)``, ``IsUpper = Predicate(str.isupper)``, and - ``IsDigits = Predicate(str.isdigit)``. Users are encouraged to use methods which - can be given special handling, and avoid indirection like ``lambda s: s.lower()``. - - Some libraries might have special logic to handle certain predicates, e.g. by - checking for `str.isdigit` and using its presence to both call custom logic to - enforce digit-only strings, and customise some generated external schema. - - We do not specify what behaviour should be expected for predicates that raise - an exception. For example `Annotated[int, Predicate(str.isdigit)]` might silently - skip invalid constraints, or statically raise an error; or it might try calling it - and then propagate or discard the resulting exception. - """ - - func: Callable[[Any], bool] - - def __repr__(self) -> str: - if getattr(self.func, "__name__", "") == "": - return f"{self.__class__.__name__}({self.func!r})" - if isinstance(self.func, (types.MethodType, types.BuiltinMethodType)) and ( - namespace := getattr(self.func.__self__, "__name__", None) - ): - return f"{self.__class__.__name__}({namespace}.{self.func.__name__})" - if isinstance(self.func, type(str.isascii)): # method descriptor - return f"{self.__class__.__name__}({self.func.__qualname__})" - return f"{self.__class__.__name__}({self.func.__name__})" - - -@dataclass -class Not: - func: Callable[[Any], bool] - - def __call__(self, __v: Any) -> bool: - return not self.func(__v) - - -_StrType = TypeVar("_StrType", bound=str) - -LowerCase = Annotated[_StrType, Predicate(str.islower)] -""" -Return True if the string is a lowercase string, False otherwise. - -A string is lowercase if all cased characters in the string are lowercase and there is at least one cased character in the string. -""" # noqa: E501 -UpperCase = Annotated[_StrType, Predicate(str.isupper)] -""" -Return True if the string is an uppercase string, False otherwise. - -A string is uppercase if all cased characters in the string are uppercase and there is at least one cased character in the string. -""" # noqa: E501 -IsDigit = Annotated[_StrType, Predicate(str.isdigit)] -IsDigits = IsDigit # type: ignore # plural for backwards compatibility, see #63 -""" -Return True if the string is a digit string, False otherwise. - -A string is a digit string if all characters in the string are digits and there is at least one character in the string. -""" # noqa: E501 -IsAscii = Annotated[_StrType, Predicate(str.isascii)] -""" -Return True if all characters in the string are ASCII, False otherwise. - -ASCII characters have code points in the range U+0000-U+007F. Empty string is ASCII too. -""" - -_NumericType = TypeVar('_NumericType', bound=Union[SupportsFloat, SupportsIndex]) -IsFinite = Annotated[_NumericType, Predicate(math.isfinite)] -"""Return True if x is neither an infinity nor a NaN, and False otherwise.""" -IsNotFinite = Annotated[_NumericType, Predicate(Not(math.isfinite))] -"""Return True if x is one of infinity or NaN, and False otherwise""" -IsNan = Annotated[_NumericType, Predicate(math.isnan)] -"""Return True if x is a NaN (not a number), and False otherwise.""" -IsNotNan = Annotated[_NumericType, Predicate(Not(math.isnan))] -"""Return True if x is anything but NaN (not a number), and False otherwise.""" -IsInfinite = Annotated[_NumericType, Predicate(math.isinf)] -"""Return True if x is a positive or negative infinity, and False otherwise.""" -IsNotInfinite = Annotated[_NumericType, Predicate(Not(math.isinf))] -"""Return True if x is neither a positive or negative infinity, and False otherwise.""" - -try: - from typing_extensions import DocInfo, doc # type: ignore [attr-defined] -except ImportError: - - @dataclass(frozen=True, **SLOTS) - class DocInfo: # type: ignore [no-redef] - """ " - The return value of doc(), mainly to be used by tools that want to extract the - Annotated documentation at runtime. - """ - - documentation: str - """The documentation string passed to doc().""" - - def doc( - documentation: str, - ) -> DocInfo: - """ - Add documentation to a type annotation inside of Annotated. - - For example: - - >>> def hi(name: Annotated[int, doc("The name of the user")]) -> None: ... - """ - return DocInfo(documentation) diff --git a/venv/lib/python3.12/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/annotated_types/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 14fa32887b0c8dc46605919fce58c5d75744674e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18616 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 We%KN?(<%J0bL*Jk{ozp&>Hh(c6!9Yf diff --git a/venv/lib/python3.12/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc b/venv/lib/python3.12/site-packages/annotated_types/__pycache__/test_cases.cpython-312.pyc deleted file mode 100644 index 973ebfd9fc126ddb2a925261599613c2968fd510..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13235 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 diff --git a/venv/lib/python3.12/site-packages/annotated_types/py.typed b/venv/lib/python3.12/site-packages/annotated_types/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/annotated_types/test_cases.py b/venv/lib/python3.12/site-packages/annotated_types/test_cases.py deleted file mode 100644 index d9164d6..0000000 --- a/venv/lib/python3.12/site-packages/annotated_types/test_cases.py +++ /dev/null @@ -1,151 +0,0 @@ -import math -import sys -from datetime import date, datetime, timedelta, timezone -from decimal import Decimal -from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Set, Tuple - -if sys.version_info < (3, 9): - from typing_extensions import Annotated -else: - from typing import Annotated - -import annotated_types as at - - -class Case(NamedTuple): - """ - A test case for `annotated_types`. - """ - - annotation: Any - valid_cases: Iterable[Any] - invalid_cases: Iterable[Any] - - -def cases() -> Iterable[Case]: - # Gt, Ge, Lt, Le - yield Case(Annotated[int, at.Gt(4)], (5, 6, 1000), (4, 0, -1)) - yield Case(Annotated[float, at.Gt(0.5)], (0.6, 0.7, 0.8, 0.9), (0.5, 0.0, -0.1)) - yield Case( - Annotated[datetime, at.Gt(datetime(2000, 1, 1))], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - [datetime(2000, 1, 1), datetime(1999, 12, 31)], - ) - yield Case( - Annotated[datetime, at.Gt(date(2000, 1, 1))], - [date(2000, 1, 2), date(2000, 1, 3)], - [date(2000, 1, 1), date(1999, 12, 31)], - ) - yield Case( - Annotated[datetime, at.Gt(Decimal('1.123'))], - [Decimal('1.1231'), Decimal('123')], - [Decimal('1.123'), Decimal('0')], - ) - - yield Case(Annotated[int, at.Ge(4)], (4, 5, 6, 1000, 4), (0, -1)) - yield Case(Annotated[float, at.Ge(0.5)], (0.5, 0.6, 0.7, 0.8, 0.9), (0.4, 0.0, -0.1)) - yield Case( - Annotated[datetime, at.Ge(datetime(2000, 1, 1))], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - [datetime(1998, 1, 1), datetime(1999, 12, 31)], - ) - - yield Case(Annotated[int, at.Lt(4)], (0, -1), (4, 5, 6, 1000, 4)) - yield Case(Annotated[float, at.Lt(0.5)], (0.4, 0.0, -0.1), (0.5, 0.6, 0.7, 0.8, 0.9)) - yield Case( - Annotated[datetime, at.Lt(datetime(2000, 1, 1))], - [datetime(1999, 12, 31), datetime(1999, 12, 31)], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - ) - - yield Case(Annotated[int, at.Le(4)], (4, 0, -1), (5, 6, 1000)) - yield Case(Annotated[float, at.Le(0.5)], (0.5, 0.0, -0.1), (0.6, 0.7, 0.8, 0.9)) - yield Case( - Annotated[datetime, at.Le(datetime(2000, 1, 1))], - [datetime(2000, 1, 1), datetime(1999, 12, 31)], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - ) - - # Interval - yield Case(Annotated[int, at.Interval(gt=4)], (5, 6, 1000), (4, 0, -1)) - yield Case(Annotated[int, at.Interval(gt=4, lt=10)], (5, 6), (4, 10, 1000, 0, -1)) - yield Case(Annotated[float, at.Interval(ge=0.5, le=1)], (0.5, 0.9, 1), (0.49, 1.1)) - yield Case( - Annotated[datetime, at.Interval(gt=datetime(2000, 1, 1), le=datetime(2000, 1, 3))], - [datetime(2000, 1, 2), datetime(2000, 1, 3)], - [datetime(2000, 1, 1), datetime(2000, 1, 4)], - ) - - yield Case(Annotated[int, at.MultipleOf(multiple_of=3)], (0, 3, 9), (1, 2, 4)) - yield Case(Annotated[float, at.MultipleOf(multiple_of=0.5)], (0, 0.5, 1, 1.5), (0.4, 1.1)) - - # lengths - - yield Case(Annotated[str, at.MinLen(3)], ('123', '1234', 'x' * 10), ('', '1', '12')) - yield Case(Annotated[str, at.Len(3)], ('123', '1234', 'x' * 10), ('', '1', '12')) - yield Case(Annotated[List[int], at.MinLen(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2])) - yield Case(Annotated[List[int], at.Len(3)], ([1, 2, 3], [1, 2, 3, 4], [1] * 10), ([], [1], [1, 2])) - - yield Case(Annotated[str, at.MaxLen(4)], ('', '1234'), ('12345', 'x' * 10)) - yield Case(Annotated[str, at.Len(0, 4)], ('', '1234'), ('12345', 'x' * 10)) - yield Case(Annotated[List[str], at.MaxLen(4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10)) - yield Case(Annotated[List[str], at.Len(0, 4)], ([], ['a', 'bcdef'], ['a', 'b', 'c']), (['a'] * 5, ['b'] * 10)) - - yield Case(Annotated[str, at.Len(3, 5)], ('123', '12345'), ('', '1', '12', '123456', 'x' * 10)) - yield Case(Annotated[str, at.Len(3, 3)], ('123',), ('12', '1234')) - - yield Case(Annotated[Dict[int, int], at.Len(2, 3)], [{1: 1, 2: 2}], [{}, {1: 1}, {1: 1, 2: 2, 3: 3, 4: 4}]) - yield Case(Annotated[Set[int], at.Len(2, 3)], ({1, 2}, {1, 2, 3}), (set(), {1}, {1, 2, 3, 4})) - yield Case(Annotated[Tuple[int, ...], at.Len(2, 3)], ((1, 2), (1, 2, 3)), ((), (1,), (1, 2, 3, 4))) - - # Timezone - - yield Case( - Annotated[datetime, at.Timezone(None)], [datetime(2000, 1, 1)], [datetime(2000, 1, 1, tzinfo=timezone.utc)] - ) - yield Case( - Annotated[datetime, at.Timezone(...)], [datetime(2000, 1, 1, tzinfo=timezone.utc)], [datetime(2000, 1, 1)] - ) - yield Case( - Annotated[datetime, at.Timezone(timezone.utc)], - [datetime(2000, 1, 1, tzinfo=timezone.utc)], - [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))], - ) - yield Case( - Annotated[datetime, at.Timezone('Europe/London')], - [datetime(2000, 1, 1, tzinfo=timezone(timedelta(0), name='Europe/London'))], - [datetime(2000, 1, 1), datetime(2000, 1, 1, tzinfo=timezone(timedelta(hours=6)))], - ) - - # Quantity - - yield Case(Annotated[float, at.Unit(unit='m')], (5, 4.2), ('5m', '4.2m')) - - # predicate types - - yield Case(at.LowerCase[str], ['abc', 'foobar'], ['', 'A', 'Boom']) - yield Case(at.UpperCase[str], ['ABC', 'DEFO'], ['', 'a', 'abc', 'AbC']) - yield Case(at.IsDigit[str], ['123'], ['', 'ab', 'a1b2']) - yield Case(at.IsAscii[str], ['123', 'foo bar'], ['ÂŁ100', 'đźŠ', 'whatever đź‘€']) - - yield Case(Annotated[int, at.Predicate(lambda x: x % 2 == 0)], [0, 2, 4], [1, 3, 5]) - - yield Case(at.IsFinite[float], [1.23], [math.nan, math.inf, -math.inf]) - yield Case(at.IsNotFinite[float], [math.nan, math.inf], [1.23]) - yield Case(at.IsNan[float], [math.nan], [1.23, math.inf]) - yield Case(at.IsNotNan[float], [1.23, math.inf], [math.nan]) - yield Case(at.IsInfinite[float], [math.inf], [math.nan, 1.23]) - yield Case(at.IsNotInfinite[float], [math.nan, 1.23], [math.inf]) - - # check stacked predicates - yield Case(at.IsInfinite[Annotated[float, at.Predicate(lambda x: x > 0)]], [math.inf], [-math.inf, 1.23, math.nan]) - - # doc - yield Case(Annotated[int, at.doc("A number")], [1, 2], []) - - # custom GroupedMetadata - class MyCustomGroupedMetadata(at.GroupedMetadata): - def __iter__(self) -> Iterator[at.Predicate]: - yield at.Predicate(lambda x: float(x).is_integer()) - - yield Case(Annotated[float, MyCustomGroupedMetadata()], [0, 2.0], [0.01, 1.5]) diff --git a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/LICENSE b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/LICENSE deleted file mode 100644 index 104eebf..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 Alex Grönholm - -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/python3.12/site-packages/anyio-4.9.0.dist-info/METADATA b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/METADATA deleted file mode 100644 index 9d87e1d..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/METADATA +++ /dev/null @@ -1,105 +0,0 @@ -Metadata-Version: 2.2 -Name: anyio -Version: 4.9.0 -Summary: High level compatibility layer for multiple asynchronous event loop implementations -Author-email: Alex Grönholm -License: MIT -Project-URL: Documentation, https://anyio.readthedocs.io/en/latest/ -Project-URL: Changelog, https://anyio.readthedocs.io/en/stable/versionhistory.html -Project-URL: Source code, https://github.com/agronholm/anyio -Project-URL: Issue tracker, https://github.com/agronholm/anyio/issues -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Framework :: AnyIO -Classifier: Typing :: Typed -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 -Requires-Python: >=3.9 -Description-Content-Type: text/x-rst -License-File: LICENSE -Requires-Dist: exceptiongroup>=1.0.2; python_version < "3.11" -Requires-Dist: idna>=2.8 -Requires-Dist: sniffio>=1.1 -Requires-Dist: typing_extensions>=4.5; python_version < "3.13" -Provides-Extra: trio -Requires-Dist: trio>=0.26.1; extra == "trio" -Provides-Extra: test -Requires-Dist: anyio[trio]; extra == "test" -Requires-Dist: blockbuster>=1.5.23; extra == "test" -Requires-Dist: coverage[toml]>=7; extra == "test" -Requires-Dist: exceptiongroup>=1.2.0; extra == "test" -Requires-Dist: hypothesis>=4.0; extra == "test" -Requires-Dist: psutil>=5.9; extra == "test" -Requires-Dist: pytest>=7.0; extra == "test" -Requires-Dist: trustme; extra == "test" -Requires-Dist: truststore>=0.9.1; python_version >= "3.10" and extra == "test" -Requires-Dist: uvloop>=0.21; (platform_python_implementation == "CPython" and platform_system != "Windows" and python_version < "3.14") and extra == "test" -Provides-Extra: doc -Requires-Dist: packaging; extra == "doc" -Requires-Dist: Sphinx~=8.2; extra == "doc" -Requires-Dist: sphinx_rtd_theme; extra == "doc" -Requires-Dist: sphinx-autodoc-typehints>=1.2.0; extra == "doc" - -.. image:: https://github.com/agronholm/anyio/actions/workflows/test.yml/badge.svg - :target: https://github.com/agronholm/anyio/actions/workflows/test.yml - :alt: Build Status -.. image:: https://coveralls.io/repos/github/agronholm/anyio/badge.svg?branch=master - :target: https://coveralls.io/github/agronholm/anyio?branch=master - :alt: Code Coverage -.. image:: https://readthedocs.org/projects/anyio/badge/?version=latest - :target: https://anyio.readthedocs.io/en/latest/?badge=latest - :alt: Documentation -.. image:: https://badges.gitter.im/gitterHQ/gitter.svg - :target: https://gitter.im/python-trio/AnyIO - :alt: Gitter chat - -AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio_ or -trio_. It implements trio-like `structured concurrency`_ (SC) on top of asyncio and works in harmony -with the native SC of trio itself. - -Applications and libraries written against AnyIO's API will run unmodified on either asyncio_ or -trio_. AnyIO can also be adopted into a library or application incrementally – bit by bit, no full -refactoring necessary. It will blend in with the native libraries of your chosen backend. - -Documentation -------------- - -View full documentation at: https://anyio.readthedocs.io/ - -Features --------- - -AnyIO offers the following functionality: - -* Task groups (nurseries_ in trio terminology) -* High-level networking (TCP, UDP and UNIX sockets) - - * `Happy eyeballs`_ algorithm for TCP connections (more robust than that of asyncio on Python - 3.8) - * async/await style UDP sockets (unlike asyncio where you still have to use Transports and - Protocols) - -* A versatile API for byte streams and object streams -* Inter-task synchronization and communication (locks, conditions, events, semaphores, object - streams) -* Worker threads -* Subprocesses -* Asynchronous file I/O (using worker threads) -* Signal handling - -AnyIO also comes with its own pytest_ plugin which also supports asynchronous fixtures. -It even works with the popular Hypothesis_ library. - -.. _asyncio: https://docs.python.org/3/library/asyncio.html -.. _trio: https://github.com/python-trio/trio -.. _structured concurrency: https://en.wikipedia.org/wiki/Structured_concurrency -.. _nurseries: https://trio.readthedocs.io/en/stable/reference-core.html#nurseries-and-spawning -.. _Happy eyeballs: https://en.wikipedia.org/wiki/Happy_Eyeballs -.. _pytest: https://docs.pytest.org/en/latest/ -.. _Hypothesis: https://hypothesis.works/ diff --git a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/RECORD b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/RECORD deleted file mode 100644 index 40eedc8..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/RECORD +++ /dev/null @@ -1,88 +0,0 @@ -anyio-4.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -anyio-4.9.0.dist-info/LICENSE,sha256=U2GsncWPLvX9LpsJxoKXwX8ElQkJu8gCO9uC6s8iwrA,1081 -anyio-4.9.0.dist-info/METADATA,sha256=vvkWPXXTbrpTCFK7zdcYwQcSQhx6Q4qITM9t_PEQCrY,4682 -anyio-4.9.0.dist-info/RECORD,, -anyio-4.9.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91 -anyio-4.9.0.dist-info/entry_points.txt,sha256=_d6Yu6uiaZmNe0CydowirE9Cmg7zUL2g08tQpoS3Qvc,39 -anyio-4.9.0.dist-info/top_level.txt,sha256=QglSMiWX8_5dpoVAEIHdEYzvqFMdSYWmCj6tYw2ITkQ,6 -anyio/__init__.py,sha256=t8bZuNXa5ncwXBaNKbv48BDgZt48RT_zCEtrnPmjNU8,4993 -anyio/__pycache__/__init__.cpython-312.pyc,, -anyio/__pycache__/from_thread.cpython-312.pyc,, -anyio/__pycache__/lowlevel.cpython-312.pyc,, -anyio/__pycache__/pytest_plugin.cpython-312.pyc,, -anyio/__pycache__/to_interpreter.cpython-312.pyc,, -anyio/__pycache__/to_process.cpython-312.pyc,, -anyio/__pycache__/to_thread.cpython-312.pyc,, -anyio/_backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/_backends/__pycache__/__init__.cpython-312.pyc,, -anyio/_backends/__pycache__/_asyncio.cpython-312.pyc,, -anyio/_backends/__pycache__/_trio.cpython-312.pyc,, -anyio/_backends/_asyncio.py,sha256=AT1oaTfCE-9YFxooMlvld2yDqY5U2A-ANMcBDh9eRfI,93455 -anyio/_backends/_trio.py,sha256=HVfDqRGQ7Xj3JfTcYdgzmC7pZEplqU4NOO5kxNNSZnk,40429 -anyio/_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/_core/__pycache__/__init__.cpython-312.pyc,, -anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc,, -anyio/_core/__pycache__/_eventloop.cpython-312.pyc,, -anyio/_core/__pycache__/_exceptions.cpython-312.pyc,, -anyio/_core/__pycache__/_fileio.cpython-312.pyc,, -anyio/_core/__pycache__/_resources.cpython-312.pyc,, -anyio/_core/__pycache__/_signals.cpython-312.pyc,, -anyio/_core/__pycache__/_sockets.cpython-312.pyc,, -anyio/_core/__pycache__/_streams.cpython-312.pyc,, -anyio/_core/__pycache__/_subprocesses.cpython-312.pyc,, -anyio/_core/__pycache__/_synchronization.cpython-312.pyc,, -anyio/_core/__pycache__/_tasks.cpython-312.pyc,, -anyio/_core/__pycache__/_tempfile.cpython-312.pyc,, -anyio/_core/__pycache__/_testing.cpython-312.pyc,, -anyio/_core/__pycache__/_typedattr.cpython-312.pyc,, -anyio/_core/_asyncio_selector_thread.py,sha256=2PdxFM3cs02Kp6BSppbvmRT7q7asreTW5FgBxEsflBo,5626 -anyio/_core/_eventloop.py,sha256=t_tAwBFPjF8jrZGjlJ6bbYy6KA3bjsbZxV9mvh9t1i0,4695 -anyio/_core/_exceptions.py,sha256=RlPRlwastdmfDPoskdXNO6SI8_l3fclA2wtW6cokU9I,3503 -anyio/_core/_fileio.py,sha256=qFZhkLIz0cGXluvih_vcPUTucgq8UFVgsTCtYbijZIg,23340 -anyio/_core/_resources.py,sha256=NbmU5O5UX3xEyACnkmYX28Fmwdl-f-ny0tHym26e0w0,435 -anyio/_core/_signals.py,sha256=vulT1M1xdLYtAR-eY5TamIgaf1WTlOwOrMGwswlTTr8,905 -anyio/_core/_sockets.py,sha256=5Okc_UThGDEN9KCnsIhqWPRHBNuSy6b4NmG1i51TVF4,27150 -anyio/_core/_streams.py,sha256=OnaKgoDD-FcMSwLvkoAUGP51sG2ZdRvMpxt9q2w1gYA,1804 -anyio/_core/_subprocesses.py,sha256=EXm5igL7dj55iYkPlbYVAqtbqxJxjU-6OndSTIx9SRg,8047 -anyio/_core/_synchronization.py,sha256=DwUh8Tl6cG_UMVC_GyzPoC_U9BpfDfjMl9SINSxcZN4,20320 -anyio/_core/_tasks.py,sha256=f3CuWwo06cCZ6jaOv-JHFKWkgpgf2cvaF25Oh4augMA,4757 -anyio/_core/_tempfile.py,sha256=s-_ucacXbxBH5Bo5eo65lN0lPwZQd5B8yNN_9nARpCM,19696 -anyio/_core/_testing.py,sha256=YUGwA5cgFFbUTv4WFd7cv_BSVr4ryTtPp8owQA3JdWE,2118 -anyio/_core/_typedattr.py,sha256=P4ozZikn3-DbpoYcvyghS_FOYAgbmUxeoU8-L_07pZM,2508 -anyio/abc/__init__.py,sha256=c2OQbTCS_fQowviMXanLPh8m29ccwkXmpDr7uyNZYOo,2652 -anyio/abc/__pycache__/__init__.cpython-312.pyc,, -anyio/abc/__pycache__/_eventloop.cpython-312.pyc,, -anyio/abc/__pycache__/_resources.cpython-312.pyc,, -anyio/abc/__pycache__/_sockets.cpython-312.pyc,, -anyio/abc/__pycache__/_streams.cpython-312.pyc,, -anyio/abc/__pycache__/_subprocesses.cpython-312.pyc,, -anyio/abc/__pycache__/_tasks.cpython-312.pyc,, -anyio/abc/__pycache__/_testing.cpython-312.pyc,, -anyio/abc/_eventloop.py,sha256=UmL8DZCvQTgxzmyBZcGm9kWj9VQY8BMWueLh5S8yWN4,9682 -anyio/abc/_resources.py,sha256=DrYvkNN1hH6Uvv5_5uKySvDsnknGVDe8FCKfko0VtN8,783 -anyio/abc/_sockets.py,sha256=KhWtJxan8jpBXKwPaFeQzI4iRXdFaOIn0HXtDZnaO7U,6262 -anyio/abc/_streams.py,sha256=He_JpkAW2g5veOzcUq0XsRC2nId_i35L-d8cs7Uj1ZQ,6598 -anyio/abc/_subprocesses.py,sha256=cumAPJTktOQtw63IqG0lDpyZqu_l1EElvQHMiwJgL08,2067 -anyio/abc/_tasks.py,sha256=yJWbMwowvqjlAX4oJ3l9Is1w-zwynr2lX1Z02AWJqsY,3080 -anyio/abc/_testing.py,sha256=tBJUzkSfOXJw23fe8qSJ03kJlShOYjjaEyFB6k6MYT8,1821 -anyio/from_thread.py,sha256=MbXHZpgM9wgsRkbGhMNMomEGYj7Y_QYq6a5BZ3c5Ev8,17478 -anyio/lowlevel.py,sha256=nkgmW--SdxGVp0cmLUYazjkigveRm5HY7-gW8Bpp9oY,4169 -anyio/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/pytest_plugin.py,sha256=qXNwk9Pa7hPQKWocgLl9qijqKGMkGzdH2wJa-jPkGUM,9375 -anyio/streams/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -anyio/streams/__pycache__/__init__.cpython-312.pyc,, -anyio/streams/__pycache__/buffered.cpython-312.pyc,, -anyio/streams/__pycache__/file.cpython-312.pyc,, -anyio/streams/__pycache__/memory.cpython-312.pyc,, -anyio/streams/__pycache__/stapled.cpython-312.pyc,, -anyio/streams/__pycache__/text.cpython-312.pyc,, -anyio/streams/__pycache__/tls.cpython-312.pyc,, -anyio/streams/buffered.py,sha256=UCldKC168YuLvT7n3HtNPnQ2iWAMSTYQWbZvzLwMwkM,4500 -anyio/streams/file.py,sha256=6uoTNb5KbMoj-6gS3_xrrL8uZN8Q4iIvOS1WtGyFfKw,4383 -anyio/streams/memory.py,sha256=o1OVVx0OooteTTe2GytJreum93Ucuw5s4cAsr3X0-Ag,10560 -anyio/streams/stapled.py,sha256=U09pCrmOw9kkNhe6tKopsm1QIMT1lFTFvtb-A7SIe4k,4302 -anyio/streams/text.py,sha256=6x8w8xlfCZKTUWQoJiMPoMhSSJFUBRKgoBNSBtbd9yg,5094 -anyio/streams/tls.py,sha256=HxzpVmUgo8SUSIBass_lvef1pAI1uRSrnysM3iEGzl4,13199 -anyio/to_interpreter.py,sha256=UhuNCIucCRN7ZtyJg35Mlamzs1JpgDvK4xnL4TDWrAo,6527 -anyio/to_process.py,sha256=ZvruelRM-HNmqDaql4sdNODg2QD_uSlwSCxnV4OhsfQ,9595 -anyio/to_thread.py,sha256=WM2JQ2MbVsd5D5CM08bQiTwzZIvpsGjfH1Fy247KoDQ,2396 diff --git a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/WHEEL b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/WHEEL deleted file mode 100644 index 9c3ae63..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: setuptools (76.0.0) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/entry_points.txt b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/entry_points.txt deleted file mode 100644 index 44dd9bd..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[pytest11] -anyio = anyio.pytest_plugin diff --git a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/top_level.txt b/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/top_level.txt deleted file mode 100644 index c77c069..0000000 --- a/venv/lib/python3.12/site-packages/anyio-4.9.0.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -anyio diff --git a/venv/lib/python3.12/site-packages/anyio/__init__.py b/venv/lib/python3.12/site-packages/anyio/__init__.py deleted file mode 100644 index 578cda6..0000000 --- a/venv/lib/python3.12/site-packages/anyio/__init__.py +++ /dev/null @@ -1,85 +0,0 @@ -from __future__ import annotations - -from ._core._eventloop import current_time as current_time -from ._core._eventloop import get_all_backends as get_all_backends -from ._core._eventloop import get_cancelled_exc_class as get_cancelled_exc_class -from ._core._eventloop import run as run -from ._core._eventloop import sleep as sleep -from ._core._eventloop import sleep_forever as sleep_forever -from ._core._eventloop import sleep_until as sleep_until -from ._core._exceptions import BrokenResourceError as BrokenResourceError -from ._core._exceptions import BrokenWorkerIntepreter as BrokenWorkerIntepreter -from ._core._exceptions import BrokenWorkerProcess as BrokenWorkerProcess -from ._core._exceptions import BusyResourceError as BusyResourceError -from ._core._exceptions import ClosedResourceError as ClosedResourceError -from ._core._exceptions import DelimiterNotFound as DelimiterNotFound -from ._core._exceptions import EndOfStream as EndOfStream -from ._core._exceptions import IncompleteRead as IncompleteRead -from ._core._exceptions import TypedAttributeLookupError as TypedAttributeLookupError -from ._core._exceptions import WouldBlock as WouldBlock -from ._core._fileio import AsyncFile as AsyncFile -from ._core._fileio import Path as Path -from ._core._fileio import open_file as open_file -from ._core._fileio import wrap_file as wrap_file -from ._core._resources import aclose_forcefully as aclose_forcefully -from ._core._signals import open_signal_receiver as open_signal_receiver -from ._core._sockets import connect_tcp as connect_tcp -from ._core._sockets import connect_unix as connect_unix -from ._core._sockets import create_connected_udp_socket as create_connected_udp_socket -from ._core._sockets import ( - create_connected_unix_datagram_socket as create_connected_unix_datagram_socket, -) -from ._core._sockets import create_tcp_listener as create_tcp_listener -from ._core._sockets import create_udp_socket as create_udp_socket -from ._core._sockets import create_unix_datagram_socket as create_unix_datagram_socket -from ._core._sockets import create_unix_listener as create_unix_listener -from ._core._sockets import getaddrinfo as getaddrinfo -from ._core._sockets import getnameinfo as getnameinfo -from ._core._sockets import wait_readable as wait_readable -from ._core._sockets import wait_socket_readable as wait_socket_readable -from ._core._sockets import wait_socket_writable as wait_socket_writable -from ._core._sockets import wait_writable as wait_writable -from ._core._streams import create_memory_object_stream as create_memory_object_stream -from ._core._subprocesses import open_process as open_process -from ._core._subprocesses import run_process as run_process -from ._core._synchronization import CapacityLimiter as CapacityLimiter -from ._core._synchronization import ( - CapacityLimiterStatistics as CapacityLimiterStatistics, -) -from ._core._synchronization import Condition as Condition -from ._core._synchronization import ConditionStatistics as ConditionStatistics -from ._core._synchronization import Event as Event -from ._core._synchronization import EventStatistics as EventStatistics -from ._core._synchronization import Lock as Lock -from ._core._synchronization import LockStatistics as LockStatistics -from ._core._synchronization import ResourceGuard as ResourceGuard -from ._core._synchronization import Semaphore as Semaphore -from ._core._synchronization import SemaphoreStatistics as SemaphoreStatistics -from ._core._tasks import TASK_STATUS_IGNORED as TASK_STATUS_IGNORED -from ._core._tasks import CancelScope as CancelScope -from ._core._tasks import create_task_group as create_task_group -from ._core._tasks import current_effective_deadline as current_effective_deadline -from ._core._tasks import fail_after as fail_after -from ._core._tasks import move_on_after as move_on_after -from ._core._tempfile import NamedTemporaryFile as NamedTemporaryFile -from ._core._tempfile import SpooledTemporaryFile as SpooledTemporaryFile -from ._core._tempfile import TemporaryDirectory as TemporaryDirectory -from ._core._tempfile import TemporaryFile as TemporaryFile -from ._core._tempfile import gettempdir as gettempdir -from ._core._tempfile import gettempdirb as gettempdirb -from ._core._tempfile import mkdtemp as mkdtemp -from ._core._tempfile import mkstemp as mkstemp -from ._core._testing import TaskInfo as TaskInfo -from ._core._testing import get_current_task as get_current_task -from ._core._testing import get_running_tasks as get_running_tasks -from ._core._testing import wait_all_tasks_blocked as wait_all_tasks_blocked -from ._core._typedattr import TypedAttributeProvider as TypedAttributeProvider -from ._core._typedattr import TypedAttributeSet as TypedAttributeSet -from ._core._typedattr import typed_attribute as typed_attribute - -# Re-export imports so they look like they live directly in this package -for __value in list(locals().values()): - if getattr(__value, "__module__", "").startswith("anyio."): - __value.__module__ = __name__ - -del __value diff --git a/venv/lib/python3.12/site-packages/anyio/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index babd8f81d1367a5e44003481e119dd5036a34d34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3578 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≫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 B%+3G+ diff --git a/venv/lib/python3.12/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/__pycache__/to_interpreter.cpython-312.pyc deleted file mode 100644 index 163fc0accfe78c972c4f23d47c1a1769a2c420a0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9116 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 r14kd%w(Qzn;NiRKZY=Hqdckt$^6*U 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 T?M&`WfOY>(!!=$p^sfI8G(k@# diff --git a/venv/lib/python3.12/site-packages/anyio/_backends/__init__.py b/venv/lib/python3.12/site-packages/anyio/_backends/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 004a96fa213c704f7ff0db6046daf3c6d05e1aaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 185 zcmX@j%ge<81nM7Or-SInAOanHW&w&!XQ*V*Wb|9fP{ah}eFmxd6``MzpPQJXUz}Nzs#}nloSm4STCAU# zSDBfwAD;x|r{<*;>&M4u=4F<|$LkeT{^GF7%}*)KNwq6t1zN-i#Kj=SM`lJw#v*1Q F3jk&4Fs1+i diff --git a/venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/_asyncio.cpython-312.pyc deleted file mode 100644 index 4937a062b831a4a7669ae6e4414741438ab06b7f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132756 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 diff --git a/venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_backends/__pycache__/_trio.cpython-312.pyc deleted file mode 100644 index 1fc8d4d9d412464b4e6c2d51715a0e50e4a6198e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 70477 zcmeFa33yw_eJ^?rfCC(m00DygDv%UOfuu<7nAP(&A<6-RPq$aS&Ff9NeYB}mj^fw% ze*c-XVIgJ3?rr z5-$yw#$7>I+#Phs%YtQbPtX(h2EFm}U^y$_7W2g`f)&g!#VX@f!7Apr$ExEs!5Zdw z#A@Sp!8+!bWA*WdU<30zW43r>u#x#oVomYpU^DZV#-#YX;Jmm$=x6V)m?Pd2Y+-(P ztTo;iY>Uqi&X2bT+v6R}TM#4+M8Ie*^rxg1h1m1|MYa zjd*`3_%QP~#XcH;Bp77==2(CH(cq);j|D##-yPh|!sf+39uEaW@lOOl!QTC`aC}d2 zk0?avD>VKsvB7vG7{R;!!2hiQm+>2EJ@_#}PzXZWFampndqrWG^0meG@wZv>&1d_Gfr@F40#vHOfzix6E9>HMn5zaNaT_XYZUoV^F4!_h~- zYE{#WAZ&l6OHXqM?|UQN`uiuNJqLbbv`6zD_*>0q{00*iVXF}7c}|Edj0W{DJidA60L(b*M`42`8&8Ox3 zsu~bHQnZ8>C}AZ^nAY+czXc^6En31Vl&~5lTsLxRzJd}`tk!Fg;|}!laV?$kd*Gi9 zzvk0Q36A3XiO5>52ZF~U>!MFa)~-du$ezgh=WM~JSowFN{0-5L=tv!6^xRLgxPHV9 zM4yiKpArvPv@aOHU$t?6@EMkRBT{dQKEqP0F-BUHt))KBQg24;Eo#{+wk?|aIhJ}W zQs4DHQh$o2-iFk7BlV-yCRQJpxoqy&>+@?Y&ppUf6q94&mX9o-2iO^lqoqFg4Ec8KyJ`{ae4}FM*K8()~#KY`G2G^B@qF8aCP3r8)1!Jkoq0Wn(|9v&V^hLb}h!-?$yIa}7BI66GI6(~sw zCr6a5o4s#Ks;|!eBjKTBcuy>vl{bcCG3G1TI1-CR2dRv#bK{6IayU6Oj07wfOS&`q z$-~j%!6-gx-*Py4SRr3^|DHrr2@fVWjtnQGk0M0+X*l#zqc;Rm9Lk;BShlsCJ4;Bew- zZcxR>*hnIZ>0?e;x_LNq|K6QRloiJ(ss=}f(S^y-(4ogxgcA687$b*>hC!rAMnmyv zd_*}K8rgFIfE5CqAm0Ts>&a^~f+W^fcx=>00s`&JTMvhoNVZ~UG#);*e?*BI?MG^- z9*mdLjbT7%Z0Fzz0K=Ls+qQ!shk%JXKkI&Q(~cd0n`n}~RzJ9X+ebG6ME5D-xDk#| zyVz_Qprpf*Y#Ew+zcO$%8BGwl1_1K+v1Z-RTD22t^bT>}6;5m!ibaP<0+yfA%>Eg% z%E;o}5yn?`9*PbIEXrLJQA!c`mI{))4j;m7v_CiuU^s{jKAIw%A0Lb!q6xVbv++xs`LyHL5tSnq5yx{jo%}na&I6VD z*L6>%G9u@sk|R|SrzxZqB~?XAOd&27QfdluN8Lrsu8z3Osg8<)8f61My?xM3dZ{PS z<>E{aJZFR?T>czT`$&7I-%&wB@H>SI;`R%ctet~!))5K~M~{R;059ucECCdv4DA~N z-pbk!9tmRz5>%Yu@4xwA-+thczP*61#KOUFUn~}1h*=HjTiSBQ@-L*p2lh<#g@=z0jr4^G%>lj=eW9c>G}3$MsPYJkPgR%zy;rT#V~9vp zzcJZ$kp@p`l{6Cnn=|YCkHD zT1KrJ(~wtx^mO!b>gfwMR{g9TeS9#KBs}RLAE6jK3)+*Q+5n{0#!=_x4-YTuIARh_ zaGn;XU4pmrg{MwDmGN|@J)P&}i=D5pnDh)x$OChX&no1-ofaD7b2N8!?1PLFDEp~K zrhz$x_ms~(Fg)RBC>`;Wrcr55%gt}e{=(`~d2B#>;hD9%`usp5^-+i5f(k-%1Qa<2 z9;=|531rCaVlC}ey&xG9b;Sal3WiPJ+s*745-nTzlQ0o-cy0Ng+6;BA=U_tM;r#8Ev{*!w9Zv4E&@1?IW10M6{HT!pYhdCRH$k7vR~Hrzw^t zAz4p(hSJ$6A4Z>ESmFz^5`+I{J)zr2a~Qqd+GpaFpfV>;iyCH8Ibx6&#lN>_WF&?` zW8XWD#Hv3l?S-(D1i~j?K_Q%1kVg45LIY|F@*61vWkjBb!|`Y+lr0H`;v@qO@Sf3g0yOSlFjS&x9yE zK;cys9?;V+)YC51!xrgbi}bJ#J*cj2eUzBqbK0UIN^dPj9Wxd43JyiTQBAAk;LD*-pBy`sZi-i_`waKb(KXfB%^6 zirh5S=pVDaCD(E6CL*==Q1hOpvHJsf?h(X-&H`m7^p*Ds=|F?EAX)h#0VJ-vuo91>{i9!XXq8 zR+(BL2DQWageCG+(6uiiFjZ;pS}ptUASOXV@lS(kBa zC!059YQf*1bYE@kJa7A^`+_^OU?9C4Jplm&6 z8?_zKM+!AkpQJuI2V7d1@vDtf#6rr`#JssvAE2Jddo&0dwH>z{2NWH%J!v~49uXe5 zJ|Y|u+l0dUYjF$?tlPKzj9@z;b2xw`6z2Rt2afHC%Swquv7scNkxouU!M$Lra>YNBfPuYP&gD<6OHo(`d@r#MH90O0REf{|mkFlekZ+as1y%MgToQGjS~-JZH**Z!e|KM4xpXE@i7H)xyv9P8czzaKgg zmLTB=cJ=Rx`V&d0d!vzF<;(aS_z6NAS=R%Hhm%8bu5(mgrl1m*5URtGVNDRV?L9m^ z$ns@vOrt^#FyP?=-ppvkDB#Z!lehzpCVq~7X7sABdCGg=jMY+6HZ54(Wz(|YYysQn zKH<*D{ELL0RST;&YVQa990w-qyBXUK}RksnrEoQ zMiWu_3M!;_t#TfI-lG!h5aqWKkSDl*13@W|F_T!rA5l6T_ktyX*j~KfsspEXo!NbQ zccyAVx@y7s%89BC7j2iTHoU$pU9}QLg@cR8wc}-reKZmnt5GQh)bug(z{#o1c)u3uDVo469mx zlU{yrZ*TDec}{{=QyIj;qmCqUE1x6h1#+U~5G_*(Gbsd)3iWJ0=gOK%4z)2s6!SS@ z#$uIPW=d>eOkG~7h4H2MMXwWENld3w1KmAd;32}y? z*Ug&pwk<~YwY=cuP!fMMy_Ovm^)UEV4t|W$m184EV$sKv1LYCn(u3tuc}`q+83~HS6)LDq>mEP2JjvQMqu4vx>p&A ztIKK%DcBTZwX&sbiI58?3^{;LCgoI!QMK2pI6LQkXt)_R%2duzSI*B= z_N6QPE=I1n?wE3UU%3Co{rF-3eN!$U81pkvoPJ{3BRE@sF38RjHbXSDei5Z}Jn!OY zeXWjm=SJ(=iWaFpbU*7DC}C(-tS~$4v72QP2!xM9E(A^oX)uw1@1rg$FJGd5)F|^A zs^W1t0Y^SoCltZw);N4ww>n+0niyjm{_h}^p_C1L;;`0|^S2anFPwJ?y^B)Y&!Kk! zUiL~Q*UIjmmhcO7?P2J>gwXrEX(xr15aKQ+ANa_YX*c=Gpoh5OfsbQkDt-%q&l3G) zam3t(1co92wsvCF8nLWJDA2A0OL(-DC$l9x>8Lf}%vL@S9gIR!=IfOYE8#;xDXD6v z>cXONZ%#Crb@VM3Y;zaV2(3L!NYD%J=vNV)H1<^IY^+>tItI2=!QW0HsZZSFBE-)! z2u}1>_7p>=5T>e+SqylT5HbQ$b3Ti5+ZZ?xU54h zH`SOkUg~i6s<9;)oX&Vj1&s06c|a>Fn}Lo^jSqA}uFpX(AYJ|XA`=3nsgVIml9 z#NQV>v6#?_Wma@zdD8N}(22#+(v04sv_f=Z=Wr<}U2^^ zJR7VC;v8vM5vMZ{Salzcq^ga6*RTbJ&m*89#jOcd_^QwJobJi^I@3O=+a`SrGp>b~ zT?;=LS|HMNT@o$LE*#FSm{_ zm&m`yid6pwSV6f=UA!NTS)yRLpti6#IU?vpe=1if-&=6D1GoPby=2IFh8*HSiqC0f zilY8IImPC2mLkZ3#kw(%{gXETjLj~szK-P!bskfq;`5kz&{^iO75syZ@edMwcHQS- zz6vtp!7Q&N(;X}*RFJ_A77r>SFw=pxepLj9I6*n;L<+abB&P%+)sZq&NGU>UA|6wS z3n8@;uPMaMLds1cWk-F1x~yY|GBOC`z?6$&6ZH)mXe=*L_{}=vWXN307#kTo};Hxv>wI6n9(`F;i` zYa_GMtUG6gIBPpN1o}`ETa~FZrI+KVC4@l!9~8uJ{#AGFIolO?``d!u*@Kmo7oPac z6H}1$51u}lsa}w-UNBkRmGO2>c)KVP`az0}osMOy1L^9(WOaAO+dbj!o-^`>8)Z*> z?NGOaxCBlIe!V;6YD$CO^a$nM?_TrrKc0;0adX-yxSK(78o81l66v-R+fLqdwY>4% zrYq%vw*}GNN);J8J@o4bGv1c8x8;TvVNlZFkofOSrmTN2@mpx=ardSL;tO3HE!J;~ z18eQySqR^Fr#P_QKE8nbm#V~#g8fppjr{d85?^Yo*yt55tq?bs*)FZLk^c^n!qg@yA`=|kPOjohGZUq=fmQ7O{!z!cOkg{1V73@kdqHG6qs^pAVZ+GkpN~Mf*HU} zRn>7_aA&%zbFwOs@dPI1z=S8DF}R&zaNBLKN}ah41J2}Xp;hqAwwy5+8&6CeXPJ5R zvrZTh#9@JnpZrF=Lyaic8lk7#qR~!n?8TM>=B4F%Z^IS!V2kP3aUzhMt{>R z-d3cR^=Y~OExD1`l4_d8j z`}_V+QDA;Y0LB>imC^|oe}5D;V8S!6!RU$63Ay0|*MLZA(Hem5%c%k0$xc%F|0o05 zCv9g8Jd_5{;3aE?;EuJpf2LRxuMIw5O`-e3UM8}+cpyfCtR z;%JT4bP$!)AK*25#2G)_oOLJ*TYnO<{$yqAOE#=8S+mU{6>@jL3~uNC!+@qE!`p_T z%RC&1y-ER{Mfu`PE6TprijF~eejll`&hTE4lo0mwDBs3=&bo?>u1+nOyCS`M{wNJh z8OnH9Uuda&O9gH&CQAA6K_5`wL>A=-^liKes%DxrJPJA3JS!yJRO)lW4eDR;OIjyW ze6~YdHi|^|h7ZS*+E$@MT#yRI_=coZB@?u?)uvu7;$sU{PB-c@(SDSxsca0XsF)07 z(!myyRx}xE7T#Y1Uyp|IrBK9l_$9H@0=kQ=Rd&r0IWP%3E{Bb=vj$vS|r%*JYusPL)9{&d#ZZR_LAGou?dA z)lFoEGg;k{@pfGHcDxM^zw?F_X>Op*&KYuUPM6{{?mxrrM5x z_C$~{TS_xqjWojmTM0|m<<~~HhJ1#=fG?U)HFk3IJF<#=-c?AD^;!?(i?gvLiXEHO z)#o^EQ@~uwe-5Ziv*vKEKO^Eno55X zkUKQEKRS3&?WpI|a0rP7=vleS56Rvi=WJ(*;rHz@=wsdLRWNG_( z@p5T^M^0M>S65+Qp{Nha0<-2xY)lLIn$nOGKB5kHs`>jHe^* z>6nl^3hPas{49~t&%pDmimMpIk71BnVSZ-XT?SY{nfcFLut0*$Q9(6TWaGaJoEi0t zQcn(nLROk%ji;udXSmAb1?m*CFXIw$;rNzcF729Xm^ZfRf_FBziA{vL1U|)|QPG$g#b$-3M^hXIMI9B7qYsO%l+I;# zqRycT6dQ*DT!VGpZ~cwAI);tK4kvL!=_A#h`4g>72N z$QvKW{W~|)hHSpL!O<08)*x8Z%p$5n+6H9WdmM#zIOR!o6bxX|biYC4NtzIFU8Pm0 z247y5X;_+WSbC*&8C&k0aP>~P%QNogw7WUuZcn@0C*7UrTQ0l1FWUal^(_}AS~lV8 zyXvkvYkm1)sL!-)*L+oD+t@TA^g3vecC(cCR$>Y=k>|}do)@3B|&L6`bHpfEVh}RYN zh^J}D9%lJ^6D#;($in;lWO8$}gf{ilTXN)rq>v22d!A52whSi#Fx!gIKDJ-IG{iI^ z>_uIiV}PK12dNX(8o%FcgjHp3xlU-$p{r+Tj10-3_H4ryx&3N$_xbIU&36#(ZMfR7 z;C$m`!wTAbP|LA1%@XY){`y(!I+7FT!p^i}!L;$_+-fPsbo@q#>wLOu0)Nc%ltn2W zwG6`MB3IiF>kb{eFzXJ|(d!Zb`1XclR$w49AIp2Nl@+}~4{7?jEyu}anoWns8RzrP z8t1Gp^TYgV5z1i%A#1~+J;vu3n=4CDy7Cura!oGS!g{JQXNc6{{xZr+j3Ngo3WP8G zX}AAv!Rc(BwpiVZrkYwZO}*)+-b~Zdbkov{+a{aVXKL1;vb`ADlP`#(UUFVl(ynShJ-!EZg;a+s}hJ!vq-+3=V=1a%j z{cFV+#QsIr)6M-(%QwY-hy9`rzTdMV><>#2J1*Mc9e0Qb9d|nW7fR#4^8N+Vc$-Aw z3nU6zNXf?+N&TxGTK4ly*104I{n4)rzLGk;#g-u}werRRbc+mrZqcXF6A`)zt!AdY58NZ-)H}>4Zd;F zfj~eZ;>Ud=g;YBGS4rbd<^4;g@m`5ymr4|}%1Zt_ux-L|NpK*2j`D$UDMN2W+!0ZbV1+rgG6dBM}Jx zV;a9^ef(rsMy^ZCbr7Y~a_eg=zOw$+^>4{be!-B^@$QA9(t!*C5z0%Eb^!b(aw=8? zaVCM;8T>Vcjlr44f}NQPF?d{08Q-MjKY(LaCE@5gK_TZA{INp|pi25VY}i*`FDZd` zu+}LBZd8lXQqC7p%0U#NKPnj!nNgHUIM(gQxo`~AM0?gtr?Hp;dyvLedx#vcG5#n* z`55OgpgO_QX1*egiYh}}YT^ZSOmbW_<+m6twkf|QVm*j*6?1+aKOny@juwNQh@`;| z3=?(SQ;e~mOZ}wdJKbgtcuQxjwa($D24r!MSg#SP`3_WQKI0c+MV0n;pjz`8zjSiM zfm-8T^QC~0w3caorPop={vQKgKV~~79kU;EjM@_NsFbiLiF0MoaqL0O$I?$pP@_F2 z2p_}f9&;WmIaWIAOp^G?o&$c>WBNI`5)fH2T4GAoYKm69luD^gwrepF`%|`;ED^`3 z^Ccl7kCwb7{H9%N4b%?S1D#q*<9D<)A|wOa`)H|_zF62SeFmDD0@G8k_Z-xUkK2T& zY{_oDT%Ebu3jI7Q@X4;l+rAVBmTp~(Z_KL6847qApv5YGpro-lcnn&{y406 zaQKaXoj>L2@eiUBA-2DP0?O0?+A)v!K(*3J$cd0%wuBwk#l*#|6jqe*Q7%{h0qU16 zVY-?_BdD~A?;{i1$M6AVEfpYdyl>~$(7l_tXJs;=lmTUm$N)~o}a zK&_{}`Qd#q`lSQ380kmN^&ZGNnV+4`!o8G-t;aFuKy?_8kS)~&5qv1sn2%O9^WYF- z$I6dj-QBU$~w|z9g}4XGV+26c>$B7IbZB@*2Df|+EP+pKec9kX3ah6 zHTPuJ>`brOIaS;In*A%DS3MW)uUCAp@!O5*MVlx6Td;ZWj%w(7msh7N7oXaC_Th8U z^SfZP+}L(u<<;iEL~Y<&W!;TBlsnxhEM5hTv-1%#?dlo3`>gZa>M2j%%MWn|{IaL_ zV&IP-%iOsmedmtLOLknXhV{s%??3$gd!_|(hd6&~e($-p=bwCi==Ddz%T(Ph&RDHA zzG=Z)?t{6$+xx+9S8sO*Oo|F!YY8q=#DOm{pqQUCB; zu8&T8r~9S*?P%+=jP>>H(cW8rS>=6PV!fmApDJ%fpR4J z!BP=HKUnVEQYZajefgG3=}$cpqW`o~Ldc)iF@LkPrPJ}JZ4RW*p}a)p809?+TBveY zBDOjLYWQQw*TA5boEQ_e-3QbAQ46sAE}{)4xxi*{U>ZG9e88hRb=AHD`Cg~Kz@P0o zW#|-EDYrSqgL$fxAY zG;a@Rmlw3luNB8=mmRdLO$#x8M|BFU(k}axc1FAKYtXKfqxqD}EOp_Kh*X_MJ{Z-a z{mGzQ(fFa{(NvXApv=L_M!;~ur)D3+;WX<@NR%M3&%x$g zbRbk-SAfcy_<*SYfkG2FADZLwAA719>RvVJTRq`g{bP@hy)K*dEuU~Lzt%Kw%rWJw zB9pqFu>nHttuGH=@wC!%T-oWev&viE)~n?WX9r%hzg6C;hrV+3#iK7h@s_un4C;EW zyM&6`Gu@}V&kmkjIqB;jbIgJFxhU#!E@OD#4cW22IaA-AuJ6v&FHP4kovQPnbpj=} zbn*i=uKGK;XUg9>?XWd9Ph0JE^)r&Q0c5~gRSlg7oJygp{zd~zofgQka_owjUtF)g z6?UC&VAxg5{9a-|y8U>6<>nG`yr#bvKbQK%O+MSDMPB&d5Gwu3!ADfZ(7Ao zmG(DnHu5`55dCJQNd9W)rZv)=^U60Zm)=|?A;X)?B??(%Bma77v%~QNs{`q`Ljy(D zM_gjtq5Gae9a8F!H^xl#_=%5r6r9WM-N?h>hskyXM5$WixK>I6<7IxV>TW}|3Fn`A~(Tw!WSGSJupKNjG^?g zEt;@f!Wob1dYi(u#BLl_LuGL#v9@WW#8`NnO+8#+&||ue*ai|bvk(n=SGOLi#cF)R ziw&8&mFc>bua`{LZM-6Hy4ut=(Y zx;Lh~H%@kM&a`h%ds|PHo_+9!M5$bYvoa&o@rf@#mYKIWJ#X>vt;j6hoL;*5`=7ib zZ@cPgID5~ehs1*EQlVoDbc(msbW^cZgZC2mqiWD8E`+9gpv8K+seg^-8)E+|`!^l% z{XxG4G2^R5_{Y~c2b!fz*7AWm=~AVH#Fy$M3Td{IA0{4Mj!PX5q=$tbt^g2}1#mR0 zJkn)d$lq|smwTxHitEevPz*U%>O|rPnZC>-Z4+uqW>+CmO)CM(n$$JEA<};t=w{btN3>f zRKr!)b_35S41RU)lo5U9lQbw$+X;R=oFiap!o+iGAcp-Tgr;f<#GgivUl~t;hxGc- zl}@tbHm9BM9~0zcd@r#bl>kPNY3*wXVT4k`2u{KXrItUaK*YFHgm=8u+21FPSC;p8 zN#pGj(vEjY6w+rU{}O3Ha*VGmM|y>n;2I_%rbi)hw?IAq7zL73QDnM1q=lSmq6EdK z`yy04hiS5zm?nucO;|N&Yvrc%Q=B-)oGZ$6m?k1{`1@bCK(6#q`}@dQ0;kBF_USd% zr*a!j<)xH|c+cWfxe?JH=2SL#yL<`uW2g;rAkc>E`UYdQac|M(Ysj`un9{n&L0_`g zc}X-(eTpqvGuf6ML!d2L7n7prl6HxExD$Ppvyv^7Mw8f1Whp*xFcBJ4@LwtPLF)J~ z!IwAJClHh>H%3d(XuOUXM<;ZOSxl zI$d(gb}E9U?JG@7aH>|*s)?FaHyp_HwgBf^)23hi`0E z7if*!Lu=e_`^5_Q#;qj-E^*u~lHcQ`6~x-|{$6Q3AR#fWCL(01mHaE6NO?(+2Aqyd zk^}ynX`~aBpP=2hhC+728oDX}DQ2oQDt->CH1*U*U58RsgOYz%U;|*ZxKV_zV^g&! z*pYs+3%n@XnXW}}^R1^F*IB+U-eLcSZJp&?PK5rExX$ujXMc-C2Tn9f<24dejWd1BicIaOo?4ubi*r2i#Rc%L?0?K@!{4Ml4zq5eJpdP!@onS(ok4s zoxH3@2i}Ujyodh1^~A<>Ls|JxF)OIq$xAWoCywlw$xQOnBW2N?A_uXUz8bc+If}XXK&2NVltWVm*QFA@r3o@j0E)Cw`s{)aJ>i zHJO?|{Lon#huOJk>>qH!N4%owVN{{RGmV=e>7L=-x}EU18C zyVLS}&i*CE0Heb?t^)@A9S{v1f@jbMeu&3klkZbBYw}U~7zL8E3aw@b z?HH&WSo}trj>;*~hl|Qdg5HF6VY<)gKZbz7g#O$r>!=(zt=$rpm!Jy%e_C$cQyH2G( zIPZ^DW0LW$G@Vxx?{6pG-)6s90^fH^5HW5O;T^X-NxJux_qR*qehFzw(nm;_mHfR< zO1Tmufn$8F1O6Od=YLPuUwMXrWHy{$1TqMxKT4DHS<3hvIm{eUMUWdYR2p+keuFtK zjxm3O3Lxh`D)ZOqjV()2(1(g2O?=~jI7B($psfXU*D>ba_kl705A#a^_E~a@v$<_^ z^|Z?G9;A*wNo71wK#Dj0(Q(NCb{wNZ+v8@#BmTL1l@JOU9xA7(gwx~@LQ(z`Ie$$k zq$sQPB1Mx!1E8~7*sHX1rX-iuVu|!2f=3-Oab_)EOoqvMSE=Y%r>Gm1a9s-R)pcMm zFI|5qA9cXUj}EfQ(PLT>fWO;ily0aSypQaxB zU4$2EQmJ{Y1}oq(Zze1z(rT--=1rH{Ne5PL_Cig>-emT9<1W8^D|fa!mMYUK$6Zvq|7gv*Zej%Es-4rQtW>8ikFRd>eIJt22bc)D*Y)2MK9Slxq|**0g-)r@1J zVO@`-6bSw0JvfmY4WS37AC~Pn&)7{@NhCs4bL^%AufWEOZh}xRzE#NFTKUh&2B|9o zf7U}6Na9#NEk%xc;wv65OXOB*^j`qYB9Dd$BK5zbsw9Y_fjEnCGge`Ftp| z@b2`&yRUfenUL?9V-gYc|0-Q$K2V9Z&{_-}sdG|Jwer#ADXKMT0Qs3o?0U$CwA}EP z+{CK5U0ar-TCx2d%1QXNQ0lnC{h@?C_}VoAKZhymG=)B%ZwbT-CI{D?3yBtZ)Pt>O za1IRig3`5EaC+!|t$W4mvM8yyr%|3k{OJ$P6FlM!2QKaM*$A!-cv+0Nu&`yvwN?Dh zjjf>epbh6Flo5{A<}}Vp@GxBKz%MSE4a&HhmQJB`;+;;REWwqubP8qZ(NdW5t-`CQ=3m79s5abM)45Ad}8z?Ua4jGbm(e=d|j{ZElun3N( ziXetpWD`69ubjgi4BOUX>j+xsnD?`47~6)U%gv4F2%P!_rv+2h4Ezn4p}AGqjwnJ? zZnYg8jg#@Oc57)vdxW(+6=Q?RYkq#8!uOy; z%pN&gW9)DV4eiCz@^slLUA9%G<_Zmu5Uo{ukR@vi#YU1@+o7;>uuuZ}LzJB27);Ik zD#3Ib8M$ho&H`z<>}jFZ-)cH~bL8|$rg~wzdf{YsA9g2Cc>8FpLM{us7ofG_CVeFo8_R>M3eW&{}zK*o7Bjf8%`?~o_)swD;Ff*e=hv;h= zS9jXgeSYH=*P$;rb@n%EB=R>}5dKE9 zO#Tkv##PogRg^HcwyZPYDf9B%GXkK9^5Jq87F@6j)LB=t+I;X}C z^N_V1h~I4X#uy8*&f5O#qi$TB1&a^pR-z5BIYk#%%d%pg1>v*{YZ_Y^I%VzoM zgNPz*`r2c(Ke+Hv%0HpDm$J6=6n}y*D_^3%E3l5y>qKnU2W3Y&QcBl2j8b^ zaV(%F8OPVzy0nQao%O_2N$b5o`4wx*j%(9l7=@^hQf0Ez5sPw0s5w2uB3VEr^(EEf z$G>5Zt5}TwX|}?eK82%Dyh|q@cxX(z z>S>yCHDp|^X;oV+Ph&1ZJ#L^Cb|f9Ao8w zgL-8n-kuYt7B2ZYjxTJ(xsi*O|6H)(q#9YU``*F9HCwPx58i3+m3=tCa)ASmPnA?! zuiGW;l{>zMs97(Cn?B;$mmd1n5yl?8PAKH)(RRRbkJs@C|i#^4N99{E; zllaxIK)BG+3BT6shiDJDe`*#M%zhu`aQT>O!1_8{8PZ#25}DL%OaGj@L+=y5XM^fP z9rH9dpN--*<mQM`A5}=eBdF7f@!zKDq;f>p2xd+pSuPWo;jcUb_?zv>`T5q?iw4UoxSfRK7vXe?;2PyeogFOX8U>veB%{j{|ei9rH%Y` z_5G`a@ue2>ufR$B*qgCt;127hCE~zx`=zB4`Bzcwr8Oe?@36w3!;2B5W73N=kHPc5 zmMhlAm~*x`WSaAN3%80d=RX>MW8p1h_$xWfEf`NibLxCxeQAJk0e=btJ`DxGm37OxIlLKSaH>?Lg4BnbS$@d9V z^81nkad?vs8!B^s6Q5VcDMJC%k4o{1eFC0eh3UVwdfrgZ=YTm=57X)xV`-K1s9uh) zlX0$y8KZ5z^U8zw#d6LLRmGma=?6xB+dz`*cF^kw2V zOgt;GK<_W*amqbLj*W`2z|j=s)TDrWR<@O6ZicD}-}1^ZsAD6_dgV=u_yHV-xi@ff zPnBbg!=F?0iF&~93#yQo_Nk`Uw{bdg+qIhdX$il;w3W@%PV$uqH4SufaT~VGl~l~Q z$ycvsk)``YmWMoQCg$b2m>1c~e(omkOl67GJ5y_uI`tDA1H=}y6C4BjY3uEJSUV~4 zTW>&#KcHR!OidWXpZ?gmPn>xd9%Gdh_NG3rwKsTU+yP~M&Jna0jjIID>;Okx#a2%x zBbUlkS2IqTIOH1Ql{L}}4p}ay%ELWT`FwO;4j)~@N&+XXmsE;x6G!ce)U!LP+<3q?H`E@XbgY=V6$S88Ny3pE?Vhr)wH$)or3li4+P z+ltR=>^3%4&B1Qx)S8T{fK)8c$Y8E>^zWnM)0Vq&lJ?x|5QaV|H#bKlR_N06>T594 zTzyF$t4YgKG*hXEbKA|>=-Rw;bY{Ag8s3LY?8bLjbi(}eniOqNbrOm}q&!v9LXPgVybhFgTm+*-K;y{6^`oe~W zaTFkK83@%-Q|ag@&I9859k#~Xm#*rYtXiD$ES``TPk0uqYrN{zMRG1)v8EBA-EPzP zeaV{GmES;>D>v@Y1e#?{dB`XU9na^K9mfF>Zy_Qk%l!Am<%eukrN}C zvd(l_=Xv>J=j$sb%LX#?z-4*hCOiJ!{>&ism85mxzFOBh_{ zQ*sJSHRd!+6y*SeW4_^x`X8b_+kMKub?Nk1W!09l; za%l6dYu7=wD?>goZ=JBmcmeCoZx!Q=K4>qh@R0TF!BNg5N1_o8!{ztrUsI3H%kR;= zTwO&vwKwhQosfGAXY_|vb#M5w@K7wgCl;Np?tepd_vhC=KU*&e&!Sc=ddx< z*`6+IpDgRl$eowv&YSE;Qk{uGV#dU$P~-lPfenQ zbWAY5SeNlEO?xoGCOzvWip??Fg^f(&%pd%U!*FYX7i&H;3eS6tV-#jt6GEfuK`hbD zya$SD8xP_(ZZ?JJnL>m(>(r4IUmcP;U%^Dl1;}JdDzOcx$~5IA>o-tOhVN`-{gyL3 znD|}5EgC}jChGaSP`at-1GsZ%(gSmytDXf@js8sIqIBaTTnV44>q^&kU9E07yXlqf zFK)+Wp6q`^^TrPNp|+&YG_?XQC9g ztuv--hMGzFl7>NrX@Sm2P|IxwiCW<)va1cMej6)KtoVcH&aT!N|wGv>L*enNsr3)QZxQX}ew8C|>jRP}v(reAw49?Oz{II_j)!9jsWm zq^n&*7CNHPxqQkXqV)&eNsl3aCJOHe+Pu)8J-l@Hvc+m3iL z>2|;@k(n7Dl>=^A%0JY!EF%8!q^|rPG-wGLpU>*z2}fsouH5q zz+bGi*P6<~0+F!BthcBZaYDG<^q9tPIp@tdw`6xg)6htP=^cZih+8m7)!@`!CcW67`D7$`qce zEz&S1Du=0EO-RC2AFzpf{KVt@o~CoP=T~0bGU>TvLcXIA5b#Cb1~LGmHfY+YFy8Y! z7r-5Y3ce*O>)E_SJcldkUiB`)5s((;m*}8W1wUef18<_o-`m@}TccGs zkl=lh!BpuU+|Q@dSuHoAokC0SDTMNsZZ@G9=!s~rLXFP1!=MT%=h93e_J% znRvt*qP+$>2Wl39nxR|H{fFH+>|9A^Np1^D5wanNrA2NkXr!4%dC*}Fhb;!%!IKl_ zWvJho6IM>T=3vQDXTX;&*%eJBar-45SBYNHAF6jL)q4{>XFz-+mY5L7u|guu8*rSE znh^L;Z6U}~E-oeGZynKa3k6Dwy%N$#4o441ab%|SN%AOkJYTjH=0awcdZ`ZePXMpY_|M(G6Q2#q&MR8I^4O`iAHtJeLI zgG|0_r|!6u-}PsvGJ3s{o{GnxIP)evvmr=j*DOnvlsoUy`i`0I=Ec$LGYi=PJmxy6 zsfrySt(B(z&RQxik|85>jZE8=QgplGr}IiMn)oGgS8!>duR7yvOZ(a;e0@{ij#IXb*Pr(KGv4`W@BB$` z#})4apcK$CmT1z~N4LuHogq0ODdSVm(m*UjojJly>L6?Ea;IJG06jg1Ebo>J=oZ|T zxis&jBDMqGatzaO)S?Uf>M2IYY&dIMC+_M9;KyXIr=Q)eA!?lAy#%OwA^uum(Lpt4 z53D!lACqP&uT)Dls^70+l*cZGlAe@KejL_+_%)75SyA+)>N!tEilI{=sVu_>`RLRA z(~6&7*@k+W9*B?NCtIfO3)Lo}ZE!>x$(D^AP7aP>2f_Z481DPd+Ht2h)~5NE1ERi| zh1xl`ABvMbcc*2x zPowVa`YCtA+c*?|^;GZL8-m@vdYYVcb=RrL+3nL7seCn#@p>hAY73BdRa>Sqkgg1T zt^K0?s|(+%Ts7@R+IO!tb!r#?teC27)zetN+LftXo~~TZF8^6^^KFOFx9)}&-?~8` zWM6$RK|VaDEtaZR;eaSW;+FrrIUGh0Ad|$F5?7Y-pZi5B3M}`G^aa{sAC18`gaK`MDS4idw-5#Z(=8X_E!jDeoy}3X7CQ)EyD=Wjc<`n^yo{ zUlTtk&W2T=?qRsP*q6yvFz?ZDwDvn|sle5^T!1e0$}53h50FAF??EkK9XKS6TB)|9 zw!Nk!)Nox5&fuD*f8Jj$ZMb@%brfe_*WtT!Z6krI2%DTN*;<;_Bv<03XlUM&`)OxW zBD^=6bw@^qqm0(?2@f7*ceB9cmeHa;D4cKq@IdRM(1Fsx9qcmlD!`UXrVbrWDs)h% z;v&ZbCtJ$61->IBYd<_pay3jK36Ck%*KA{y@-gyNAboj21|!6# zLu#IR7BJoP%o=IK{(_*`}jXUlD`nE5KXGHbt#$TZXHnoc9vl;c!dY92fIwxs{GC zJ1S_lbnKoX>-N-qrb+SdqqE;hm*Q6mog1!V015QA#IH5>_X^{32fR4+rhg4iy|j>jHBQF1j<2!8UjUtG z13$?B42dm8(dnqTSJdED)f>PrhK5Ho+l>=19uXkTh&2HRhzJdDg67?iL`zN zBvB%G17pdIhb#)uH>N!sUay8TA#dQ+6DjqFCKjuD7d-E;>iVLi5-_TsbtVae>JXFL z0GTRE2~uYEUJLxcsOp68QFXiEY#p;@pV`qIZ`P9*hzZpu2-}H0sBxs4+MwyN1fnQ+&$|tJCr{uG+#P_MRJB5++7{SM1B0p`V zmn8pm8E#HwS`+-LS`+d?Yl8b#$j9~Z@Xb^^rPVXIWD%66O6s~+);lfXm&i`_w1a#g zg$>hA@*$INrj&fWUTG^<2L`4k@*r{fylDsX%0fxwjFWliOKb@NiO8cSVqPTj%{ZC2 z4Ckp#)oqxz((m0LWxv;)?&}iX8BntZ4x(-PgT~TxySIWUZ-NHpaPA}|p)hf#88Ngm zgm!gd1&$S;>nO{MhZm!r$~!4iV+);@!k%Ibwy}5%xn1Airb#g+*)nYGh2}dnd|1KGzN6Vv^_`@atYrv0 zu~0PE0DhT#K0s&IaU>c(s6_W>r9;Zd<43a+bY;?C66{k!??MKutQ~Vsm3lIz&6i7?&*9kU73sDWnYMw;Z39

(Al>_TF?u zZ>C{Qx?#;^?Hyy=ej>Zs2AP+AXE(i6du}yU_d^$kUa$OK-M8zm$Q!R#HJ;ghdiS|y zlT{0_@KM6a1E58JZ16D{+5^uV`v=eu`A@M$ke#%@Rv&-pDmZ^5YW$5-iI1b_mQ%l$ zfmx=_*zDkv!-;HFbnjleJ?61!?5G;W_Gv#5-5bTI4My1=h6PIa+Wp}~i0-7qX(?JZ z9E375oNCYM@!697h(=&BS_kT6k(_l?V4c^TUc=WyG8F^qih&8&0QMde45QftMElH)w*2p5# z9P1$xLKf38`+A5SAxlV`tcN%dvNY#p5}AcSi>#+{vJkTca|uG0#*hw(Dh=p`^uRyR3(J5VC@-nDr1ZLROMJvmR28kX2;atcUmzf?bD^ za`U%XFRhOFOy8?Ox;2psQ_f1>yOBH0`f=`$tc_GYC+Xj)Lf)m3DpTI-!jXxri&UFZ z)D%gvK2l>!QHxUVjMSP!>I(B{b&G6>)R|J&BX57C-W1Y6c_RZ_dbJ%JBMqi@G$Plg zNTVrN6GApenoJ?hETq{KGOu{8B3mN!OsV{UgBJ7GBU>YWBVO;z)`E0*MOuod%PDPJ zq}50jL@ALr_22xLZRV7@{>a^tb`un|v0l2zNE5j?(qZbM`6&0kNT=yb?JQ)0DWn4- z+am!}NT<<5k^3WErkDjtyCc$V3JDIkQ&q{}4IJt~y_LLTrAX zY^iJ@%;_;zsu%gM5#A$t0NX*mbhZW7anIT&JoC>cFW+jr(t2Kfxcn)`>=aYWYtW@F zM61WVkmEF;Ft#E&g3e6UncI*P^>@@7Zp8KzSbQBjaV+EMOMChz znSFX8bw-bvg*Ri3qF7V%tF4ZLORoWr>&dUWvWYsqwrGWs{GX`4VBpaEs4rhXpY*g& z$gPESC9VR=#hF%ka&~)AEAk$#Yk3`&R}r0GwQQY!R7)uOINhlOk{%k2g%b%**j3Q& zoi!O0Py(}pXSJtI))VS6VL6LINW~X}NDfmMgY@ba>*%>)Mqm2T4*+6Uewwxbn4xJ4 zk@q}kVi#ya31CdlUgHFtf2Jmp5`bw^eo}au@MU?y%^6~#kGJ-SuZdl@FWY-^O*#J! zoBMjP=2Bp)t$1^D4(z#EyzRyTI+x|;Hpo)OPZ z#1`Aj_BIh`Jtzr$L?N}JKHk(?oqEwUF;g#g=z)G)FSA5d*eU9FBB8p`%qTNgzg01a zRfi-kHgJJu5cXJ5dz$BHVFEj~iet~~vfynvch|*-u6Wi?$ZHF+C)FI|BhGZ?)w&!P#L-@2mrK57otsM?O| zymsW*SyX-7*q#&#FCFXi>aiVa67}Fcq%`8WUMTAm}#of6lB9pB2F%F<{bp8d>!eP)l{F0 z@R?^(wp6VUor;vIDbhU@QA^b!iIGvibB$MwjX>KKI^aXsB~kC_YU1XCisc?H!siX; zSJqMG{tHzOpAw8kFt1v@gtnDC)mWsCdTb+Alok&;i&w`F`?%tHctU=d_aIeJd-NV8 zrZBe$HPw=4vbP*5R9wVNs&o3VMy+JNC2bxl(q?t8xornkS?k;8v!ncyK3-WfCrwrx z&(f?u56`E?Pg_21=L|-~I%XLY$LxD?RL*lQ+>VZT{>-(3@-udmCJiw~>C} z2Hec>#0@L_Hz)urN$xg&%EW(?TCA^1T@I{GmxuSj8U<`Aai)wkWF0ZS`51ur4Aov; z7N7_&;Cos=8aHE*IS(}>6AkUhti#lK% zs&bRj-5XwuvkjE0yfNbqq`iSjZ#Rz6s=^Uk6;sW9S1WOCa;9!!x^Ch5Ba@XYuRCnj zCAe&ec0kyibLj%#PL$G-)kFpN$?jZ5gYJjKoea46eD$W@!I-26(D5~ zicr1_C+lHMmZk{Av2ywRbrhYMYA}OLUXFFtEtMz>n3ER3YtwRVMqZGX7rZ5R@kx#p z`a^z9Dsg529`o!d+8%RGwTRIoBDASROfbH{51ul~(F`W2Gz0Ng(MYq^*$}&7o5Ovo z#oX4SN%~Pv!jH1}fmD?l&%Cr}UdGdw_OzYbG~rove%WOc!8f;o{Qs)0XY*wrO#u3o z(b!5Itj%rp=eL!i0#k~+QA)9dPSpMS6vc?0PwwwgpI%qj2>vgcrRfkbWF-tBS zsYv`gdy1#fzQ>MKbRvyUOK<$56y46Mc#51-N|1)Q=e#Gclp-l|N-0g!f;)Rg9iz_C zlF?Fa5si`h?+(KLn)>I6029;W%<#m%JqJM$KEa$mOf!&p6YvTRO|PtearL=fFWotI z?^RFT*`BXiuXuW$(%k2+R!3uTe!&UzvW5kh1ph1<%J&V6LQO zuJOavmu`HHu^ls&l5;W6L3CB0+V`6EwFkd;*TlT#S4vl0ZS=o#-;4KU8dsznSNz!9 zc=q8*Z~L^>(NuP=x?!rOiT+pDJERib-2h}iO$V4Pe5QGV)k5o*P zU?;RO9VT&SI#cX~hED(4^*Y^Uv0^cV|Ju%4UP^J&nf`wFd+fto18M*4jCo%{Ii zJ@;<)lIxJu8_PkZxEGlLD9<2I_4#&|suzmXoj!>5t|8o6xU!vV!IgV z+lrT87CGRW696h%VULxQ@m>Ib$kHm^ThRkihy10NS+Q{>N(L4AsZRR3d&D7y7RbfPfBpLEXoJz-1J z?vWfnzCMEQ<^HfQ)3K1~x97X!G~=7(ape3meDlamjGB8rNHAJOIlf@ZPNWk`-@%ljAvTVpJtWFUs?}APCDx_)f7WQz?>u@A>c>u?D+(d4UQ45 zX&dqbx_smfb+hT z^<;;qAAB^2DWiRl9?!DDo<~eM@bLIy`2%l00R1=^jz9L| zu~?`n5^6dViiS4Kx#P}2%vlw2R{i;7vFi3nb^BXAvCdtQ&RuVR?Xq*=J$G5$zbfWm z6Y;NE*cSD-$2{#}PkYj4gMoK?)JOdF3y|Jj7?1ipW1h~ir!xg1!j-4*((ETBixqFj ze?rE|+x6*{!j-yZ_|lk%>Nl4?)vyb%n}y$s%%AEnxV>Dx=vMnT+Aex*go{J{Ta=59 zYJacoVv~(U4}+=V zla_pHPwBNro|a4|kNlsLQ;QE0YmvPJ5h&{?Lw=xpU0d)xg2lse@)xwMomB(dk`-`)|K%c;}vb`|cKUwz?A)l<*AhAHH|jeS^CW z?7w$NoI-qUP?%%enT4ZIRx)Y93)-k;cYG2jRK{H85@Rz{W0J*?f4(wKT4qKcg=P(; zK&JDaw4}YyvaP*>^2)&j(iqU~Hm9j`j=#S@wryWz+rDt9DH_^8=l;N568B&Rq3!)2 zK!~v`Qrq>`L$RKLNYB8#?Uy}we~^FD`oLYDp0XyQ{_dEkJM8Jc5~yD|77cWSJsrOd ztUP@v8fXrCnv<~3tj$|JH>72}Q+*rzJ1NNDzutCXa|PgwxT>VxcCnbTtR6)<8g&`CkJS$VsTa*e8o{#ja#QP2jc8A!ph7JI;vkZZIHGxb7gyrfd4=u zlhI==5Z2UxdL20Bl*RUiGcNuNrOV2s_zPfWKW}E<$<55Vwok?PkwO*)IZ8_k{*6h& zjD;!boAb-Z(@l@)Q1r2&k6QDM9k=S)X&zE~NsB&8TFPH07X7ortYh@0BM2c^lHwuu zFgXFgO6XKDAkO6yOo6wJTc1pLM5`p=~6KE&60lGE%-U6D}Nxi3dUJJ@|f z>27c=>hFko*!Hgk+Rpq*G_WP?+49?Tk4Uaiyq!1XMUtm_`byOEYG1(ica?wy>5md{ z3=%KHkwVPSC>la(%xYv=I2g-ncxA7@Gt!Ka@~y~} zM)?K>OQ1t99*UK;L`quD44vybA9_3Z_RPCu(UPH9;ZWE)6fPXnr4O3g)gP}6k`80sq@2p)G-qHS5l|mq>eM2 zItS0qL`$~Cq-nBn;WnKrb*<`;)OEJk?XB5sHEK57zESYRWs z+ArT~16#*tC>xlK(AX~KA2;$b8I7$0uXv*B#FLg28NBg)9B+IRY^(H`l2+_v8d;lE z%RbS{!NVbHQ3h>oj5xE@bI*uv4jf=(=RZ;vH@ZA2`6ElJo1R951& zkP1sM3p6rHt)*qwqPfUV+Uy0}ulTDMtWkem%u{#CQ-?)6WcjF#N&UDX^@_hf>Tits zdm{dxb5pU6cSJVc5%mweJ0126{!WJFb*~JIglZS|VGDUa81`(VR^9gBUuTX_;o2|t zSzm?nl3Hf_uB}3Og^1H?h4QC?zAo!u*U6itY5`v8!d3JC-&B;ZTfd~7P~{>KO{Gn1 zDs>=bx~YgW9Ocf^A&te40cFqT446Fx8Y(?VTUH~K zCMR|2gG7}foi#f4(8$dAw2n6{xXH_A4elvV{xi3S;!PlC*JiCDb#blyso6mJsUc(o zIxV&p1(jC@%BG-Nw)j)7Zwd1rM5;X6t^D?rG(ZVk zlhMM}Vdv_b524u&WC3{AlfM8b)u|lw^yz|p6?T`PVrOTPCD}CC>`thUYqj#oi@al zxm2GYI%zSg#35GWy*g4O>b zN`UGQ)<=Vla|Q1emf@EV%&IC1! z5x)*@zh*~hsH}Q#gKlhj!`#4fp;B0eGq0kGuwjWMxAQ#1ZoL`#)mFNuH7`|K^HPm& zWUlH=&P!Sj9(FynZHbx)$(0MObxB$cORIQEL1{ z(*8R*(-wb>P`EdZI?YCIrKStsu>{vxwSIl~FV*SUQox9;${N`M)dzL;p~Hu7q0}xeBH;`jbg6;=3*w%p za{vy?BH@EXJeNkmJ|CD`hx%c9Vwa(zaoEtdzZ-=X-(n0I_Y|W!H2G?YeUe_^H2h}^ zM~*xQ+qe|39;9@&{>@o0@k8jJdngQSU<-(qx5A5e&_Xd4fA$SIT2khnJlGUV`?cvT za@uaT?A~V(wBeQnH5KhODMd*|DYhre#2I|HLMxLdJE~twl4YGh5?3=pAbv@Dy+L}& zq$u8%VXPoCQeRB>s{4LI2mGuMkI$y;kub0y=9GJP@8O!kO+N z=IMYYYH>K-HZ)#`iK8Jsst1`Z5jU)zU$?M+r5#t`lI!Y{Q!2(5%#2YSKxx z)F9Co=B=eh3o1b%*|f7Ude|&K8C#a{@ZrN4@sUrCZa-pG^sx$aGFF(8B))VQt&iNE z*}^+Urgk44ADfuOXOU>SKNw@K9F%O*9I7vmI-Lwx{W$7~v7gGnonuDqz1xyl*+9mr&JYmU7Stg5Jmr{7(>gJtfg zvy;wl>99tmw%1*Jb@SCjheAK%0CD%y8KQGPor83~OoxUP1&;y67@dddP?A=R)1hFI zc!JIxo#*My(|L)`t8{4fSMp;8S%HEaFO3INM-T3#1a}qUEkg22X|5>5FX)Ug2>E!L z7?YIRrgIfb?y0}TG>ofu?L|q;3VZ#M?>1goR*ysTLRbtZ1kvegUR_p?<&?jMSC`fE z>N5W_t}c^Tixtb5SYSDdX(+toIt+yaC(V%SxLOm(%Y3zPRVJ>=#L4T+WL$ZDnM|+8 z4A*0Z>osw`Ca%WB)kxgZnugb#UTZqveGO(zw#6%|X~tw*ybDrNcrF!`EyJA2Ha!v` z6i>@oyO~hCnRum%t2A+?Ca%=PNsH*R0Ma6QF%mUzgFC2Q?Y6>x(74)7g2sh#z=Eu$ zBTFqTLr4a>9xu-2K3Gs{CuX{;YB()PR9j?E^H1<0xLbb6?V0Xm5@q3HhvAtvx&T$mdc)$+8{( zdUAl0Yh+?h%|brP4hWX}wX!stG;Ng0vwTe^u1VsOmH=%0piFi=fhlWEt{~)8%3ZDhKxI;RSER-O0^{>eQP59hWS2uh1_IN4eDfw(`mruQ?Z`Z@a2lQm^IB+k4HdF!9TOUnU8@R1H z&S^J#KOkANxX0Dr6fcFPZ#PFs9a{99DesiY${jyN?Yisa5ZLnT5SA=)d^hRqtySXvch zR@14WvzpEtI<<5-pC;TgnzlX`^+Y#F?tzdpJ#po%GoyeX#Ds_GPN=IOILV<6<|F z1;euK!s4#j!*|bPV`7Tt63ERGcM?^swGznOg8fCmDX|xLaW_4Erhx^iaw~W?E%wvl zzEhJ!zlYGhbO!1C3{Jvv@65#gBSKT?z`dKdVF$pW_)bBxQ5XH(Uqy=7(8&yp{l=8)_kaV z-dEi3D+TW>-uD&P`+W6%VkuB9pD1vy)A=~4s11us>!PxHQCYR9lq@Qxi%P{+rDaj6 z&Ix-xq^M=@E5WNub3|$W#A0U}a6a}ZYWJd2`-yD@lZNwgk)n2H2k2Z>HhpZdz|Wzm zn--PsPb^lvI2Cn=x~TMCRrW-bJy(_9MWyotYtf>ucFF39SpyMkVE)7ses(tFb^%d`n z-jqT(^_W_wy5vecpuDe_)P2EZrg8ipwBc*Fo3gFcC zDz!5ls9hM0)puX2?@lRrPxYfR)UNrH#P(jQ?@b|9wJWvT;#Hf&Wld*lV{5lwTDvu+ z;5}92QCq|1&1X7e>$Y85w=IRjw5F;8D)dQe7OEme8_w1Ky!CHeQwmV27C-O^+!iVC zJ>MDIa?hnL_oNgcQ)?LmKDCkZwsY3lhTWGo?AGH1)eUi5aDFgiD<@$$U#i@kvI3df zHC*4Z2G9g23`7gox{ zmFuI*eV-JSsnyp|m({5q>X52#oDaNG^-@(zA)K196sqO(NF9$<-H=_apKpN|p2-O; La#lXAUDEU4Xg91i diff --git a/venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py b/venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py deleted file mode 100644 index ed91f40..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py +++ /dev/null @@ -1,2816 +0,0 @@ -from __future__ import annotations - -import array -import asyncio -import concurrent.futures -import contextvars -import math -import os -import socket -import sys -import threading -import weakref -from asyncio import ( - AbstractEventLoop, - CancelledError, - all_tasks, - create_task, - current_task, - get_running_loop, - sleep, -) -from asyncio.base_events import _run_until_complete_cb # type: ignore[attr-defined] -from collections import OrderedDict, deque -from collections.abc import ( - AsyncGenerator, - AsyncIterator, - Awaitable, - Callable, - Collection, - Coroutine, - Iterable, - Sequence, -) -from concurrent.futures import Future -from contextlib import AbstractContextManager, suppress -from contextvars import Context, copy_context -from dataclasses import dataclass -from functools import partial, wraps -from inspect import ( - CORO_RUNNING, - CORO_SUSPENDED, - getcoroutinestate, - iscoroutine, -) -from io import IOBase -from os import PathLike -from queue import Queue -from signal import Signals -from socket import AddressFamily, SocketKind -from threading import Thread -from types import CodeType, TracebackType -from typing import ( - IO, - TYPE_CHECKING, - Any, - Optional, - TypeVar, - cast, -) -from weakref import WeakKeyDictionary - -import sniffio - -from .. import ( - CapacityLimiterStatistics, - EventStatistics, - LockStatistics, - TaskInfo, - abc, -) -from .._core._eventloop import claim_worker_thread, threadlocals -from .._core._exceptions import ( - BrokenResourceError, - BusyResourceError, - ClosedResourceError, - EndOfStream, - WouldBlock, - iterate_exceptions, -) -from .._core._sockets import convert_ipv6_sockaddr -from .._core._streams import create_memory_object_stream -from .._core._synchronization import ( - CapacityLimiter as BaseCapacityLimiter, -) -from .._core._synchronization import Event as BaseEvent -from .._core._synchronization import Lock as BaseLock -from .._core._synchronization import ( - ResourceGuard, - SemaphoreStatistics, -) -from .._core._synchronization import Semaphore as BaseSemaphore -from .._core._tasks import CancelScope as BaseCancelScope -from ..abc import ( - AsyncBackend, - IPSockAddrType, - SocketListener, - UDPPacketType, - UNIXDatagramPacketType, -) -from ..abc._eventloop import StrOrBytesPath -from ..lowlevel import RunVar -from ..streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike -else: - FileDescriptorLike = object - -if sys.version_info >= (3, 10): - from typing import ParamSpec -else: - from typing_extensions import ParamSpec - -if sys.version_info >= (3, 11): - from asyncio import Runner - from typing import TypeVarTuple, Unpack -else: - import contextvars - import enum - import signal - from asyncio import coroutines, events, exceptions, tasks - - from exceptiongroup import BaseExceptionGroup - from typing_extensions import TypeVarTuple, Unpack - - class _State(enum.Enum): - CREATED = "created" - INITIALIZED = "initialized" - CLOSED = "closed" - - class Runner: - # Copied from CPython 3.11 - def __init__( - self, - *, - debug: bool | None = None, - loop_factory: Callable[[], AbstractEventLoop] | None = None, - ): - self._state = _State.CREATED - self._debug = debug - self._loop_factory = loop_factory - self._loop: AbstractEventLoop | None = None - self._context = None - self._interrupt_count = 0 - self._set_event_loop = False - - def __enter__(self) -> Runner: - self._lazy_init() - return self - - def __exit__( - self, - exc_type: type[BaseException], - exc_val: BaseException, - exc_tb: TracebackType, - ) -> None: - self.close() - - def close(self) -> None: - """Shutdown and close event loop.""" - if self._state is not _State.INITIALIZED: - return - try: - loop = self._loop - _cancel_all_tasks(loop) - loop.run_until_complete(loop.shutdown_asyncgens()) - if hasattr(loop, "shutdown_default_executor"): - loop.run_until_complete(loop.shutdown_default_executor()) - else: - loop.run_until_complete(_shutdown_default_executor(loop)) - finally: - if self._set_event_loop: - events.set_event_loop(None) - loop.close() - self._loop = None - self._state = _State.CLOSED - - def get_loop(self) -> AbstractEventLoop: - """Return embedded event loop.""" - self._lazy_init() - return self._loop - - def run(self, coro: Coroutine[T_Retval], *, context=None) -> T_Retval: - """Run a coroutine inside the embedded event loop.""" - if not coroutines.iscoroutine(coro): - raise ValueError(f"a coroutine was expected, got {coro!r}") - - if events._get_running_loop() is not None: - # fail fast with short traceback - raise RuntimeError( - "Runner.run() cannot be called from a running event loop" - ) - - self._lazy_init() - - if context is None: - context = self._context - task = context.run(self._loop.create_task, coro) - - if ( - threading.current_thread() is threading.main_thread() - and signal.getsignal(signal.SIGINT) is signal.default_int_handler - ): - sigint_handler = partial(self._on_sigint, main_task=task) - try: - signal.signal(signal.SIGINT, sigint_handler) - except ValueError: - # `signal.signal` may throw if `threading.main_thread` does - # not support signals (e.g. embedded interpreter with signals - # not registered - see gh-91880) - sigint_handler = None - else: - sigint_handler = None - - self._interrupt_count = 0 - try: - return self._loop.run_until_complete(task) - except exceptions.CancelledError: - if self._interrupt_count > 0: - uncancel = getattr(task, "uncancel", None) - if uncancel is not None and uncancel() == 0: - raise KeyboardInterrupt() - raise # CancelledError - finally: - if ( - sigint_handler is not None - and signal.getsignal(signal.SIGINT) is sigint_handler - ): - signal.signal(signal.SIGINT, signal.default_int_handler) - - def _lazy_init(self) -> None: - if self._state is _State.CLOSED: - raise RuntimeError("Runner is closed") - if self._state is _State.INITIALIZED: - return - if self._loop_factory is None: - self._loop = events.new_event_loop() - if not self._set_event_loop: - # Call set_event_loop only once to avoid calling - # attach_loop multiple times on child watchers - events.set_event_loop(self._loop) - self._set_event_loop = True - else: - self._loop = self._loop_factory() - if self._debug is not None: - self._loop.set_debug(self._debug) - self._context = contextvars.copy_context() - self._state = _State.INITIALIZED - - def _on_sigint(self, signum, frame, main_task: asyncio.Task) -> None: - self._interrupt_count += 1 - if self._interrupt_count == 1 and not main_task.done(): - main_task.cancel() - # wakeup loop if it is blocked by select() with long timeout - self._loop.call_soon_threadsafe(lambda: None) - return - raise KeyboardInterrupt() - - def _cancel_all_tasks(loop: AbstractEventLoop) -> None: - to_cancel = tasks.all_tasks(loop) - if not to_cancel: - return - - for task in to_cancel: - task.cancel() - - loop.run_until_complete(tasks.gather(*to_cancel, return_exceptions=True)) - - for task in to_cancel: - if task.cancelled(): - continue - if task.exception() is not None: - loop.call_exception_handler( - { - "message": "unhandled exception during asyncio.run() shutdown", - "exception": task.exception(), - "task": task, - } - ) - - async def _shutdown_default_executor(loop: AbstractEventLoop) -> None: - """Schedule the shutdown of the default executor.""" - - def _do_shutdown(future: asyncio.futures.Future) -> None: - try: - loop._default_executor.shutdown(wait=True) # type: ignore[attr-defined] - loop.call_soon_threadsafe(future.set_result, None) - except Exception as ex: - loop.call_soon_threadsafe(future.set_exception, ex) - - loop._executor_shutdown_called = True - if loop._default_executor is None: - return - future = loop.create_future() - thread = threading.Thread(target=_do_shutdown, args=(future,)) - thread.start() - try: - await future - finally: - thread.join() - - -T_Retval = TypeVar("T_Retval") -T_contra = TypeVar("T_contra", contravariant=True) -PosArgsT = TypeVarTuple("PosArgsT") -P = ParamSpec("P") - -_root_task: RunVar[asyncio.Task | None] = RunVar("_root_task") - - -def find_root_task() -> asyncio.Task: - root_task = _root_task.get(None) - if root_task is not None and not root_task.done(): - return root_task - - # Look for a task that has been started via run_until_complete() - for task in all_tasks(): - if task._callbacks and not task.done(): - callbacks = [cb for cb, context in task._callbacks] - for cb in callbacks: - if ( - cb is _run_until_complete_cb - or getattr(cb, "__module__", None) == "uvloop.loop" - ): - _root_task.set(task) - return task - - # Look up the topmost task in the AnyIO task tree, if possible - task = cast(asyncio.Task, current_task()) - state = _task_states.get(task) - if state: - cancel_scope = state.cancel_scope - while cancel_scope and cancel_scope._parent_scope is not None: - cancel_scope = cancel_scope._parent_scope - - if cancel_scope is not None: - return cast(asyncio.Task, cancel_scope._host_task) - - return task - - -def get_callable_name(func: Callable) -> str: - module = getattr(func, "__module__", None) - qualname = getattr(func, "__qualname__", None) - return ".".join([x for x in (module, qualname) if x]) - - -# -# Event loop -# - -_run_vars: WeakKeyDictionary[asyncio.AbstractEventLoop, Any] = WeakKeyDictionary() - - -def _task_started(task: asyncio.Task) -> bool: - """Return ``True`` if the task has been started and has not finished.""" - # The task coro should never be None here, as we never add finished tasks to the - # task list - coro = task.get_coro() - assert coro is not None - try: - return getcoroutinestate(coro) in (CORO_RUNNING, CORO_SUSPENDED) - except AttributeError: - # task coro is async_genenerator_asend https://bugs.python.org/issue37771 - raise Exception(f"Cannot determine if task {task} has started or not") from None - - -# -# Timeouts and cancellation -# - - -def is_anyio_cancellation(exc: CancelledError) -> bool: - # Sometimes third party frameworks catch a CancelledError and raise a new one, so as - # a workaround we have to look at the previous ones in __context__ too for a - # matching cancel message - while True: - if ( - exc.args - and isinstance(exc.args[0], str) - and exc.args[0].startswith("Cancelled by cancel scope ") - ): - return True - - if isinstance(exc.__context__, CancelledError): - exc = exc.__context__ - continue - - return False - - -class CancelScope(BaseCancelScope): - def __new__( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - return object.__new__(cls) - - def __init__(self, deadline: float = math.inf, shield: bool = False): - self._deadline = deadline - self._shield = shield - self._parent_scope: CancelScope | None = None - self._child_scopes: set[CancelScope] = set() - self._cancel_called = False - self._cancelled_caught = False - self._active = False - self._timeout_handle: asyncio.TimerHandle | None = None - self._cancel_handle: asyncio.Handle | None = None - self._tasks: set[asyncio.Task] = set() - self._host_task: asyncio.Task | None = None - if sys.version_info >= (3, 11): - self._pending_uncancellations: int | None = 0 - else: - self._pending_uncancellations = None - - def __enter__(self) -> CancelScope: - if self._active: - raise RuntimeError( - "Each CancelScope may only be used for a single 'with' block" - ) - - self._host_task = host_task = cast(asyncio.Task, current_task()) - self._tasks.add(host_task) - try: - task_state = _task_states[host_task] - except KeyError: - task_state = TaskState(None, self) - _task_states[host_task] = task_state - else: - self._parent_scope = task_state.cancel_scope - task_state.cancel_scope = self - if self._parent_scope is not None: - # If using an eager task factory, the parent scope may not even contain - # the host task - self._parent_scope._child_scopes.add(self) - self._parent_scope._tasks.discard(host_task) - - self._timeout() - self._active = True - - # Start cancelling the host task if the scope was cancelled before entering - if self._cancel_called: - self._deliver_cancellation(self) - - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - del exc_tb - - if not self._active: - raise RuntimeError("This cancel scope is not active") - if current_task() is not self._host_task: - raise RuntimeError( - "Attempted to exit cancel scope in a different task than it was " - "entered in" - ) - - assert self._host_task is not None - host_task_state = _task_states.get(self._host_task) - if host_task_state is None or host_task_state.cancel_scope is not self: - raise RuntimeError( - "Attempted to exit a cancel scope that isn't the current tasks's " - "current cancel scope" - ) - - try: - self._active = False - if self._timeout_handle: - self._timeout_handle.cancel() - self._timeout_handle = None - - self._tasks.remove(self._host_task) - if self._parent_scope is not None: - self._parent_scope._child_scopes.remove(self) - self._parent_scope._tasks.add(self._host_task) - - host_task_state.cancel_scope = self._parent_scope - - # Restart the cancellation effort in the closest visible, cancelled parent - # scope if necessary - self._restart_cancellation_in_parent() - - # We only swallow the exception iff it was an AnyIO CancelledError, either - # directly as exc_val or inside an exception group and there are no cancelled - # parent cancel scopes visible to us here - if self._cancel_called and not self._parent_cancellation_is_visible_to_us: - # For each level-cancel() call made on the host task, call uncancel() - while self._pending_uncancellations: - self._host_task.uncancel() - self._pending_uncancellations -= 1 - - # Update cancelled_caught and check for exceptions we must not swallow - cannot_swallow_exc_val = False - if exc_val is not None: - for exc in iterate_exceptions(exc_val): - if isinstance(exc, CancelledError) and is_anyio_cancellation( - exc - ): - self._cancelled_caught = True - else: - cannot_swallow_exc_val = True - - return self._cancelled_caught and not cannot_swallow_exc_val - else: - if self._pending_uncancellations: - assert self._parent_scope is not None - assert self._parent_scope._pending_uncancellations is not None - self._parent_scope._pending_uncancellations += ( - self._pending_uncancellations - ) - self._pending_uncancellations = 0 - - return False - finally: - self._host_task = None - del exc_val - - @property - def _effectively_cancelled(self) -> bool: - cancel_scope: CancelScope | None = self - while cancel_scope is not None: - if cancel_scope._cancel_called: - return True - - if cancel_scope.shield: - return False - - cancel_scope = cancel_scope._parent_scope - - return False - - @property - def _parent_cancellation_is_visible_to_us(self) -> bool: - return ( - self._parent_scope is not None - and not self.shield - and self._parent_scope._effectively_cancelled - ) - - def _timeout(self) -> None: - if self._deadline != math.inf: - loop = get_running_loop() - if loop.time() >= self._deadline: - self.cancel() - else: - self._timeout_handle = loop.call_at(self._deadline, self._timeout) - - def _deliver_cancellation(self, origin: CancelScope) -> bool: - """ - Deliver cancellation to directly contained tasks and nested cancel scopes. - - Schedule another run at the end if we still have tasks eligible for - cancellation. - - :param origin: the cancel scope that originated the cancellation - :return: ``True`` if the delivery needs to be retried on the next cycle - - """ - should_retry = False - current = current_task() - for task in self._tasks: - should_retry = True - if task._must_cancel: # type: ignore[attr-defined] - continue - - # The task is eligible for cancellation if it has started - if task is not current and (task is self._host_task or _task_started(task)): - waiter = task._fut_waiter # type: ignore[attr-defined] - if not isinstance(waiter, asyncio.Future) or not waiter.done(): - task.cancel(f"Cancelled by cancel scope {id(origin):x}") - if ( - task is origin._host_task - and origin._pending_uncancellations is not None - ): - origin._pending_uncancellations += 1 - - # Deliver cancellation to child scopes that aren't shielded or running their own - # cancellation callbacks - for scope in self._child_scopes: - if not scope._shield and not scope.cancel_called: - should_retry = scope._deliver_cancellation(origin) or should_retry - - # Schedule another callback if there are still tasks left - if origin is self: - if should_retry: - self._cancel_handle = get_running_loop().call_soon( - self._deliver_cancellation, origin - ) - else: - self._cancel_handle = None - - return should_retry - - def _restart_cancellation_in_parent(self) -> None: - """ - Restart the cancellation effort in the closest directly cancelled parent scope. - - """ - scope = self._parent_scope - while scope is not None: - if scope._cancel_called: - if scope._cancel_handle is None: - scope._deliver_cancellation(scope) - - break - - # No point in looking beyond any shielded scope - if scope._shield: - break - - scope = scope._parent_scope - - def cancel(self) -> None: - if not self._cancel_called: - if self._timeout_handle: - self._timeout_handle.cancel() - self._timeout_handle = None - - self._cancel_called = True - if self._host_task is not None: - self._deliver_cancellation(self) - - @property - def deadline(self) -> float: - return self._deadline - - @deadline.setter - def deadline(self, value: float) -> None: - self._deadline = float(value) - if self._timeout_handle is not None: - self._timeout_handle.cancel() - self._timeout_handle = None - - if self._active and not self._cancel_called: - self._timeout() - - @property - def cancel_called(self) -> bool: - return self._cancel_called - - @property - def cancelled_caught(self) -> bool: - return self._cancelled_caught - - @property - def shield(self) -> bool: - return self._shield - - @shield.setter - def shield(self, value: bool) -> None: - if self._shield != value: - self._shield = value - if not value: - self._restart_cancellation_in_parent() - - -# -# Task states -# - - -class TaskState: - """ - Encapsulates auxiliary task information that cannot be added to the Task instance - itself because there are no guarantees about its implementation. - """ - - __slots__ = "parent_id", "cancel_scope", "__weakref__" - - def __init__(self, parent_id: int | None, cancel_scope: CancelScope | None): - self.parent_id = parent_id - self.cancel_scope = cancel_scope - - -_task_states: WeakKeyDictionary[asyncio.Task, TaskState] = WeakKeyDictionary() - - -# -# Task groups -# - - -class _AsyncioTaskStatus(abc.TaskStatus): - def __init__(self, future: asyncio.Future, parent_id: int): - self._future = future - self._parent_id = parent_id - - def started(self, value: T_contra | None = None) -> None: - try: - self._future.set_result(value) - except asyncio.InvalidStateError: - if not self._future.cancelled(): - raise RuntimeError( - "called 'started' twice on the same task status" - ) from None - - task = cast(asyncio.Task, current_task()) - _task_states[task].parent_id = self._parent_id - - -if sys.version_info >= (3, 12): - _eager_task_factory_code: CodeType | None = asyncio.eager_task_factory.__code__ -else: - _eager_task_factory_code = None - - -class TaskGroup(abc.TaskGroup): - def __init__(self) -> None: - self.cancel_scope: CancelScope = CancelScope() - self._active = False - self._exceptions: list[BaseException] = [] - self._tasks: set[asyncio.Task] = set() - self._on_completed_fut: asyncio.Future[None] | None = None - - async def __aenter__(self) -> TaskGroup: - self.cancel_scope.__enter__() - self._active = True - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - try: - if exc_val is not None: - self.cancel_scope.cancel() - if not isinstance(exc_val, CancelledError): - self._exceptions.append(exc_val) - - loop = get_running_loop() - try: - if self._tasks: - with CancelScope() as wait_scope: - while self._tasks: - self._on_completed_fut = loop.create_future() - - try: - await self._on_completed_fut - except CancelledError as exc: - # Shield the scope against further cancellation attempts, - # as they're not productive (#695) - wait_scope.shield = True - self.cancel_scope.cancel() - - # Set exc_val from the cancellation exception if it was - # previously unset. However, we should not replace a native - # cancellation exception with one raise by a cancel scope. - if exc_val is None or ( - isinstance(exc_val, CancelledError) - and not is_anyio_cancellation(exc) - ): - exc_val = exc - - self._on_completed_fut = None - else: - # If there are no child tasks to wait on, run at least one checkpoint - # anyway - await AsyncIOBackend.cancel_shielded_checkpoint() - - self._active = False - if self._exceptions: - # The exception that got us here should already have been - # added to self._exceptions so it's ok to break exception - # chaining and avoid adding a "During handling of above..." - # for each nesting level. - raise BaseExceptionGroup( - "unhandled errors in a TaskGroup", self._exceptions - ) from None - elif exc_val: - raise exc_val - except BaseException as exc: - if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__): - return True - - raise - - return self.cancel_scope.__exit__(exc_type, exc_val, exc_tb) - finally: - del exc_val, exc_tb, self._exceptions - - def _spawn( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - args: tuple[Unpack[PosArgsT]], - name: object, - task_status_future: asyncio.Future | None = None, - ) -> asyncio.Task: - def task_done(_task: asyncio.Task) -> None: - task_state = _task_states[_task] - assert task_state.cancel_scope is not None - assert _task in task_state.cancel_scope._tasks - task_state.cancel_scope._tasks.remove(_task) - self._tasks.remove(task) - del _task_states[_task] - - if self._on_completed_fut is not None and not self._tasks: - try: - self._on_completed_fut.set_result(None) - except asyncio.InvalidStateError: - pass - - try: - exc = _task.exception() - except CancelledError as e: - while isinstance(e.__context__, CancelledError): - e = e.__context__ - - exc = e - - if exc is not None: - # The future can only be in the cancelled state if the host task was - # cancelled, so return immediately instead of adding one more - # CancelledError to the exceptions list - if task_status_future is not None and task_status_future.cancelled(): - return - - if task_status_future is None or task_status_future.done(): - if not isinstance(exc, CancelledError): - self._exceptions.append(exc) - - if not self.cancel_scope._effectively_cancelled: - self.cancel_scope.cancel() - else: - task_status_future.set_exception(exc) - elif task_status_future is not None and not task_status_future.done(): - task_status_future.set_exception( - RuntimeError("Child exited without calling task_status.started()") - ) - - if not self._active: - raise RuntimeError( - "This task group is not active; no new tasks can be started." - ) - - kwargs = {} - if task_status_future: - parent_id = id(current_task()) - kwargs["task_status"] = _AsyncioTaskStatus( - task_status_future, id(self.cancel_scope._host_task) - ) - else: - parent_id = id(self.cancel_scope._host_task) - - coro = func(*args, **kwargs) - if not iscoroutine(coro): - prefix = f"{func.__module__}." if hasattr(func, "__module__") else "" - raise TypeError( - f"Expected {prefix}{func.__qualname__}() to return a coroutine, but " - f"the return value ({coro!r}) is not a coroutine object" - ) - - name = get_callable_name(func) if name is None else str(name) - loop = asyncio.get_running_loop() - if ( - (factory := loop.get_task_factory()) - and getattr(factory, "__code__", None) is _eager_task_factory_code - and (closure := getattr(factory, "__closure__", None)) - ): - custom_task_constructor = closure[0].cell_contents - task = custom_task_constructor(coro, loop=loop, name=name) - else: - task = create_task(coro, name=name) - - # Make the spawned task inherit the task group's cancel scope - _task_states[task] = TaskState( - parent_id=parent_id, cancel_scope=self.cancel_scope - ) - self.cancel_scope._tasks.add(task) - self._tasks.add(task) - task.add_done_callback(task_done) - return task - - def start_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> None: - self._spawn(func, args, name) - - async def start( - self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None - ) -> Any: - future: asyncio.Future = asyncio.Future() - task = self._spawn(func, args, name, future) - - # If the task raises an exception after sending a start value without a switch - # point between, the task group is cancelled and this method never proceeds to - # process the completed future. That's why we have to have a shielded cancel - # scope here. - try: - return await future - except CancelledError: - # Cancel the task and wait for it to exit before returning - task.cancel() - with CancelScope(shield=True), suppress(CancelledError): - await task - - raise - - -# -# Threads -# - -_Retval_Queue_Type = tuple[Optional[T_Retval], Optional[BaseException]] - - -class WorkerThread(Thread): - MAX_IDLE_TIME = 10 # seconds - - def __init__( - self, - root_task: asyncio.Task, - workers: set[WorkerThread], - idle_workers: deque[WorkerThread], - ): - super().__init__(name="AnyIO worker thread") - self.root_task = root_task - self.workers = workers - self.idle_workers = idle_workers - self.loop = root_task._loop - self.queue: Queue[ - tuple[Context, Callable, tuple, asyncio.Future, CancelScope] | None - ] = Queue(2) - self.idle_since = AsyncIOBackend.current_time() - self.stopping = False - - def _report_result( - self, future: asyncio.Future, result: Any, exc: BaseException | None - ) -> None: - self.idle_since = AsyncIOBackend.current_time() - if not self.stopping: - self.idle_workers.append(self) - - if not future.cancelled(): - if exc is not None: - if isinstance(exc, StopIteration): - new_exc = RuntimeError("coroutine raised StopIteration") - new_exc.__cause__ = exc - exc = new_exc - - future.set_exception(exc) - else: - future.set_result(result) - - def run(self) -> None: - with claim_worker_thread(AsyncIOBackend, self.loop): - while True: - item = self.queue.get() - if item is None: - # Shutdown command received - return - - context, func, args, future, cancel_scope = item - if not future.cancelled(): - result = None - exception: BaseException | None = None - threadlocals.current_cancel_scope = cancel_scope - try: - result = context.run(func, *args) - except BaseException as exc: - exception = exc - finally: - del threadlocals.current_cancel_scope - - if not self.loop.is_closed(): - self.loop.call_soon_threadsafe( - self._report_result, future, result, exception - ) - - del result, exception - - self.queue.task_done() - del item, context, func, args, future, cancel_scope - - def stop(self, f: asyncio.Task | None = None) -> None: - self.stopping = True - self.queue.put_nowait(None) - self.workers.discard(self) - try: - self.idle_workers.remove(self) - except ValueError: - pass - - -_threadpool_idle_workers: RunVar[deque[WorkerThread]] = RunVar( - "_threadpool_idle_workers" -) -_threadpool_workers: RunVar[set[WorkerThread]] = RunVar("_threadpool_workers") - - -class BlockingPortal(abc.BlockingPortal): - def __new__(cls) -> BlockingPortal: - return object.__new__(cls) - - def __init__(self) -> None: - super().__init__() - self._loop = get_running_loop() - - def _spawn_task_from_thread( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - name: object, - future: Future[T_Retval], - ) -> None: - AsyncIOBackend.run_sync_from_thread( - partial(self._task_group.start_soon, name=name), - (self._call_func, func, args, kwargs, future), - self._loop, - ) - - -# -# Subprocesses -# - - -@dataclass(eq=False) -class StreamReaderWrapper(abc.ByteReceiveStream): - _stream: asyncio.StreamReader - - async def receive(self, max_bytes: int = 65536) -> bytes: - data = await self._stream.read(max_bytes) - if data: - return data - else: - raise EndOfStream - - async def aclose(self) -> None: - self._stream.set_exception(ClosedResourceError()) - await AsyncIOBackend.checkpoint() - - -@dataclass(eq=False) -class StreamWriterWrapper(abc.ByteSendStream): - _stream: asyncio.StreamWriter - - async def send(self, item: bytes) -> None: - self._stream.write(item) - await self._stream.drain() - - async def aclose(self) -> None: - self._stream.close() - await AsyncIOBackend.checkpoint() - - -@dataclass(eq=False) -class Process(abc.Process): - _process: asyncio.subprocess.Process - _stdin: StreamWriterWrapper | None - _stdout: StreamReaderWrapper | None - _stderr: StreamReaderWrapper | None - - async def aclose(self) -> None: - with CancelScope(shield=True) as scope: - if self._stdin: - await self._stdin.aclose() - if self._stdout: - await self._stdout.aclose() - if self._stderr: - await self._stderr.aclose() - - scope.shield = False - try: - await self.wait() - except BaseException: - scope.shield = True - self.kill() - await self.wait() - raise - - async def wait(self) -> int: - return await self._process.wait() - - def terminate(self) -> None: - self._process.terminate() - - def kill(self) -> None: - self._process.kill() - - def send_signal(self, signal: int) -> None: - self._process.send_signal(signal) - - @property - def pid(self) -> int: - return self._process.pid - - @property - def returncode(self) -> int | None: - return self._process.returncode - - @property - def stdin(self) -> abc.ByteSendStream | None: - return self._stdin - - @property - def stdout(self) -> abc.ByteReceiveStream | None: - return self._stdout - - @property - def stderr(self) -> abc.ByteReceiveStream | None: - return self._stderr - - -def _forcibly_shutdown_process_pool_on_exit( - workers: set[Process], _task: object -) -> None: - """ - Forcibly shuts down worker processes belonging to this event loop.""" - child_watcher: asyncio.AbstractChildWatcher | None = None - if sys.version_info < (3, 12): - try: - child_watcher = asyncio.get_event_loop_policy().get_child_watcher() - except NotImplementedError: - pass - - # Close as much as possible (w/o async/await) to avoid warnings - for process in workers: - if process.returncode is None: - continue - - process._stdin._stream._transport.close() # type: ignore[union-attr] - process._stdout._stream._transport.close() # type: ignore[union-attr] - process._stderr._stream._transport.close() # type: ignore[union-attr] - process.kill() - if child_watcher: - child_watcher.remove_child_handler(process.pid) - - -async def _shutdown_process_pool_on_exit(workers: set[abc.Process]) -> None: - """ - Shuts down worker processes belonging to this event loop. - - NOTE: this only works when the event loop was started using asyncio.run() or - anyio.run(). - - """ - process: abc.Process - try: - await sleep(math.inf) - except asyncio.CancelledError: - for process in workers: - if process.returncode is None: - process.kill() - - for process in workers: - await process.aclose() - - -# -# Sockets and networking -# - - -class StreamProtocol(asyncio.Protocol): - read_queue: deque[bytes] - read_event: asyncio.Event - write_event: asyncio.Event - exception: Exception | None = None - is_at_eof: bool = False - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - self.read_queue = deque() - self.read_event = asyncio.Event() - self.write_event = asyncio.Event() - self.write_event.set() - cast(asyncio.Transport, transport).set_write_buffer_limits(0) - - def connection_lost(self, exc: Exception | None) -> None: - if exc: - self.exception = BrokenResourceError() - self.exception.__cause__ = exc - - self.read_event.set() - self.write_event.set() - - def data_received(self, data: bytes) -> None: - # ProactorEventloop sometimes sends bytearray instead of bytes - self.read_queue.append(bytes(data)) - self.read_event.set() - - def eof_received(self) -> bool | None: - self.is_at_eof = True - self.read_event.set() - return True - - def pause_writing(self) -> None: - self.write_event = asyncio.Event() - - def resume_writing(self) -> None: - self.write_event.set() - - -class DatagramProtocol(asyncio.DatagramProtocol): - read_queue: deque[tuple[bytes, IPSockAddrType]] - read_event: asyncio.Event - write_event: asyncio.Event - exception: Exception | None = None - - def connection_made(self, transport: asyncio.BaseTransport) -> None: - self.read_queue = deque(maxlen=100) # arbitrary value - self.read_event = asyncio.Event() - self.write_event = asyncio.Event() - self.write_event.set() - - def connection_lost(self, exc: Exception | None) -> None: - self.read_event.set() - self.write_event.set() - - def datagram_received(self, data: bytes, addr: IPSockAddrType) -> None: - addr = convert_ipv6_sockaddr(addr) - self.read_queue.append((data, addr)) - self.read_event.set() - - def error_received(self, exc: Exception) -> None: - self.exception = exc - - def pause_writing(self) -> None: - self.write_event.clear() - - def resume_writing(self) -> None: - self.write_event.set() - - -class SocketStream(abc.SocketStream): - def __init__(self, transport: asyncio.Transport, protocol: StreamProtocol): - self._transport = transport - self._protocol = protocol - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - self._closed = False - - @property - def _raw_socket(self) -> socket.socket: - return self._transport.get_extra_info("socket") - - async def receive(self, max_bytes: int = 65536) -> bytes: - with self._receive_guard: - if ( - not self._protocol.read_event.is_set() - and not self._transport.is_closing() - and not self._protocol.is_at_eof - ): - self._transport.resume_reading() - await self._protocol.read_event.wait() - self._transport.pause_reading() - else: - await AsyncIOBackend.checkpoint() - - try: - chunk = self._protocol.read_queue.popleft() - except IndexError: - if self._closed: - raise ClosedResourceError from None - elif self._protocol.exception: - raise self._protocol.exception from None - else: - raise EndOfStream from None - - if len(chunk) > max_bytes: - # Split the oversized chunk - chunk, leftover = chunk[:max_bytes], chunk[max_bytes:] - self._protocol.read_queue.appendleft(leftover) - - # If the read queue is empty, clear the flag so that the next call will - # block until data is available - if not self._protocol.read_queue: - self._protocol.read_event.clear() - - return chunk - - async def send(self, item: bytes) -> None: - with self._send_guard: - await AsyncIOBackend.checkpoint() - - if self._closed: - raise ClosedResourceError - elif self._protocol.exception is not None: - raise self._protocol.exception - - try: - self._transport.write(item) - except RuntimeError as exc: - if self._transport.is_closing(): - raise BrokenResourceError from exc - else: - raise - - await self._protocol.write_event.wait() - - async def send_eof(self) -> None: - try: - self._transport.write_eof() - except OSError: - pass - - async def aclose(self) -> None: - if not self._transport.is_closing(): - self._closed = True - try: - self._transport.write_eof() - except OSError: - pass - - self._transport.close() - await sleep(0) - self._transport.abort() - - -class _RawSocketMixin: - _receive_future: asyncio.Future | None = None - _send_future: asyncio.Future | None = None - _closing = False - - def __init__(self, raw_socket: socket.socket): - self.__raw_socket = raw_socket - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - @property - def _raw_socket(self) -> socket.socket: - return self.__raw_socket - - def _wait_until_readable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: - def callback(f: object) -> None: - del self._receive_future - loop.remove_reader(self.__raw_socket) - - f = self._receive_future = asyncio.Future() - loop.add_reader(self.__raw_socket, f.set_result, None) - f.add_done_callback(callback) - return f - - def _wait_until_writable(self, loop: asyncio.AbstractEventLoop) -> asyncio.Future: - def callback(f: object) -> None: - del self._send_future - loop.remove_writer(self.__raw_socket) - - f = self._send_future = asyncio.Future() - loop.add_writer(self.__raw_socket, f.set_result, None) - f.add_done_callback(callback) - return f - - async def aclose(self) -> None: - if not self._closing: - self._closing = True - if self.__raw_socket.fileno() != -1: - self.__raw_socket.close() - - if self._receive_future: - self._receive_future.set_result(None) - if self._send_future: - self._send_future.set_result(None) - - -class UNIXSocketStream(_RawSocketMixin, abc.UNIXSocketStream): - async def send_eof(self) -> None: - with self._send_guard: - self._raw_socket.shutdown(socket.SHUT_WR) - - async def receive(self, max_bytes: int = 65536) -> bytes: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - data = self._raw_socket.recv(max_bytes) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - if not data: - raise EndOfStream - - return data - - async def send(self, item: bytes) -> None: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._send_guard: - view = memoryview(item) - while view: - try: - bytes_sent = self._raw_socket.send(view) - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - view = view[bytes_sent:] - - async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: - if not isinstance(msglen, int) or msglen < 0: - raise ValueError("msglen must be a non-negative integer") - if not isinstance(maxfds, int) or maxfds < 1: - raise ValueError("maxfds must be a positive integer") - - loop = get_running_loop() - fds = array.array("i") - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - message, ancdata, flags, addr = self._raw_socket.recvmsg( - msglen, socket.CMSG_LEN(maxfds * fds.itemsize) - ) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - if not message and not ancdata: - raise EndOfStream - - break - - for cmsg_level, cmsg_type, cmsg_data in ancdata: - if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: - raise RuntimeError( - f"Received unexpected ancillary data; message = {message!r}, " - f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" - ) - - fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) - - return message, list(fds) - - async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: - if not message: - raise ValueError("message must not be empty") - if not fds: - raise ValueError("fds must not be empty") - - loop = get_running_loop() - filenos: list[int] = [] - for fd in fds: - if isinstance(fd, int): - filenos.append(fd) - elif isinstance(fd, IOBase): - filenos.append(fd.fileno()) - - fdarray = array.array("i", filenos) - await AsyncIOBackend.checkpoint() - with self._send_guard: - while True: - try: - # The ignore can be removed after mypy picks up - # https://github.com/python/typeshed/pull/5545 - self._raw_socket.sendmsg( - [message], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fdarray)] - ) - break - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - - -class TCPSocketListener(abc.SocketListener): - _accept_scope: CancelScope | None = None - _closed = False - - def __init__(self, raw_socket: socket.socket): - self.__raw_socket = raw_socket - self._loop = cast(asyncio.BaseEventLoop, get_running_loop()) - self._accept_guard = ResourceGuard("accepting connections from") - - @property - def _raw_socket(self) -> socket.socket: - return self.__raw_socket - - async def accept(self) -> abc.SocketStream: - if self._closed: - raise ClosedResourceError - - with self._accept_guard: - await AsyncIOBackend.checkpoint() - with CancelScope() as self._accept_scope: - try: - client_sock, _addr = await self._loop.sock_accept(self._raw_socket) - except asyncio.CancelledError: - # Workaround for https://bugs.python.org/issue41317 - try: - self._loop.remove_reader(self._raw_socket) - except (ValueError, NotImplementedError): - pass - - if self._closed: - raise ClosedResourceError from None - - raise - finally: - self._accept_scope = None - - client_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - transport, protocol = await self._loop.connect_accepted_socket( - StreamProtocol, client_sock - ) - return SocketStream(transport, protocol) - - async def aclose(self) -> None: - if self._closed: - return - - self._closed = True - if self._accept_scope: - # Workaround for https://bugs.python.org/issue41317 - try: - self._loop.remove_reader(self._raw_socket) - except (ValueError, NotImplementedError): - pass - - self._accept_scope.cancel() - await sleep(0) - - self._raw_socket.close() - - -class UNIXSocketListener(abc.SocketListener): - def __init__(self, raw_socket: socket.socket): - self.__raw_socket = raw_socket - self._loop = get_running_loop() - self._accept_guard = ResourceGuard("accepting connections from") - self._closed = False - - async def accept(self) -> abc.SocketStream: - await AsyncIOBackend.checkpoint() - with self._accept_guard: - while True: - try: - client_sock, _ = self.__raw_socket.accept() - client_sock.setblocking(False) - return UNIXSocketStream(client_sock) - except BlockingIOError: - f: asyncio.Future = asyncio.Future() - self._loop.add_reader(self.__raw_socket, f.set_result, None) - f.add_done_callback( - lambda _: self._loop.remove_reader(self.__raw_socket) - ) - await f - except OSError as exc: - if self._closed: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - - async def aclose(self) -> None: - self._closed = True - self.__raw_socket.close() - - @property - def _raw_socket(self) -> socket.socket: - return self.__raw_socket - - -class UDPSocket(abc.UDPSocket): - def __init__( - self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol - ): - self._transport = transport - self._protocol = protocol - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - self._closed = False - - @property - def _raw_socket(self) -> socket.socket: - return self._transport.get_extra_info("socket") - - async def aclose(self) -> None: - if not self._transport.is_closing(): - self._closed = True - self._transport.close() - - async def receive(self) -> tuple[bytes, IPSockAddrType]: - with self._receive_guard: - await AsyncIOBackend.checkpoint() - - # If the buffer is empty, ask for more data - if not self._protocol.read_queue and not self._transport.is_closing(): - self._protocol.read_event.clear() - await self._protocol.read_event.wait() - - try: - return self._protocol.read_queue.popleft() - except IndexError: - if self._closed: - raise ClosedResourceError from None - else: - raise BrokenResourceError from None - - async def send(self, item: UDPPacketType) -> None: - with self._send_guard: - await AsyncIOBackend.checkpoint() - await self._protocol.write_event.wait() - if self._closed: - raise ClosedResourceError - elif self._transport.is_closing(): - raise BrokenResourceError - else: - self._transport.sendto(*item) - - -class ConnectedUDPSocket(abc.ConnectedUDPSocket): - def __init__( - self, transport: asyncio.DatagramTransport, protocol: DatagramProtocol - ): - self._transport = transport - self._protocol = protocol - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - self._closed = False - - @property - def _raw_socket(self) -> socket.socket: - return self._transport.get_extra_info("socket") - - async def aclose(self) -> None: - if not self._transport.is_closing(): - self._closed = True - self._transport.close() - - async def receive(self) -> bytes: - with self._receive_guard: - await AsyncIOBackend.checkpoint() - - # If the buffer is empty, ask for more data - if not self._protocol.read_queue and not self._transport.is_closing(): - self._protocol.read_event.clear() - await self._protocol.read_event.wait() - - try: - packet = self._protocol.read_queue.popleft() - except IndexError: - if self._closed: - raise ClosedResourceError from None - else: - raise BrokenResourceError from None - - return packet[0] - - async def send(self, item: bytes) -> None: - with self._send_guard: - await AsyncIOBackend.checkpoint() - await self._protocol.write_event.wait() - if self._closed: - raise ClosedResourceError - elif self._transport.is_closing(): - raise BrokenResourceError - else: - self._transport.sendto(item) - - -class UNIXDatagramSocket(_RawSocketMixin, abc.UNIXDatagramSocket): - async def receive(self) -> UNIXDatagramPacketType: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - data = self._raw_socket.recvfrom(65536) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return data - - async def send(self, item: UNIXDatagramPacketType) -> None: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._send_guard: - while True: - try: - self._raw_socket.sendto(*item) - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return - - -class ConnectedUNIXDatagramSocket(_RawSocketMixin, abc.ConnectedUNIXDatagramSocket): - async def receive(self) -> bytes: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._receive_guard: - while True: - try: - data = self._raw_socket.recv(65536) - except BlockingIOError: - await self._wait_until_readable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return data - - async def send(self, item: bytes) -> None: - loop = get_running_loop() - await AsyncIOBackend.checkpoint() - with self._send_guard: - while True: - try: - self._raw_socket.send(item) - except BlockingIOError: - await self._wait_until_writable(loop) - except OSError as exc: - if self._closing: - raise ClosedResourceError from None - else: - raise BrokenResourceError from exc - else: - return - - -_read_events: RunVar[dict[int, asyncio.Event]] = RunVar("read_events") -_write_events: RunVar[dict[int, asyncio.Event]] = RunVar("write_events") - - -# -# Synchronization -# - - -class Event(BaseEvent): - def __new__(cls) -> Event: - return object.__new__(cls) - - def __init__(self) -> None: - self._event = asyncio.Event() - - def set(self) -> None: - self._event.set() - - def is_set(self) -> bool: - return self._event.is_set() - - async def wait(self) -> None: - if self.is_set(): - await AsyncIOBackend.checkpoint() - else: - await self._event.wait() - - def statistics(self) -> EventStatistics: - return EventStatistics(len(self._event._waiters)) - - -class Lock(BaseLock): - def __new__(cls, *, fast_acquire: bool = False) -> Lock: - return object.__new__(cls) - - def __init__(self, *, fast_acquire: bool = False) -> None: - self._fast_acquire = fast_acquire - self._owner_task: asyncio.Task | None = None - self._waiters: deque[tuple[asyncio.Task, asyncio.Future]] = deque() - - async def acquire(self) -> None: - task = cast(asyncio.Task, current_task()) - if self._owner_task is None and not self._waiters: - await AsyncIOBackend.checkpoint_if_cancelled() - self._owner_task = task - - # Unless on the "fast path", yield control of the event loop so that other - # tasks can run too - if not self._fast_acquire: - try: - await AsyncIOBackend.cancel_shielded_checkpoint() - except CancelledError: - self.release() - raise - - return - - if self._owner_task == task: - raise RuntimeError("Attempted to acquire an already held Lock") - - fut: asyncio.Future[None] = asyncio.Future() - item = task, fut - self._waiters.append(item) - try: - await fut - except CancelledError: - self._waiters.remove(item) - if self._owner_task is task: - self.release() - - raise - - self._waiters.remove(item) - - def acquire_nowait(self) -> None: - task = cast(asyncio.Task, current_task()) - if self._owner_task is None and not self._waiters: - self._owner_task = task - return - - if self._owner_task is task: - raise RuntimeError("Attempted to acquire an already held Lock") - - raise WouldBlock - - def locked(self) -> bool: - return self._owner_task is not None - - def release(self) -> None: - if self._owner_task != current_task(): - raise RuntimeError("The current task is not holding this lock") - - for task, fut in self._waiters: - if not fut.cancelled(): - self._owner_task = task - fut.set_result(None) - return - - self._owner_task = None - - def statistics(self) -> LockStatistics: - task_info = AsyncIOTaskInfo(self._owner_task) if self._owner_task else None - return LockStatistics(self.locked(), task_info, len(self._waiters)) - - -class Semaphore(BaseSemaphore): - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - return object.__new__(cls) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ): - super().__init__(initial_value, max_value=max_value) - self._value = initial_value - self._max_value = max_value - self._fast_acquire = fast_acquire - self._waiters: deque[asyncio.Future[None]] = deque() - - async def acquire(self) -> None: - if self._value > 0 and not self._waiters: - await AsyncIOBackend.checkpoint_if_cancelled() - self._value -= 1 - - # Unless on the "fast path", yield control of the event loop so that other - # tasks can run too - if not self._fast_acquire: - try: - await AsyncIOBackend.cancel_shielded_checkpoint() - except CancelledError: - self.release() - raise - - return - - fut: asyncio.Future[None] = asyncio.Future() - self._waiters.append(fut) - try: - await fut - except CancelledError: - try: - self._waiters.remove(fut) - except ValueError: - self.release() - - raise - - def acquire_nowait(self) -> None: - if self._value == 0: - raise WouldBlock - - self._value -= 1 - - def release(self) -> None: - if self._max_value is not None and self._value == self._max_value: - raise ValueError("semaphore released too many times") - - for fut in self._waiters: - if not fut.cancelled(): - fut.set_result(None) - self._waiters.remove(fut) - return - - self._value += 1 - - @property - def value(self) -> int: - return self._value - - @property - def max_value(self) -> int | None: - return self._max_value - - def statistics(self) -> SemaphoreStatistics: - return SemaphoreStatistics(len(self._waiters)) - - -class CapacityLimiter(BaseCapacityLimiter): - _total_tokens: float = 0 - - def __new__(cls, total_tokens: float) -> CapacityLimiter: - return object.__new__(cls) - - def __init__(self, total_tokens: float): - self._borrowers: set[Any] = set() - self._wait_queue: OrderedDict[Any, asyncio.Event] = OrderedDict() - self.total_tokens = total_tokens - - async def __aenter__(self) -> None: - await self.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - @property - def total_tokens(self) -> float: - return self._total_tokens - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - if not isinstance(value, int) and not math.isinf(value): - raise TypeError("total_tokens must be an int or math.inf") - if value < 1: - raise ValueError("total_tokens must be >= 1") - - waiters_to_notify = max(value - self._total_tokens, 0) - self._total_tokens = value - - # Notify waiting tasks that they have acquired the limiter - while self._wait_queue and waiters_to_notify: - event = self._wait_queue.popitem(last=False)[1] - event.set() - waiters_to_notify -= 1 - - @property - def borrowed_tokens(self) -> int: - return len(self._borrowers) - - @property - def available_tokens(self) -> float: - return self._total_tokens - len(self._borrowers) - - def acquire_nowait(self) -> None: - self.acquire_on_behalf_of_nowait(current_task()) - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - if borrower in self._borrowers: - raise RuntimeError( - "this borrower is already holding one of this CapacityLimiter's tokens" - ) - - if self._wait_queue or len(self._borrowers) >= self._total_tokens: - raise WouldBlock - - self._borrowers.add(borrower) - - async def acquire(self) -> None: - return await self.acquire_on_behalf_of(current_task()) - - async def acquire_on_behalf_of(self, borrower: object) -> None: - await AsyncIOBackend.checkpoint_if_cancelled() - try: - self.acquire_on_behalf_of_nowait(borrower) - except WouldBlock: - event = asyncio.Event() - self._wait_queue[borrower] = event - try: - await event.wait() - except BaseException: - self._wait_queue.pop(borrower, None) - raise - - self._borrowers.add(borrower) - else: - try: - await AsyncIOBackend.cancel_shielded_checkpoint() - except BaseException: - self.release() - raise - - def release(self) -> None: - self.release_on_behalf_of(current_task()) - - def release_on_behalf_of(self, borrower: object) -> None: - try: - self._borrowers.remove(borrower) - except KeyError: - raise RuntimeError( - "this borrower isn't holding any of this CapacityLimiter's tokens" - ) from None - - # Notify the next task in line if this limiter has free capacity now - if self._wait_queue and len(self._borrowers) < self._total_tokens: - event = self._wait_queue.popitem(last=False)[1] - event.set() - - def statistics(self) -> CapacityLimiterStatistics: - return CapacityLimiterStatistics( - self.borrowed_tokens, - self.total_tokens, - tuple(self._borrowers), - len(self._wait_queue), - ) - - -_default_thread_limiter: RunVar[CapacityLimiter] = RunVar("_default_thread_limiter") - - -# -# Operating system signals -# - - -class _SignalReceiver: - def __init__(self, signals: tuple[Signals, ...]): - self._signals = signals - self._loop = get_running_loop() - self._signal_queue: deque[Signals] = deque() - self._future: asyncio.Future = asyncio.Future() - self._handled_signals: set[Signals] = set() - - def _deliver(self, signum: Signals) -> None: - self._signal_queue.append(signum) - if not self._future.done(): - self._future.set_result(None) - - def __enter__(self) -> _SignalReceiver: - for sig in set(self._signals): - self._loop.add_signal_handler(sig, self._deliver, sig) - self._handled_signals.add(sig) - - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - for sig in self._handled_signals: - self._loop.remove_signal_handler(sig) - - def __aiter__(self) -> _SignalReceiver: - return self - - async def __anext__(self) -> Signals: - await AsyncIOBackend.checkpoint() - if not self._signal_queue: - self._future = asyncio.Future() - await self._future - - return self._signal_queue.popleft() - - -# -# Testing and debugging -# - - -class AsyncIOTaskInfo(TaskInfo): - def __init__(self, task: asyncio.Task): - task_state = _task_states.get(task) - if task_state is None: - parent_id = None - else: - parent_id = task_state.parent_id - - coro = task.get_coro() - assert coro is not None, "created TaskInfo from a completed Task" - super().__init__(id(task), parent_id, task.get_name(), coro) - self._task = weakref.ref(task) - - def has_pending_cancellation(self) -> bool: - if not (task := self._task()): - # If the task isn't around anymore, it won't have a pending cancellation - return False - - if task._must_cancel: # type: ignore[attr-defined] - return True - elif ( - isinstance(task._fut_waiter, asyncio.Future) # type: ignore[attr-defined] - and task._fut_waiter.cancelled() # type: ignore[attr-defined] - ): - return True - - if task_state := _task_states.get(task): - if cancel_scope := task_state.cancel_scope: - return cancel_scope._effectively_cancelled - - return False - - -class TestRunner(abc.TestRunner): - _send_stream: MemoryObjectSendStream[tuple[Awaitable[Any], asyncio.Future[Any]]] - - def __init__( - self, - *, - debug: bool | None = None, - use_uvloop: bool = False, - loop_factory: Callable[[], AbstractEventLoop] | None = None, - ) -> None: - if use_uvloop and loop_factory is None: - import uvloop - - loop_factory = uvloop.new_event_loop - - self._runner = Runner(debug=debug, loop_factory=loop_factory) - self._exceptions: list[BaseException] = [] - self._runner_task: asyncio.Task | None = None - - def __enter__(self) -> TestRunner: - self._runner.__enter__() - self.get_loop().set_exception_handler(self._exception_handler) - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self._runner.__exit__(exc_type, exc_val, exc_tb) - - def get_loop(self) -> AbstractEventLoop: - return self._runner.get_loop() - - def _exception_handler( - self, loop: asyncio.AbstractEventLoop, context: dict[str, Any] - ) -> None: - if isinstance(context.get("exception"), Exception): - self._exceptions.append(context["exception"]) - else: - loop.default_exception_handler(context) - - def _raise_async_exceptions(self) -> None: - # Re-raise any exceptions raised in asynchronous callbacks - if self._exceptions: - exceptions, self._exceptions = self._exceptions, [] - if len(exceptions) == 1: - raise exceptions[0] - elif exceptions: - raise BaseExceptionGroup( - "Multiple exceptions occurred in asynchronous callbacks", exceptions - ) - - async def _run_tests_and_fixtures( - self, - receive_stream: MemoryObjectReceiveStream[ - tuple[Awaitable[T_Retval], asyncio.Future[T_Retval]] - ], - ) -> None: - from _pytest.outcomes import OutcomeException - - with receive_stream, self._send_stream: - async for coro, future in receive_stream: - try: - retval = await coro - except CancelledError as exc: - if not future.cancelled(): - future.cancel(*exc.args) - - raise - except BaseException as exc: - if not future.cancelled(): - future.set_exception(exc) - - if not isinstance(exc, (Exception, OutcomeException)): - raise - else: - if not future.cancelled(): - future.set_result(retval) - - async def _call_in_runner_task( - self, - func: Callable[P, Awaitable[T_Retval]], - *args: P.args, - **kwargs: P.kwargs, - ) -> T_Retval: - if not self._runner_task: - self._send_stream, receive_stream = create_memory_object_stream[ - tuple[Awaitable[Any], asyncio.Future] - ](1) - self._runner_task = self.get_loop().create_task( - self._run_tests_and_fixtures(receive_stream) - ) - - coro = func(*args, **kwargs) - future: asyncio.Future[T_Retval] = self.get_loop().create_future() - self._send_stream.send_nowait((coro, future)) - return await future - - def run_asyncgen_fixture( - self, - fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], - kwargs: dict[str, Any], - ) -> Iterable[T_Retval]: - asyncgen = fixture_func(**kwargs) - fixturevalue: T_Retval = self.get_loop().run_until_complete( - self._call_in_runner_task(asyncgen.asend, None) - ) - self._raise_async_exceptions() - - yield fixturevalue - - try: - self.get_loop().run_until_complete( - self._call_in_runner_task(asyncgen.asend, None) - ) - except StopAsyncIteration: - self._raise_async_exceptions() - else: - self.get_loop().run_until_complete(asyncgen.aclose()) - raise RuntimeError("Async generator fixture did not stop") - - def run_fixture( - self, - fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], - kwargs: dict[str, Any], - ) -> T_Retval: - retval = self.get_loop().run_until_complete( - self._call_in_runner_task(fixture_func, **kwargs) - ) - self._raise_async_exceptions() - return retval - - def run_test( - self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] - ) -> None: - try: - self.get_loop().run_until_complete( - self._call_in_runner_task(test_func, **kwargs) - ) - except Exception as exc: - self._exceptions.append(exc) - - self._raise_async_exceptions() - - -class AsyncIOBackend(AsyncBackend): - @classmethod - def run( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - options: dict[str, Any], - ) -> T_Retval: - @wraps(func) - async def wrapper() -> T_Retval: - task = cast(asyncio.Task, current_task()) - task.set_name(get_callable_name(func)) - _task_states[task] = TaskState(None, None) - - try: - return await func(*args) - finally: - del _task_states[task] - - debug = options.get("debug", None) - loop_factory = options.get("loop_factory", None) - if loop_factory is None and options.get("use_uvloop", False): - import uvloop - - loop_factory = uvloop.new_event_loop - - with Runner(debug=debug, loop_factory=loop_factory) as runner: - return runner.run(wrapper()) - - @classmethod - def current_token(cls) -> object: - return get_running_loop() - - @classmethod - def current_time(cls) -> float: - return get_running_loop().time() - - @classmethod - def cancelled_exception_class(cls) -> type[BaseException]: - return CancelledError - - @classmethod - async def checkpoint(cls) -> None: - await sleep(0) - - @classmethod - async def checkpoint_if_cancelled(cls) -> None: - task = current_task() - if task is None: - return - - try: - cancel_scope = _task_states[task].cancel_scope - except KeyError: - return - - while cancel_scope: - if cancel_scope.cancel_called: - await sleep(0) - elif cancel_scope.shield: - break - else: - cancel_scope = cancel_scope._parent_scope - - @classmethod - async def cancel_shielded_checkpoint(cls) -> None: - with CancelScope(shield=True): - await sleep(0) - - @classmethod - async def sleep(cls, delay: float) -> None: - await sleep(delay) - - @classmethod - def create_cancel_scope( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - return CancelScope(deadline=deadline, shield=shield) - - @classmethod - def current_effective_deadline(cls) -> float: - if (task := current_task()) is None: - return math.inf - - try: - cancel_scope = _task_states[task].cancel_scope - except KeyError: - return math.inf - - deadline = math.inf - while cancel_scope: - deadline = min(deadline, cancel_scope.deadline) - if cancel_scope._cancel_called: - deadline = -math.inf - break - elif cancel_scope.shield: - break - else: - cancel_scope = cancel_scope._parent_scope - - return deadline - - @classmethod - def create_task_group(cls) -> abc.TaskGroup: - return TaskGroup() - - @classmethod - def create_event(cls) -> abc.Event: - return Event() - - @classmethod - def create_lock(cls, *, fast_acquire: bool) -> abc.Lock: - return Lock(fast_acquire=fast_acquire) - - @classmethod - def create_semaphore( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> abc.Semaphore: - return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) - - @classmethod - def create_capacity_limiter(cls, total_tokens: float) -> abc.CapacityLimiter: - return CapacityLimiter(total_tokens) - - @classmethod - async def run_sync_in_worker_thread( # type: ignore[return] - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - abandon_on_cancel: bool = False, - limiter: abc.CapacityLimiter | None = None, - ) -> T_Retval: - await cls.checkpoint() - - # If this is the first run in this event loop thread, set up the necessary - # variables - try: - idle_workers = _threadpool_idle_workers.get() - workers = _threadpool_workers.get() - except LookupError: - idle_workers = deque() - workers = set() - _threadpool_idle_workers.set(idle_workers) - _threadpool_workers.set(workers) - - async with limiter or cls.current_default_thread_limiter(): - with CancelScope(shield=not abandon_on_cancel) as scope: - future = asyncio.Future[T_Retval]() - root_task = find_root_task() - if not idle_workers: - worker = WorkerThread(root_task, workers, idle_workers) - worker.start() - workers.add(worker) - root_task.add_done_callback( - worker.stop, context=contextvars.Context() - ) - else: - worker = idle_workers.pop() - - # Prune any other workers that have been idle for MAX_IDLE_TIME - # seconds or longer - now = cls.current_time() - while idle_workers: - if ( - now - idle_workers[0].idle_since - < WorkerThread.MAX_IDLE_TIME - ): - break - - expired_worker = idle_workers.popleft() - expired_worker.root_task.remove_done_callback( - expired_worker.stop - ) - expired_worker.stop() - - context = copy_context() - context.run(sniffio.current_async_library_cvar.set, None) - if abandon_on_cancel or scope._parent_scope is None: - worker_scope = scope - else: - worker_scope = scope._parent_scope - - worker.queue.put_nowait((context, func, args, future, worker_scope)) - return await future - - @classmethod - def check_cancelled(cls) -> None: - scope: CancelScope | None = threadlocals.current_cancel_scope - while scope is not None: - if scope.cancel_called: - raise CancelledError(f"Cancelled by cancel scope {id(scope):x}") - - if scope.shield: - return - - scope = scope._parent_scope - - @classmethod - def run_async_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - async def task_wrapper(scope: CancelScope) -> T_Retval: - __tracebackhide__ = True - task = cast(asyncio.Task, current_task()) - _task_states[task] = TaskState(None, scope) - scope._tasks.add(task) - try: - return await func(*args) - except CancelledError as exc: - raise concurrent.futures.CancelledError(str(exc)) from None - finally: - scope._tasks.discard(task) - - loop = cast(AbstractEventLoop, token) - context = copy_context() - context.run(sniffio.current_async_library_cvar.set, "asyncio") - wrapper = task_wrapper(threadlocals.current_cancel_scope) - f: concurrent.futures.Future[T_Retval] = context.run( - asyncio.run_coroutine_threadsafe, wrapper, loop - ) - return f.result() - - @classmethod - def run_sync_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - @wraps(func) - def wrapper() -> None: - try: - sniffio.current_async_library_cvar.set("asyncio") - f.set_result(func(*args)) - except BaseException as exc: - f.set_exception(exc) - if not isinstance(exc, Exception): - raise - - f: concurrent.futures.Future[T_Retval] = Future() - loop = cast(AbstractEventLoop, token) - loop.call_soon_threadsafe(wrapper) - return f.result() - - @classmethod - def create_blocking_portal(cls) -> abc.BlockingPortal: - return BlockingPortal() - - @classmethod - async def open_process( - cls, - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None, - stdout: int | IO[Any] | None, - stderr: int | IO[Any] | None, - **kwargs: Any, - ) -> Process: - await cls.checkpoint() - if isinstance(command, PathLike): - command = os.fspath(command) - - if isinstance(command, (str, bytes)): - process = await asyncio.create_subprocess_shell( - command, - stdin=stdin, - stdout=stdout, - stderr=stderr, - **kwargs, - ) - else: - process = await asyncio.create_subprocess_exec( - *command, - stdin=stdin, - stdout=stdout, - stderr=stderr, - **kwargs, - ) - - stdin_stream = StreamWriterWrapper(process.stdin) if process.stdin else None - stdout_stream = StreamReaderWrapper(process.stdout) if process.stdout else None - stderr_stream = StreamReaderWrapper(process.stderr) if process.stderr else None - return Process(process, stdin_stream, stdout_stream, stderr_stream) - - @classmethod - def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: - create_task( - _shutdown_process_pool_on_exit(workers), - name="AnyIO process pool shutdown task", - ) - find_root_task().add_done_callback( - partial(_forcibly_shutdown_process_pool_on_exit, workers) # type:ignore[arg-type] - ) - - @classmethod - async def connect_tcp( - cls, host: str, port: int, local_address: IPSockAddrType | None = None - ) -> abc.SocketStream: - transport, protocol = cast( - tuple[asyncio.Transport, StreamProtocol], - await get_running_loop().create_connection( - StreamProtocol, host, port, local_addr=local_address - ), - ) - transport.pause_reading() - return SocketStream(transport, protocol) - - @classmethod - async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: - await cls.checkpoint() - loop = get_running_loop() - raw_socket = socket.socket(socket.AF_UNIX) - raw_socket.setblocking(False) - while True: - try: - raw_socket.connect(path) - except BlockingIOError: - f: asyncio.Future = asyncio.Future() - loop.add_writer(raw_socket, f.set_result, None) - f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) - await f - except BaseException: - raw_socket.close() - raise - else: - return UNIXSocketStream(raw_socket) - - @classmethod - def create_tcp_listener(cls, sock: socket.socket) -> SocketListener: - return TCPSocketListener(sock) - - @classmethod - def create_unix_listener(cls, sock: socket.socket) -> SocketListener: - return UNIXSocketListener(sock) - - @classmethod - async def create_udp_socket( - cls, - family: AddressFamily, - local_address: IPSockAddrType | None, - remote_address: IPSockAddrType | None, - reuse_port: bool, - ) -> UDPSocket | ConnectedUDPSocket: - transport, protocol = await get_running_loop().create_datagram_endpoint( - DatagramProtocol, - local_addr=local_address, - remote_addr=remote_address, - family=family, - reuse_port=reuse_port, - ) - if protocol.exception: - transport.close() - raise protocol.exception - - if not remote_address: - return UDPSocket(transport, protocol) - else: - return ConnectedUDPSocket(transport, protocol) - - @classmethod - async def create_unix_datagram_socket( # type: ignore[override] - cls, raw_socket: socket.socket, remote_path: str | bytes | None - ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: - await cls.checkpoint() - loop = get_running_loop() - - if remote_path: - while True: - try: - raw_socket.connect(remote_path) - except BlockingIOError: - f: asyncio.Future = asyncio.Future() - loop.add_writer(raw_socket, f.set_result, None) - f.add_done_callback(lambda _: loop.remove_writer(raw_socket)) - await f - except BaseException: - raw_socket.close() - raise - else: - return ConnectedUNIXDatagramSocket(raw_socket) - else: - return UNIXDatagramSocket(raw_socket) - - @classmethod - async def getaddrinfo( - cls, - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, - ) -> Sequence[ - tuple[ - AddressFamily, - SocketKind, - int, - str, - tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], - ] - ]: - return await get_running_loop().getaddrinfo( - host, port, family=family, type=type, proto=proto, flags=flags - ) - - @classmethod - async def getnameinfo( - cls, sockaddr: IPSockAddrType, flags: int = 0 - ) -> tuple[str, str]: - return await get_running_loop().getnameinfo(sockaddr, flags) - - @classmethod - async def wait_readable(cls, obj: FileDescriptorLike) -> None: - await cls.checkpoint() - try: - read_events = _read_events.get() - except LookupError: - read_events = {} - _read_events.set(read_events) - - if not isinstance(obj, int): - obj = obj.fileno() - - if read_events.get(obj): - raise BusyResourceError("reading from") - - loop = get_running_loop() - event = asyncio.Event() - try: - loop.add_reader(obj, event.set) - except NotImplementedError: - from anyio._core._asyncio_selector_thread import get_selector - - selector = get_selector() - selector.add_reader(obj, event.set) - remove_reader = selector.remove_reader - else: - remove_reader = loop.remove_reader - - read_events[obj] = event - try: - await event.wait() - finally: - remove_reader(obj) - del read_events[obj] - - @classmethod - async def wait_writable(cls, obj: FileDescriptorLike) -> None: - await cls.checkpoint() - try: - write_events = _write_events.get() - except LookupError: - write_events = {} - _write_events.set(write_events) - - if not isinstance(obj, int): - obj = obj.fileno() - - if write_events.get(obj): - raise BusyResourceError("writing to") - - loop = get_running_loop() - event = asyncio.Event() - try: - loop.add_writer(obj, event.set) - except NotImplementedError: - from anyio._core._asyncio_selector_thread import get_selector - - selector = get_selector() - selector.add_writer(obj, event.set) - remove_writer = selector.remove_writer - else: - remove_writer = loop.remove_writer - - write_events[obj] = event - try: - await event.wait() - finally: - del write_events[obj] - remove_writer(obj) - - @classmethod - def current_default_thread_limiter(cls) -> CapacityLimiter: - try: - return _default_thread_limiter.get() - except LookupError: - limiter = CapacityLimiter(40) - _default_thread_limiter.set(limiter) - return limiter - - @classmethod - def open_signal_receiver( - cls, *signals: Signals - ) -> AbstractContextManager[AsyncIterator[Signals]]: - return _SignalReceiver(signals) - - @classmethod - def get_current_task(cls) -> TaskInfo: - return AsyncIOTaskInfo(current_task()) # type: ignore[arg-type] - - @classmethod - def get_running_tasks(cls) -> Sequence[TaskInfo]: - return [AsyncIOTaskInfo(task) for task in all_tasks() if not task.done()] - - @classmethod - async def wait_all_tasks_blocked(cls) -> None: - await cls.checkpoint() - this_task = current_task() - while True: - for task in all_tasks(): - if task is this_task: - continue - - waiter = task._fut_waiter # type: ignore[attr-defined] - if waiter is None or waiter.done(): - await sleep(0.1) - break - else: - return - - @classmethod - def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: - return TestRunner(**options) - - -backend_class = AsyncIOBackend diff --git a/venv/lib/python3.12/site-packages/anyio/_backends/_trio.py b/venv/lib/python3.12/site-packages/anyio/_backends/_trio.py deleted file mode 100644 index b80cc04..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_backends/_trio.py +++ /dev/null @@ -1,1334 +0,0 @@ -from __future__ import annotations - -import array -import math -import os -import socket -import sys -import types -import weakref -from collections.abc import ( - AsyncGenerator, - AsyncIterator, - Awaitable, - Callable, - Collection, - Coroutine, - Iterable, - Sequence, -) -from concurrent.futures import Future -from contextlib import AbstractContextManager -from dataclasses import dataclass -from functools import partial -from io import IOBase -from os import PathLike -from signal import Signals -from socket import AddressFamily, SocketKind -from types import TracebackType -from typing import ( - IO, - TYPE_CHECKING, - Any, - Generic, - NoReturn, - TypeVar, - cast, - overload, -) - -import trio.from_thread -import trio.lowlevel -from outcome import Error, Outcome, Value -from trio.lowlevel import ( - current_root_task, - current_task, - wait_readable, - wait_writable, -) -from trio.socket import SocketType as TrioSocketType -from trio.to_thread import run_sync - -from .. import ( - CapacityLimiterStatistics, - EventStatistics, - LockStatistics, - TaskInfo, - WouldBlock, - abc, -) -from .._core._eventloop import claim_worker_thread -from .._core._exceptions import ( - BrokenResourceError, - BusyResourceError, - ClosedResourceError, - EndOfStream, -) -from .._core._sockets import convert_ipv6_sockaddr -from .._core._streams import create_memory_object_stream -from .._core._synchronization import ( - CapacityLimiter as BaseCapacityLimiter, -) -from .._core._synchronization import Event as BaseEvent -from .._core._synchronization import Lock as BaseLock -from .._core._synchronization import ( - ResourceGuard, - SemaphoreStatistics, -) -from .._core._synchronization import Semaphore as BaseSemaphore -from .._core._tasks import CancelScope as BaseCancelScope -from ..abc import IPSockAddrType, UDPPacketType, UNIXDatagramPacketType -from ..abc._eventloop import AsyncBackend, StrOrBytesPath -from ..streams.memory import MemoryObjectSendStream - -if TYPE_CHECKING: - from _typeshed import HasFileno - -if sys.version_info >= (3, 10): - from typing import ParamSpec -else: - from typing_extensions import ParamSpec - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from exceptiongroup import BaseExceptionGroup - from typing_extensions import TypeVarTuple, Unpack - -T = TypeVar("T") -T_Retval = TypeVar("T_Retval") -T_SockAddr = TypeVar("T_SockAddr", str, IPSockAddrType) -PosArgsT = TypeVarTuple("PosArgsT") -P = ParamSpec("P") - - -# -# Event loop -# - -RunVar = trio.lowlevel.RunVar - - -# -# Timeouts and cancellation -# - - -class CancelScope(BaseCancelScope): - def __new__( - cls, original: trio.CancelScope | None = None, **kwargs: object - ) -> CancelScope: - return object.__new__(cls) - - def __init__(self, original: trio.CancelScope | None = None, **kwargs: Any) -> None: - self.__original = original or trio.CancelScope(**kwargs) - - def __enter__(self) -> CancelScope: - self.__original.__enter__() - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - return self.__original.__exit__(exc_type, exc_val, exc_tb) - - def cancel(self) -> None: - self.__original.cancel() - - @property - def deadline(self) -> float: - return self.__original.deadline - - @deadline.setter - def deadline(self, value: float) -> None: - self.__original.deadline = value - - @property - def cancel_called(self) -> bool: - return self.__original.cancel_called - - @property - def cancelled_caught(self) -> bool: - return self.__original.cancelled_caught - - @property - def shield(self) -> bool: - return self.__original.shield - - @shield.setter - def shield(self, value: bool) -> None: - self.__original.shield = value - - -# -# Task groups -# - - -class TaskGroup(abc.TaskGroup): - def __init__(self) -> None: - self._active = False - self._nursery_manager = trio.open_nursery(strict_exception_groups=True) - self.cancel_scope = None # type: ignore[assignment] - - async def __aenter__(self) -> TaskGroup: - self._active = True - self._nursery = await self._nursery_manager.__aenter__() - self.cancel_scope = CancelScope(self._nursery.cancel_scope) - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - try: - # trio.Nursery.__exit__ returns bool; .open_nursery has wrong type - return await self._nursery_manager.__aexit__(exc_type, exc_val, exc_tb) # type: ignore[return-value] - except BaseExceptionGroup as exc: - if not exc.split(trio.Cancelled)[1]: - raise trio.Cancelled._create() from exc - - raise - finally: - del exc_val, exc_tb - self._active = False - - def start_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> None: - if not self._active: - raise RuntimeError( - "This task group is not active; no new tasks can be started." - ) - - self._nursery.start_soon(func, *args, name=name) - - async def start( - self, func: Callable[..., Awaitable[Any]], *args: object, name: object = None - ) -> Any: - if not self._active: - raise RuntimeError( - "This task group is not active; no new tasks can be started." - ) - - return await self._nursery.start(func, *args, name=name) - - -# -# Threads -# - - -class BlockingPortal(abc.BlockingPortal): - def __new__(cls) -> BlockingPortal: - return object.__new__(cls) - - def __init__(self) -> None: - super().__init__() - self._token = trio.lowlevel.current_trio_token() - - def _spawn_task_from_thread( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - name: object, - future: Future[T_Retval], - ) -> None: - trio.from_thread.run_sync( - partial(self._task_group.start_soon, name=name), - self._call_func, - func, - args, - kwargs, - future, - trio_token=self._token, - ) - - -# -# Subprocesses -# - - -@dataclass(eq=False) -class ReceiveStreamWrapper(abc.ByteReceiveStream): - _stream: trio.abc.ReceiveStream - - async def receive(self, max_bytes: int | None = None) -> bytes: - try: - data = await self._stream.receive_some(max_bytes) - except trio.ClosedResourceError as exc: - raise ClosedResourceError from exc.__cause__ - except trio.BrokenResourceError as exc: - raise BrokenResourceError from exc.__cause__ - - if data: - return data - else: - raise EndOfStream - - async def aclose(self) -> None: - await self._stream.aclose() - - -@dataclass(eq=False) -class SendStreamWrapper(abc.ByteSendStream): - _stream: trio.abc.SendStream - - async def send(self, item: bytes) -> None: - try: - await self._stream.send_all(item) - except trio.ClosedResourceError as exc: - raise ClosedResourceError from exc.__cause__ - except trio.BrokenResourceError as exc: - raise BrokenResourceError from exc.__cause__ - - async def aclose(self) -> None: - await self._stream.aclose() - - -@dataclass(eq=False) -class Process(abc.Process): - _process: trio.Process - _stdin: abc.ByteSendStream | None - _stdout: abc.ByteReceiveStream | None - _stderr: abc.ByteReceiveStream | None - - async def aclose(self) -> None: - with CancelScope(shield=True): - if self._stdin: - await self._stdin.aclose() - if self._stdout: - await self._stdout.aclose() - if self._stderr: - await self._stderr.aclose() - - try: - await self.wait() - except BaseException: - self.kill() - with CancelScope(shield=True): - await self.wait() - raise - - async def wait(self) -> int: - return await self._process.wait() - - def terminate(self) -> None: - self._process.terminate() - - def kill(self) -> None: - self._process.kill() - - def send_signal(self, signal: Signals) -> None: - self._process.send_signal(signal) - - @property - def pid(self) -> int: - return self._process.pid - - @property - def returncode(self) -> int | None: - return self._process.returncode - - @property - def stdin(self) -> abc.ByteSendStream | None: - return self._stdin - - @property - def stdout(self) -> abc.ByteReceiveStream | None: - return self._stdout - - @property - def stderr(self) -> abc.ByteReceiveStream | None: - return self._stderr - - -class _ProcessPoolShutdownInstrument(trio.abc.Instrument): - def after_run(self) -> None: - super().after_run() - - -current_default_worker_process_limiter: trio.lowlevel.RunVar = RunVar( - "current_default_worker_process_limiter" -) - - -async def _shutdown_process_pool(workers: set[abc.Process]) -> None: - try: - await trio.sleep(math.inf) - except trio.Cancelled: - for process in workers: - if process.returncode is None: - process.kill() - - with CancelScope(shield=True): - for process in workers: - await process.aclose() - - -# -# Sockets and networking -# - - -class _TrioSocketMixin(Generic[T_SockAddr]): - def __init__(self, trio_socket: TrioSocketType) -> None: - self._trio_socket = trio_socket - self._closed = False - - def _check_closed(self) -> None: - if self._closed: - raise ClosedResourceError - if self._trio_socket.fileno() < 0: - raise BrokenResourceError - - @property - def _raw_socket(self) -> socket.socket: - return self._trio_socket._sock # type: ignore[attr-defined] - - async def aclose(self) -> None: - if self._trio_socket.fileno() >= 0: - self._closed = True - self._trio_socket.close() - - def _convert_socket_error(self, exc: BaseException) -> NoReturn: - if isinstance(exc, trio.ClosedResourceError): - raise ClosedResourceError from exc - elif self._trio_socket.fileno() < 0 and self._closed: - raise ClosedResourceError from None - elif isinstance(exc, OSError): - raise BrokenResourceError from exc - else: - raise exc - - -class SocketStream(_TrioSocketMixin, abc.SocketStream): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self, max_bytes: int = 65536) -> bytes: - with self._receive_guard: - try: - data = await self._trio_socket.recv(max_bytes) - except BaseException as exc: - self._convert_socket_error(exc) - - if data: - return data - else: - raise EndOfStream - - async def send(self, item: bytes) -> None: - with self._send_guard: - view = memoryview(item) - while view: - try: - bytes_sent = await self._trio_socket.send(view) - except BaseException as exc: - self._convert_socket_error(exc) - - view = view[bytes_sent:] - - async def send_eof(self) -> None: - self._trio_socket.shutdown(socket.SHUT_WR) - - -class UNIXSocketStream(SocketStream, abc.UNIXSocketStream): - async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: - if not isinstance(msglen, int) or msglen < 0: - raise ValueError("msglen must be a non-negative integer") - if not isinstance(maxfds, int) or maxfds < 1: - raise ValueError("maxfds must be a positive integer") - - fds = array.array("i") - await trio.lowlevel.checkpoint() - with self._receive_guard: - while True: - try: - message, ancdata, flags, addr = await self._trio_socket.recvmsg( - msglen, socket.CMSG_LEN(maxfds * fds.itemsize) - ) - except BaseException as exc: - self._convert_socket_error(exc) - else: - if not message and not ancdata: - raise EndOfStream - - break - - for cmsg_level, cmsg_type, cmsg_data in ancdata: - if cmsg_level != socket.SOL_SOCKET or cmsg_type != socket.SCM_RIGHTS: - raise RuntimeError( - f"Received unexpected ancillary data; message = {message!r}, " - f"cmsg_level = {cmsg_level}, cmsg_type = {cmsg_type}" - ) - - fds.frombytes(cmsg_data[: len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) - - return message, list(fds) - - async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: - if not message: - raise ValueError("message must not be empty") - if not fds: - raise ValueError("fds must not be empty") - - filenos: list[int] = [] - for fd in fds: - if isinstance(fd, int): - filenos.append(fd) - elif isinstance(fd, IOBase): - filenos.append(fd.fileno()) - - fdarray = array.array("i", filenos) - await trio.lowlevel.checkpoint() - with self._send_guard: - while True: - try: - await self._trio_socket.sendmsg( - [message], - [ - ( - socket.SOL_SOCKET, - socket.SCM_RIGHTS, - fdarray, - ) - ], - ) - break - except BaseException as exc: - self._convert_socket_error(exc) - - -class TCPSocketListener(_TrioSocketMixin, abc.SocketListener): - def __init__(self, raw_socket: socket.socket): - super().__init__(trio.socket.from_stdlib_socket(raw_socket)) - self._accept_guard = ResourceGuard("accepting connections from") - - async def accept(self) -> SocketStream: - with self._accept_guard: - try: - trio_socket, _addr = await self._trio_socket.accept() - except BaseException as exc: - self._convert_socket_error(exc) - - trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - return SocketStream(trio_socket) - - -class UNIXSocketListener(_TrioSocketMixin, abc.SocketListener): - def __init__(self, raw_socket: socket.socket): - super().__init__(trio.socket.from_stdlib_socket(raw_socket)) - self._accept_guard = ResourceGuard("accepting connections from") - - async def accept(self) -> UNIXSocketStream: - with self._accept_guard: - try: - trio_socket, _addr = await self._trio_socket.accept() - except BaseException as exc: - self._convert_socket_error(exc) - - return UNIXSocketStream(trio_socket) - - -class UDPSocket(_TrioSocketMixin[IPSockAddrType], abc.UDPSocket): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> tuple[bytes, IPSockAddrType]: - with self._receive_guard: - try: - data, addr = await self._trio_socket.recvfrom(65536) - return data, convert_ipv6_sockaddr(addr) - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: UDPPacketType) -> None: - with self._send_guard: - try: - await self._trio_socket.sendto(*item) - except BaseException as exc: - self._convert_socket_error(exc) - - -class ConnectedUDPSocket(_TrioSocketMixin[IPSockAddrType], abc.ConnectedUDPSocket): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> bytes: - with self._receive_guard: - try: - return await self._trio_socket.recv(65536) - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: bytes) -> None: - with self._send_guard: - try: - await self._trio_socket.send(item) - except BaseException as exc: - self._convert_socket_error(exc) - - -class UNIXDatagramSocket(_TrioSocketMixin[str], abc.UNIXDatagramSocket): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> UNIXDatagramPacketType: - with self._receive_guard: - try: - data, addr = await self._trio_socket.recvfrom(65536) - return data, addr - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: UNIXDatagramPacketType) -> None: - with self._send_guard: - try: - await self._trio_socket.sendto(*item) - except BaseException as exc: - self._convert_socket_error(exc) - - -class ConnectedUNIXDatagramSocket( - _TrioSocketMixin[str], abc.ConnectedUNIXDatagramSocket -): - def __init__(self, trio_socket: TrioSocketType) -> None: - super().__init__(trio_socket) - self._receive_guard = ResourceGuard("reading from") - self._send_guard = ResourceGuard("writing to") - - async def receive(self) -> bytes: - with self._receive_guard: - try: - return await self._trio_socket.recv(65536) - except BaseException as exc: - self._convert_socket_error(exc) - - async def send(self, item: bytes) -> None: - with self._send_guard: - try: - await self._trio_socket.send(item) - except BaseException as exc: - self._convert_socket_error(exc) - - -# -# Synchronization -# - - -class Event(BaseEvent): - def __new__(cls) -> Event: - return object.__new__(cls) - - def __init__(self) -> None: - self.__original = trio.Event() - - def is_set(self) -> bool: - return self.__original.is_set() - - async def wait(self) -> None: - return await self.__original.wait() - - def statistics(self) -> EventStatistics: - orig_statistics = self.__original.statistics() - return EventStatistics(tasks_waiting=orig_statistics.tasks_waiting) - - def set(self) -> None: - self.__original.set() - - -class Lock(BaseLock): - def __new__(cls, *, fast_acquire: bool = False) -> Lock: - return object.__new__(cls) - - def __init__(self, *, fast_acquire: bool = False) -> None: - self._fast_acquire = fast_acquire - self.__original = trio.Lock() - - @staticmethod - def _convert_runtime_error_msg(exc: RuntimeError) -> None: - if exc.args == ("attempt to re-acquire an already held Lock",): - exc.args = ("Attempted to acquire an already held Lock",) - - async def acquire(self) -> None: - if not self._fast_acquire: - try: - await self.__original.acquire() - except RuntimeError as exc: - self._convert_runtime_error_msg(exc) - raise - - return - - # This is the "fast path" where we don't let other tasks run - await trio.lowlevel.checkpoint_if_cancelled() - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - await self.__original._lot.park() - except RuntimeError as exc: - self._convert_runtime_error_msg(exc) - raise - - def acquire_nowait(self) -> None: - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - raise WouldBlock from None - except RuntimeError as exc: - self._convert_runtime_error_msg(exc) - raise - - def locked(self) -> bool: - return self.__original.locked() - - def release(self) -> None: - self.__original.release() - - def statistics(self) -> LockStatistics: - orig_statistics = self.__original.statistics() - owner = TrioTaskInfo(orig_statistics.owner) if orig_statistics.owner else None - return LockStatistics( - orig_statistics.locked, owner, orig_statistics.tasks_waiting - ) - - -class Semaphore(BaseSemaphore): - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - return object.__new__(cls) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> None: - super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) - self.__original = trio.Semaphore(initial_value, max_value=max_value) - - async def acquire(self) -> None: - if not self._fast_acquire: - await self.__original.acquire() - return - - # This is the "fast path" where we don't let other tasks run - await trio.lowlevel.checkpoint_if_cancelled() - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - await self.__original._lot.park() - - def acquire_nowait(self) -> None: - try: - self.__original.acquire_nowait() - except trio.WouldBlock: - raise WouldBlock from None - - @property - def max_value(self) -> int | None: - return self.__original.max_value - - @property - def value(self) -> int: - return self.__original.value - - def release(self) -> None: - self.__original.release() - - def statistics(self) -> SemaphoreStatistics: - orig_statistics = self.__original.statistics() - return SemaphoreStatistics(orig_statistics.tasks_waiting) - - -class CapacityLimiter(BaseCapacityLimiter): - def __new__( - cls, - total_tokens: float | None = None, - *, - original: trio.CapacityLimiter | None = None, - ) -> CapacityLimiter: - return object.__new__(cls) - - def __init__( - self, - total_tokens: float | None = None, - *, - original: trio.CapacityLimiter | None = None, - ) -> None: - if original is not None: - self.__original = original - else: - assert total_tokens is not None - self.__original = trio.CapacityLimiter(total_tokens) - - async def __aenter__(self) -> None: - return await self.__original.__aenter__() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - await self.__original.__aexit__(exc_type, exc_val, exc_tb) - - @property - def total_tokens(self) -> float: - return self.__original.total_tokens - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - self.__original.total_tokens = value - - @property - def borrowed_tokens(self) -> int: - return self.__original.borrowed_tokens - - @property - def available_tokens(self) -> float: - return self.__original.available_tokens - - def acquire_nowait(self) -> None: - self.__original.acquire_nowait() - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - self.__original.acquire_on_behalf_of_nowait(borrower) - - async def acquire(self) -> None: - await self.__original.acquire() - - async def acquire_on_behalf_of(self, borrower: object) -> None: - await self.__original.acquire_on_behalf_of(borrower) - - def release(self) -> None: - return self.__original.release() - - def release_on_behalf_of(self, borrower: object) -> None: - return self.__original.release_on_behalf_of(borrower) - - def statistics(self) -> CapacityLimiterStatistics: - orig = self.__original.statistics() - return CapacityLimiterStatistics( - borrowed_tokens=orig.borrowed_tokens, - total_tokens=orig.total_tokens, - borrowers=tuple(orig.borrowers), - tasks_waiting=orig.tasks_waiting, - ) - - -_capacity_limiter_wrapper: trio.lowlevel.RunVar = RunVar("_capacity_limiter_wrapper") - - -# -# Signal handling -# - - -class _SignalReceiver: - _iterator: AsyncIterator[int] - - def __init__(self, signals: tuple[Signals, ...]): - self._signals = signals - - def __enter__(self) -> _SignalReceiver: - self._cm = trio.open_signal_receiver(*self._signals) - self._iterator = self._cm.__enter__() - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - return self._cm.__exit__(exc_type, exc_val, exc_tb) - - def __aiter__(self) -> _SignalReceiver: - return self - - async def __anext__(self) -> Signals: - signum = await self._iterator.__anext__() - return Signals(signum) - - -# -# Testing and debugging -# - - -class TestRunner(abc.TestRunner): - def __init__(self, **options: Any) -> None: - from queue import Queue - - self._call_queue: Queue[Callable[[], object]] = Queue() - self._send_stream: MemoryObjectSendStream | None = None - self._options = options - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: types.TracebackType | None, - ) -> None: - if self._send_stream: - self._send_stream.close() - while self._send_stream is not None: - self._call_queue.get()() - - async def _run_tests_and_fixtures(self) -> None: - self._send_stream, receive_stream = create_memory_object_stream(1) - with receive_stream: - async for coro, outcome_holder in receive_stream: - try: - retval = await coro - except BaseException as exc: - outcome_holder.append(Error(exc)) - else: - outcome_holder.append(Value(retval)) - - def _main_task_finished(self, outcome: object) -> None: - self._send_stream = None - - def _call_in_runner_task( - self, - func: Callable[P, Awaitable[T_Retval]], - *args: P.args, - **kwargs: P.kwargs, - ) -> T_Retval: - if self._send_stream is None: - trio.lowlevel.start_guest_run( - self._run_tests_and_fixtures, - run_sync_soon_threadsafe=self._call_queue.put, - done_callback=self._main_task_finished, - **self._options, - ) - while self._send_stream is None: - self._call_queue.get()() - - outcome_holder: list[Outcome] = [] - self._send_stream.send_nowait((func(*args, **kwargs), outcome_holder)) - while not outcome_holder: - self._call_queue.get()() - - return outcome_holder[0].unwrap() - - def run_asyncgen_fixture( - self, - fixture_func: Callable[..., AsyncGenerator[T_Retval, Any]], - kwargs: dict[str, Any], - ) -> Iterable[T_Retval]: - asyncgen = fixture_func(**kwargs) - fixturevalue: T_Retval = self._call_in_runner_task(asyncgen.asend, None) - - yield fixturevalue - - try: - self._call_in_runner_task(asyncgen.asend, None) - except StopAsyncIteration: - pass - else: - self._call_in_runner_task(asyncgen.aclose) - raise RuntimeError("Async generator fixture did not stop") - - def run_fixture( - self, - fixture_func: Callable[..., Coroutine[Any, Any, T_Retval]], - kwargs: dict[str, Any], - ) -> T_Retval: - return self._call_in_runner_task(fixture_func, **kwargs) - - def run_test( - self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] - ) -> None: - self._call_in_runner_task(test_func, **kwargs) - - -class TrioTaskInfo(TaskInfo): - def __init__(self, task: trio.lowlevel.Task): - parent_id = None - if task.parent_nursery and task.parent_nursery.parent_task: - parent_id = id(task.parent_nursery.parent_task) - - super().__init__(id(task), parent_id, task.name, task.coro) - self._task = weakref.proxy(task) - - def has_pending_cancellation(self) -> bool: - try: - return self._task._cancel_status.effectively_cancelled - except ReferenceError: - # If the task is no longer around, it surely doesn't have a cancellation - # pending - return False - - -class TrioBackend(AsyncBackend): - @classmethod - def run( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - options: dict[str, Any], - ) -> T_Retval: - return trio.run(func, *args) - - @classmethod - def current_token(cls) -> object: - return trio.lowlevel.current_trio_token() - - @classmethod - def current_time(cls) -> float: - return trio.current_time() - - @classmethod - def cancelled_exception_class(cls) -> type[BaseException]: - return trio.Cancelled - - @classmethod - async def checkpoint(cls) -> None: - await trio.lowlevel.checkpoint() - - @classmethod - async def checkpoint_if_cancelled(cls) -> None: - await trio.lowlevel.checkpoint_if_cancelled() - - @classmethod - async def cancel_shielded_checkpoint(cls) -> None: - await trio.lowlevel.cancel_shielded_checkpoint() - - @classmethod - async def sleep(cls, delay: float) -> None: - await trio.sleep(delay) - - @classmethod - def create_cancel_scope( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> abc.CancelScope: - return CancelScope(deadline=deadline, shield=shield) - - @classmethod - def current_effective_deadline(cls) -> float: - return trio.current_effective_deadline() - - @classmethod - def create_task_group(cls) -> abc.TaskGroup: - return TaskGroup() - - @classmethod - def create_event(cls) -> abc.Event: - return Event() - - @classmethod - def create_lock(cls, *, fast_acquire: bool) -> Lock: - return Lock(fast_acquire=fast_acquire) - - @classmethod - def create_semaphore( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> abc.Semaphore: - return Semaphore(initial_value, max_value=max_value, fast_acquire=fast_acquire) - - @classmethod - def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: - return CapacityLimiter(total_tokens) - - @classmethod - async def run_sync_in_worker_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - abandon_on_cancel: bool = False, - limiter: abc.CapacityLimiter | None = None, - ) -> T_Retval: - def wrapper() -> T_Retval: - with claim_worker_thread(TrioBackend, token): - return func(*args) - - token = TrioBackend.current_token() - return await run_sync( - wrapper, - abandon_on_cancel=abandon_on_cancel, - limiter=cast(trio.CapacityLimiter, limiter), - ) - - @classmethod - def check_cancelled(cls) -> None: - trio.from_thread.check_cancelled() - - @classmethod - def run_async_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - return trio.from_thread.run(func, *args) - - @classmethod - def run_sync_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - return trio.from_thread.run_sync(func, *args) - - @classmethod - def create_blocking_portal(cls) -> abc.BlockingPortal: - return BlockingPortal() - - @classmethod - async def open_process( - cls, - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None, - stdout: int | IO[Any] | None, - stderr: int | IO[Any] | None, - **kwargs: Any, - ) -> Process: - def convert_item(item: StrOrBytesPath) -> str: - str_or_bytes = os.fspath(item) - if isinstance(str_or_bytes, str): - return str_or_bytes - else: - return os.fsdecode(str_or_bytes) - - if isinstance(command, (str, bytes, PathLike)): - process = await trio.lowlevel.open_process( - convert_item(command), - stdin=stdin, - stdout=stdout, - stderr=stderr, - shell=True, - **kwargs, - ) - else: - process = await trio.lowlevel.open_process( - [convert_item(item) for item in command], - stdin=stdin, - stdout=stdout, - stderr=stderr, - shell=False, - **kwargs, - ) - - stdin_stream = SendStreamWrapper(process.stdin) if process.stdin else None - stdout_stream = ReceiveStreamWrapper(process.stdout) if process.stdout else None - stderr_stream = ReceiveStreamWrapper(process.stderr) if process.stderr else None - return Process(process, stdin_stream, stdout_stream, stderr_stream) - - @classmethod - def setup_process_pool_exit_at_shutdown(cls, workers: set[abc.Process]) -> None: - trio.lowlevel.spawn_system_task(_shutdown_process_pool, workers) - - @classmethod - async def connect_tcp( - cls, host: str, port: int, local_address: IPSockAddrType | None = None - ) -> SocketStream: - family = socket.AF_INET6 if ":" in host else socket.AF_INET - trio_socket = trio.socket.socket(family) - trio_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - if local_address: - await trio_socket.bind(local_address) - - try: - await trio_socket.connect((host, port)) - except BaseException: - trio_socket.close() - raise - - return SocketStream(trio_socket) - - @classmethod - async def connect_unix(cls, path: str | bytes) -> abc.UNIXSocketStream: - trio_socket = trio.socket.socket(socket.AF_UNIX) - try: - await trio_socket.connect(path) - except BaseException: - trio_socket.close() - raise - - return UNIXSocketStream(trio_socket) - - @classmethod - def create_tcp_listener(cls, sock: socket.socket) -> abc.SocketListener: - return TCPSocketListener(sock) - - @classmethod - def create_unix_listener(cls, sock: socket.socket) -> abc.SocketListener: - return UNIXSocketListener(sock) - - @classmethod - async def create_udp_socket( - cls, - family: socket.AddressFamily, - local_address: IPSockAddrType | None, - remote_address: IPSockAddrType | None, - reuse_port: bool, - ) -> UDPSocket | ConnectedUDPSocket: - trio_socket = trio.socket.socket(family=family, type=socket.SOCK_DGRAM) - - if reuse_port: - trio_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) - - if local_address: - await trio_socket.bind(local_address) - - if remote_address: - await trio_socket.connect(remote_address) - return ConnectedUDPSocket(trio_socket) - else: - return UDPSocket(trio_socket) - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket.socket, remote_path: None - ) -> abc.UNIXDatagramSocket: ... - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket.socket, remote_path: str | bytes - ) -> abc.ConnectedUNIXDatagramSocket: ... - - @classmethod - async def create_unix_datagram_socket( - cls, raw_socket: socket.socket, remote_path: str | bytes | None - ) -> abc.UNIXDatagramSocket | abc.ConnectedUNIXDatagramSocket: - trio_socket = trio.socket.from_stdlib_socket(raw_socket) - - if remote_path: - await trio_socket.connect(remote_path) - return ConnectedUNIXDatagramSocket(trio_socket) - else: - return UNIXDatagramSocket(trio_socket) - - @classmethod - async def getaddrinfo( - cls, - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, - ) -> Sequence[ - tuple[ - AddressFamily, - SocketKind, - int, - str, - tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], - ] - ]: - return await trio.socket.getaddrinfo(host, port, family, type, proto, flags) - - @classmethod - async def getnameinfo( - cls, sockaddr: IPSockAddrType, flags: int = 0 - ) -> tuple[str, str]: - return await trio.socket.getnameinfo(sockaddr, flags) - - @classmethod - async def wait_readable(cls, obj: HasFileno | int) -> None: - try: - await wait_readable(obj) - except trio.ClosedResourceError as exc: - raise ClosedResourceError().with_traceback(exc.__traceback__) from None - except trio.BusyResourceError: - raise BusyResourceError("reading from") from None - - @classmethod - async def wait_writable(cls, obj: HasFileno | int) -> None: - try: - await wait_writable(obj) - except trio.ClosedResourceError as exc: - raise ClosedResourceError().with_traceback(exc.__traceback__) from None - except trio.BusyResourceError: - raise BusyResourceError("writing to") from None - - @classmethod - def current_default_thread_limiter(cls) -> CapacityLimiter: - try: - return _capacity_limiter_wrapper.get() - except LookupError: - limiter = CapacityLimiter( - original=trio.to_thread.current_default_thread_limiter() - ) - _capacity_limiter_wrapper.set(limiter) - return limiter - - @classmethod - def open_signal_receiver( - cls, *signals: Signals - ) -> AbstractContextManager[AsyncIterator[Signals]]: - return _SignalReceiver(signals) - - @classmethod - def get_current_task(cls) -> TaskInfo: - task = current_task() - return TrioTaskInfo(task) - - @classmethod - def get_running_tasks(cls) -> Sequence[TaskInfo]: - root_task = current_root_task() - assert root_task - task_infos = [TrioTaskInfo(root_task)] - nurseries = root_task.child_nurseries - while nurseries: - new_nurseries: list[trio.Nursery] = [] - for nursery in nurseries: - for task in nursery.child_tasks: - task_infos.append(TrioTaskInfo(task)) - new_nurseries.extend(task.child_nurseries) - - nurseries = new_nurseries - - return task_infos - - @classmethod - async def wait_all_tasks_blocked(cls) -> None: - from trio.testing import wait_all_tasks_blocked - - await wait_all_tasks_blocked() - - @classmethod - def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: - return TestRunner(**options) - - -backend_class = TrioBackend diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__init__.py b/venv/lib/python3.12/site-packages/anyio/_core/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 23abd8eb28878777a42787041c90d862294c37c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 181 zcmX@j%ge<81nM7Or-SInAOanHW&w&!XQ*V*Wb|9fP{ah}eFmxd6{4S!pPQJXUz}Nzs#}nloSm4STCAU# zSDBfwAD^6Gl&T*epP83g5+AQuQ2C3)CO1E&G$+-rh!toFBM=vZ7$2D#85xV1fh+)r CPA?Du diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_asyncio_selector_thread.cpython-312.pyc deleted file mode 100644 index 30a1c5d717e46f42dc89e1d40d3a9fdfb2e15c78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8412 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 scB_8A`F8V@%9d;8OM#Ya&be=)hl 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 diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_exceptions.cpython-312.pyc deleted file mode 100644 index 00498e97b27d23a599e35acb55844c211a4e2abc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6053 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 diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_fileio.cpython-312.pyc deleted file mode 100644 index 5bdad0c764701fa15e68d8ac805f2d98417e4c3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41612 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 diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_signals.cpython-312.pyc deleted file mode 100644 index b97dbcfd5a80bf9beea3f0b686a1451366f02a7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1266 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 diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_streams.cpython-312.pyc deleted file mode 100644 index 648beebbc0ae7561dc9163646774fb1f7e12d983..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2329 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 rfl*|vk%3LfS2F`!kgZk*wjo#T3OZuT- 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 diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_tasks.cpython-312.pyc deleted file mode 100644 index dacc46be8fd0e93e75ae83c348c5fd3fd5883dca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6986 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 N(Yu=y(m{Tv{{b(~nNa`$ diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_tempfile.cpython-312.pyc deleted file mode 100644 index 19ddfc05e987c99c697641b82716b33938b58c33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28133 zcmeHwYj9l0b>_YE9?W3ye!nh3yoMkFz8p~$DG{Vdk&*?`A{5DxrQvYyfE;oL1K$~l z1VlTG#I*^p90^ezN@cIaJk}9cQmjpFIZh>;ES*g%yPI+Wf)h-Q5}w{0|NCU-vy$`=^kF;> z0mw_u7D>7+sgf#3rIT6@v{x=z#44Qs@1SLIStT2Un+&^NM(#YGZCZJ#`_rjcOBe>r}hc=8Lw`jcT{r zf_K-H#ozNj)y^-cJ;Cwucruub#K#lE_;wvhhPB{{XxMK_JNHi|!-*pgrOQXc=aNSr zdQ=NeOoTPWDj(5;q40@d=*-B}MA&bK$LEh83>-Lo@W2B{hVM&ThsLMU4mih>TH1ME zcs#5{LTOk0sjwD}2i5n{IVp2@G9E~t(!xQNK86xgp>Q-BR{gfL@1cqC`2NUvP@8%%u7=ZI`lbT%m+xUc92*O3>550SNHU!D z2mEc2+Y4IBtJ+lix8!`^Vqa>x>bU4M zdy*p`lj>VHo(k2Oizh!XwNiDhvpiL*`=WEyp;oJ9=n2kzJZ|uc>Vdy&%H^-6R*y}@ zHPD$FCHU9i$T9`b(6|z$raGm?$K#U;C22%c#t=_Qo(d+FNJ0rtCgU-5tWYo-ol-(* zJlBeS1y$L0eM1g{usvM_UQ27V)YJFT8 zn;Z`jcOXM0$Y`nCpVZ=$sEO#jo4HoVCKG5vvlL~#d{ zhsM$J7&DM3aUg2M1f)(R+7b!#vKkMcjYh^ngac@8EgnrMr{ZUo$?*sVjzlo3=-~-L zptEu9OhW04ugHb5n^_TA^J|m+_g>!0;bLDVCgYE=ZY1$>muBD6LKetrbzUHgekGdfJiZ6=K&v_fZkW&A$GPi?op<6(UpwNIv)QBI80QVzd zf~deGuWPzwd(NF|>cq>JYE6mnf^qlgh^{ni-42QD*m{svnLxuc10N;?;Dj?9C&6q_~JX81@ zyqk?G!Iwpd94~>kolt{!Pj4z@=U|vt34y@Co@gBFki^{pMBE@Dp-%VF1?e{q zFV=3FuiccYti9}>b<@i?>!VlsY&pHWvtD|6W<5DC*Q_hm&~o|d*{5$-x$Arv1nXY4 zX+*BHOPd@I&?-r*z^B#-=c7K9YUb48$eM?qPZP`yGkFV^K?Lr5|!uK)**}hsyrmwu517l%I#0+>VjoP00@RTFP#Ql_?)Jg1&^`REo2%Q^8~uT zow~mmPAp85v?Cab#uH(XjhYpc#ko)*37I18Cg`bPbP{0FkTw!jP?{SA<=jNMb3Bqa ztRx%<#F1c0fx~3WcqI_T*FNuSU-Wg)`??o=y^F5iw_UxYxA;r`~(R{Pl$e7g|s{}rma|)^6ioQcTF;sIO^nI+62t>Dqq_Ahoy%4%B;WrhJj3*$-U@I|x8(|0 zs8PQBb$c>TJG5|eQX5a(h+g27!&I9FIGA_#QYo6LS3JHym{SrUG@b#~x8reT(HJ z?E`5cgtlR&7NQoqK%s@GOIHtrFV(!^FL)l)0E>5pstDp#2&F$0g#<}lg?b3(Y$SO~ zR~tMPNkm8prZSS?XNbv4Vk&_W4=6{HB)TP5Dkr$AyGaqT`}misax9*$q)U#ng48Ue zjSvDpD<9$~PDASC5($K?aM_)sjbKSOPqhPWgC=x?ztB|V>j8eDsUXE*p?WP(Q=x{V z;Usi9kDdynuS2~;x+3z*cKx%b!ceTSx{#NFY94~yrs~kOVj}lId_2IJ?N<7P9#A3W zLBD^sf&&9I%fLsQ{|M#8Pi-*Q7Qfl%=z4ayc3hgHj&FCe4J^JT?_7opjo zf>`3W4g1~epuhGg@@3**wY-m#O7HWsj~c>nO*;du!%d{E7|zpP(pO@I3Oy61g-<}T zw}3tISvXLOv`ckOP>Dbt0#yh!9`svNFMu00WqoC&9=TaBc`Ft@E%Tn1m(ITJ=}8Uj zy>##MpPl*aT+^nvz5N-h3*xW6*079L(KES1pld%G}!hRI&%iq2aAiTxMn@=N$eLtzZoj zmun#|Z(d7WPBk=VYRVzU);Y|zW1a5e6@)94dWMU*sj`W6bd^E1#7ikwX2TxZ1Yn} zwIfeZc79@fit5VQ@?R+=Z-Cgn{?c{wwno{-iczP!kzvn8@2E@N$fC9z?{bLTWnmAD zMSK@+h8}m+3!{-9j$d&Rra$=V<*!P7`P4p!tAMFO^)p-zxKiE3a1G!p9j*mj9j-Y| ztJ8u9+b#VZzYaL-)XfanBYwTQMIGR;281+(9qJ&=Ub1CtgwIx(xa9b#+cDprx81xI(5kJOiu&6pBAz~L* zNWk(y!}dKC0kLq5_JT=d$DXg52GUX_apo2*Bnm7dOhkFwkj+YL5+()F$eAz~d8H-9 zZe1^s)ie~V^l{c#Bqk?dA%be;Y7H3gSu(p(vibwAUe>q+m4*cd+YexY911Hz1>5~m zG7w@pFd#9}#HLjQ21%DoNBhab9VC#6}~YNs!u!~Yv{h`%W z?pvvzK=%+^($4|-hP>LQbfN|N9xV3?pVNA?<@y`lg1ZBenV%Wh*L)otx<=@lTiJfQ zb{Z+u*1*_A+Rkc1Z4w^ZU2ybGf9)y2Ea59U^(k<=r6|9OE%6;hd$L3l@;!F)pFjV# z^C@rT^M_{+KR-M({6lYR%3J-OuV&`t%=iL!v|a6QyV{o%yup9xkWKy*dB|e>j}Ab2 zHZdkOUjy=0Y1w=0v_uM%l0dINXV4;=JS8F2WJ)9K)+w!#P?)wQVG*n)33M52hpg&G zC==3-02>mQAhZbFO@!VFJZvJ6@>D#(=WBaj+WG3Pmv_Co_vO9cyyvx%?>u?+$+uhX z0=cjIs-KU|#Qt@B(be|0t8F0XUD~G%`I)bHG;QWEdeq zH3jd&hlr%gFeWks5U)sg{*ruNF4m=0OLkmJnkHPuY=C%uYb|Z&gfgJC;z1eAvC;5@ znV5VUqio@0u#HiUmF$Cb)I|#(Bb{z3G6ZXp1~!(m4UcF#m=yXLOSsKmP9(ZkJam)UB{MH`0Af`pAYp6@;y*m*O zpJ7uXjk;#q&XY*mM#l2m6nwDp&_MwXVQI-@i=jRI5(1`+uLX>9?xRu>^XQ|C==IdW z8(P@RuBz^G<80$4N6O`U-ZSHQVdy#EyG@;oP5tvt{qJ}WK*iWhD#lvUI=i40!0>c> z=JZSTueQA0^3673S2O48rR3fj@7H}9H{yPTi0;1SL>DrCcBp)Ry?m`w-d}CIR@G1N z9(jMQ?b_aYz~8Tx;pVXsbw`X{^3nhREE9?{P%&mXCM+01F&;P^Vyh|Jy1L@=D?nRf zpb#k@B$|=g+Xd-5s(Wtc-1EOO^DA?%b}?h+vMI_bSpGi%SYyW8lBC%D7)(%vX^LvH zPn#@mU?8?MSnrsWbQ%6LuoI<4Q8u(N54KPIC9s{tG}6*%HjV1cw9}p?h$gqIR?+=z zB!-FEjcTD7(;G#cZYs_y=)#{PQr?d^d6V0_)&7O*{zY&9oVPz!({Op$?5@juXZK#I zU8w1q^Y*+~*F5{^>=&+dE!6ccR`jBGWt>v^X6jUxealN5fbQAmp+@=N$V0WZSGEDV zRv{17+pbmG39gsnhW(!iEUyLatTyPiQNd`sQ3Pl`-1JzpQ-?dFC-Ql?Z)AUZNeYH5g>`?PU;y$@18P7JXn3 zBdjQM>|C8WunYm&>HLDA{4{Eox8(aZc$6BJ^^`Q{CXOK9T70os(=}fM+M9eaU)Q}V zThtR@-gF<#tFjUl2XFX}v{EHR-IhQ{>TWr#23mS!t$CRMH2cI=&i-FraTR_`n zd0p=lc{2u%+K2^JHoWMpv1|2NL;F=!iQ592Be9~7kBue5$+Uy4qeA-PiYNeepRPQh zG$mG7BsV-wZ8D5FYt16Ox~hMzexYXToOi3SzUp}mgVnahifwbQZP|9&zMR+qlvrUk z(^OJ#du0cpYgJfP*{)UF32v0({!5?cwez4tiAjWlO0)}UE1sctxp$rI^5Q*n-cG$q zUVL(~V&j}^W41NAmbIVHsUwd^Zi~=?lR`L56TpnAf#l07AJoC7A*hn>iRNL7Mx- z`cM}@pMgh-g*i+AFHjvweQe8Q(COCDG8X1yL8mPS zh4bXNq(PYqC$Y~7i&?ST#53gX9L1d$9Tv1^oOO@Cy4)usl*73>M3GD91$MhXr zii@)5#tufv{{7*}@nj?xK1c_hcN>JjX?xrqF-3=%*_s_?Cz8-P-bgSC9Ry5=&3X>| zSFCu5x3n*lL)r^{s^#S;9X(3mD7{#Q=FhWhapX6MDMCOfCR*6CRMwJ~K2MQR*L3-@ z*~czFIs4?5p@q7hONUa`^_Tl+`(NC$=WESv&fS>K&8vLec6Ayqo}Bqjc^sDS@Iw|aqtc*nwlab#yZNQ{aYZ(Er#}c@K`hd zH<70lrgDd=vuh4hK^TW5lEkOn(4W$XC2$8}vZ0RyKfN)Fv))bDn7~AZ@4CsW zEO+6b(x^l|dF80|ZSwtXa(LG;e@I$a=l=s5m&SlWAD8M&k4uYnee-pFuhlKo4X!dW z&DZt5W?!fqSgaVBa}DGVO@qtY?@(dGaQw9_!z>rw*fflAV-)*daujl^$k{*+`*jj@ zkerPs)MY~5Ce&j>rs=DZdr`gf<7{?YkoRpoKI`ILD(w&z>pnQ*3~jAekmE@Tzb&=R z8q;D$d6>|W;t;zW3{&g-WiAP3yBP{*@^T<8b}&bhxT%rKvmiWeXQL_u6~`86r@b^d z825$bp`>+%Yc^4pfkujf6LMIB6GA>N~ah2JCryVTeiTQTTRjM zH^`U5aTX(~<)pW=8hsL0E zxo%!U7jp#y=xRJzVc?PW3Hy==MJ4B5{3YJNRR0kfaaY2KyGyETzHr~Akp)|mIQJ|L zJ+D0aT;qi$G#PT=XaJP*`7>6$uUFS)>=c4+$F_`;sDoKXH~E(2pHPX6in|&94qw{#2;)iF9!c5D)3(F<*WnLs)%KoDAGMFgVz1#oLGSJNXRLT% zcb9))$6GH1AdtX}i*};8TlbcT`x94{eei|^hxc^3`-aec&BrDnd1(wl_CPmX7$>Za z)iTw(+QDtrLx;3sdG3Y1xNWrHYB@gm?Sj7phq>K&J8@ZGMLK)^!@b7cQNh0hL$SnD zcnCUs{5gBklyNDWaSa+tg4t`>^6zTX1*wm7DI1-E<}64~%Q+0qSC}orw(~xBhmeR(JS|WEG*EDN5Igx9I3@hKDvf>6ey~>7At6vXxjNh~X zJ^=$|RTcN0<=+yP&3PQ>y2Y|lM`K(Sc9gFS``BoZgAkx`z!2Bj}KTRFRY8FqDR6Ag+I#oCp|aY;z9jiWvG`VTwAbQDf@yO%Xfi=oo6K-h-Mh&Qvy-pGdd_ow&pzCWRld@mk_NG7iBzOf{OYRq zl+dLSaSNW}dO4iXwSG-bQpNZwW_G5EbGa43U~1fq__%CJ7Uy!;z+vOFy@Z2SJOvMM z*!RFMSz!d6rj4(H=aM`oV<0Yh%NLs6Z6sM86G}l+M8R{KR>B3(>$Et+Q*@hXx3Nv+ zcMik2CcoQYCH@5@e4j|Bac6s+AnI`;{F#p(5EjM4L~6Z9WW{ksNDL_lQ;`ow3n7X3wx7#E_N*q6F6}e_RhC@=4%nF zdpPZn5I`2r`UPJg5X%OC3U8q+(ifq3z+<{?)$;xiD&4mcPYBD`>zgm1nLU%zU&0LO zhSSzrcFA$GtnhU8_Qiq2^8<%39h$4zH1F+y&*RHIeBH6})u&&6`qH5ncEJexz4qS4 z_O0{nTi@~C3G=xQGM{TA^SSby4ynFlv96b-Y}0~Xu&U7sO%uYAB}`~KZ_z<+L&;hLi(swNRrGRyxufYpqC zfAuq2#e6a4JGwjJD|m_-{nF0qdF$&m*x)Jb^knDBcY@`Zo7uQov#m_mGKu@WN*@$1 z(X@O}_#`RXpZ&<(e|Emro-SN6Q-ddvU4&!cT> zd}y0;-wkr;$b2`Jn&m!WTK&wPA*cMO@{ry3XHG!Hw>wF=T9wM%Zx@wI4JzxRuT!7a zSJ*=SIm$oXT!glI0xKqk#4j0?C7bC2x?UOiy(fO_iN)^S^WD1_s_$C#-Zk&Ni%FUC z-lY?gY}EglY}Eh63FxYo?i};-FtA)MZX`8S1+4Y?3uGs5nPiAZg)#D@VNjgBHl^&V zx=Mkp%fu<;Hvz%IwwM4-GjGn#T~znN^T;$HYUKPSbt#gBFG7?phbY@AZRo}sSzJz) zaaY)fWQbI~n{k5nMg@IcuWZZM+1nviwP&0Rx+GtV8CmJdl(R1cu(}Kn-*@LUy6z=8XX~k@FZpvu26CNn61% zOlJ1yk_lpBbE%Sc#?H`{MHAY8g|~~kLRQi5l^U9LMZeDZh$B{KYvir{72@UR#2K(t zRhUatYmr=>z`(gg0f-u|e%WXC6j0F-j4oTHF^uL_JQ%}PZUox&4Z#14p25rGg3Uj% z2v>5XA+du+0*crlgRG)FbZkpB{8Tt9Zu5n>fl%XyD8?$p3kF#-Gw-Dqg4A(p555;l zZ=2(cB780!n#4VYe96vj5q)^~?PJI~#nZ8HbFV4A<(2BZ z;vc|wYd(9G;Vw~~y*_b98sTSWS79dQl|?c!S1Pp5xLrJ)vkEEA!LP2LgR@d>4jV^s z5PBk*Je8|JS%poR`kxk?W()W+cy*P;2->Y2{e+qbga1artwb=|e>@VxPIkg#HUb zEK`sqF(scX$@4`Ur;*6zz}0# zr~pGl4h9qjf|0B(4w}dq%GQhJB9euSm|Vziie6A~j`{mJF}W}tlc8(@ znL?hNvS@!v$#lVsQFPO7%43tb*crDeYcyk|B(fdkt#6l zipJ0K8k^6vL3zY@PlZ)sfly62ct@ExvFqvc7&#GgzDo|T?s&f8QHMKZ{yopQj9%Ox zeYbWUDX^fx+=K3#vC6XiBdPNrB=b^OHQkS!ld(~rn= z;J;fd|K9fKg6+|pjxWe^-wXG>bZGXWn-ak{zibKO^-{x?`jfMRei>7mzz`G`ivFt>v-GohICn0 zn{g84k~|e02hydZ?gJ0}u&HJ#%UCG1lCZUOr10C=s$;`>^hUzgdL3_IYb9*;gss)Y z)=JnK2wSU(trhxgT<+Y8oz^x+RU>~+PI;R$RsyaAuoFPoaMLw|qHqiXU)z$0!Ogi< z%s6ebkL!mw*AH*KegwHBhx-FJAiW&q=gX}XA*kdk;muXTTdxv9K;R(+l_r8pkj1D- l##t#pAZkGX*Mb1O77PMI)smaQr5?9@=gmg9yqksh{|BapNC*G` diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_testing.cpython-312.pyc deleted file mode 100644 index 4305c1031acb6b6a760fadb1f0d2de11c93b504f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3561 zcmaJDU2GgjdFF2Se)epilh{d2ov<~o$)?U-leBS38mf{imRsbMIs$Z2Sg&{2zIFC? zFEe|w?r@PsBNT}uH7}T|w0U(DAzpbbPayGf#+7WXKp;^B6)%o1639<{-|XGyd@=0l zzWHY6n{U4P{{PV5uMqgY{`g-@S2KkC4JVyXiV)f=1F}vmVo{e=Xo*t96K(&lW%zSP%;f3d`Y8& zhnDO>H+bDM^##McWqXzx-5bHS5VZAen6DF?l&D2Y35%AJR-zLJGzVJRuEZww}=j!pwDp-`*V>8uX6dQP|>rB;PK%sYzJxd=E zh|4BbXAz{RN5|pDpkB4rE)LhKsBXi(0g~M8x`YQz^^A%giDuc{WR4*17D_!8ao4&I z{>b!Q*EWR_3&w(3xZ*Rv7C4@*nt(<85R2CQg=HY_W-54TawzL~f0%HrFdGXTN@7t$ z2BzF)%R!#zDOGp1dkAw>=*imYCh61uYW}qJx?>CJcw>3>96k_*Tuebv^9U_1iVW#h2+i>x1*G zAHe{EJc2<0S}K&d?Jgd)7fOpY&*UfwdZ4QAT`!jXid|e>Vg^5B8b#NwoCzF=jo^Io zj_utky3RteS`W&;cfN4;T#-A0eWnV*V=URc2p;43MIE$k7xlpAV7{e7wH{`4-SM12 z*BggAeqZP;9fiyJ6##4G$p9Ht?@2qyM<3)r$~TXl+MpZb+ovyWp1#!7UTY3tz9)U4 z>>L|`A-(fL0fvDcbsUE5&g)n1Nk7ZBfDJLbt%mv+_MHc0odg*9;#;LbOxH;_Y-E)j zWZ6}E(CV#Igv^m3w&EOlNM|)ER2=SjJTN@dW;wV^C_WsR^@Ev8)wL@Sgtnz67(P6d zeF$O3Q502W$8jm8>-KF>RlZAAxG)Zz`~?7OX=Ku20{e{^@(o%;>X1qBez)Q7Hj?z(VhLkhmf) z547IL2@7IxIkwYNZm^U5BsE7gX|^Gqa;(dZ^rXmMm-na!mdxt9=^C6vtikizaVA1c zMAz4VQ;!N5>NJ2UbtV_KCEpX)|!V-Z;WpQzg~H`vT^G-$37eS z-NQKQJs-c?bm#!kV?f`jD{R#~ufEdi%WI&9w1+ z?6?1mD>y9yZ`7O$MuGEt-?p`?f$)=;p_t*Wy=6miseL&5UWUO<0pXmNqR z0o8p{?SPv=6}JJnbyJhrSK&mMiYiB#VnS7+wBY+LL}L*)8Ct20he^1rvyK953WI)P!}_nD}-0d=D~*bxLh3KMGxUWGr$+$ris--)f<$?aTmGgsWoooz~I zqlkg+_`{+ro_iIL?&n%Gh#%T{-f~=`K!mCTjiDMjDvwmNH-H2;I-zw_OEL@~p|4Q%vF)36 zWWam1H-)qaz6F1dfe>kLusNuHK6ZXCLg}t+AP{+*?iQt!LGUs(K$grFQ^% zo6vo#?5ODfdCvRLIsFj0{5-Lq{D~|BhdP}iAIQH-u3!>-<$KVzLo*vVu4=e$l!)4T zgw9pPrXDrB=rff=j}nxzxtMMHOn4OcbvPI)Kwofu=vu5^MSKH&mM;8Jy0FKwr~2{e1pSnbOAk^LP~O{#A_p5C{K8W_lrUF8 zdk<~eVhvI;HfE@}FyGVOG6_~0I$M~6-Ws05us{i;!fD|t=qOP@;B`?{2t$fTyohUY zLfOl_7WIYSWUs>p7G{olXE#YH{WBT+2YKl)Wc2Su`*&)R4nHOUT0fv^dagB;rf<_H KLkT)1xcwK4P&*O; diff --git a/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/_core/__pycache__/_typedattr.cpython-312.pyc deleted file mode 100644 index 63a6130ee3a94476117f022e5199098e50f2052f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3831 zcma)9U1%KF6~6Pc|0}J2B1KM$J&7IJ>q=V3uH9BNZCxv=T{~`w?LgKwlhMpw?O3xj zn|o&^@3IcUh*rS~ghFv34VXNX1i$pPFC~wK_Cc-*kq4K$w55c;NKwGXPd(?(&q{I# zy|9;i@0@%7?)lC+`{%yCJb|%)Y`9`5ykcdoZ#!BCkLax=K*k_V`AME>Y zMY5|UtKZ5ltJMLS{FGR^Wn$%T$(=(no-)g?dn8$+jc^%J#+)%`YIU9uCHv7SL9Ma}Kn12Nx zprk5Uq$*odRk4&6Qj;usxmZ$<_=A<$s07eG^j zpP4)#Sd)eym?v%i4i>+WwmxnbFk+Kik?~h0KUxveC2^$BkW2dsxhi+%%PC;6V_0%b z$E0^gx^h=qkht{DQ+_5Uw3M#=fo!QCDlz3XNhN+Z{{FVoCGU>(0!<=qQcj%>O1j=N zi|cwI>76`=un29fvq!VJ*04DTfM~W4-rMepayrP&QGgW$y<*uc$aCLdK3}x`I-mfE zLtvyhzE&`(>$YqAdhA|ZN7R`PXXuk4i+o(8L4%yG3;*jn$BYBdy~KuK!FI#c+51>b zOg+YU7Z7p-riV-9-uUFl=IW7|PiOCppIRy08+-cw6CY&1Bx-JG<>cD%)1MEI-yR;n z$v+$Z_V2Tw7XEtZ^u5tNYoprDv75!!iPNi3oY_?5Cx_OFJUFzTf?Hn|Nv{9x%XbU(suj>uZYB{(r>iU~4!->9RblvhyT^Du*eUa5B zbsTVw#GXMTFwA}&S`RNs7*6O5j?=?svLUOf?1N%9wQqyKB-9Z^CVWpulDK~XN86D{ zRVxFyQ{yaDP0_TKwUjL<892#V>b8?C%>iEXR%$tw+|0DogF!Rly_RDof((ay+AP&<*K}GIBz)TyJVFg&9~*Z7 zN|E>yGin%Z4J#J|&*O)LWzW_~Iu+VtHL+bluWQnBlrhmVHUO@L+M;sm)I=<5A{K)I z;mBSU;GO+n|Ljvc2_e(PrDA=Q3=FO0!cq~{a`+k!@v<1VHy~SmBApFYk=XOhsU%l|Sd^B0e@4(^)$w8gC46B`^D`Aeis>r0P!~i@;_7Xqw<37T6 zNu(?L5%>vd5mww%HKbdJAQ+Z>4Qh`mzYYjmBv+Kz$)Z$Nj6ZHglJM+-#O)JWWc~{+ z7gn}Qt#Vjs!4+E6!yw=USYq_e+0c1>J+`+5-E`AnMxzJ&X%X6qXzf6QHf8}W0BJ*; z7HMSqjkmVHIdlqdlmXmH;GK(`?O7Yy_4&xb+am`*{{HQeqbo0M^pksMAv55MXo17lc} z_pFshe_Os?+Iw%bvU=#nJEJfCX=ZicmHSWb{&oL)4!%F)MPPWXG)CUvGp+nVnpV!1 zW%ewbb)Jj5`HNvEKB2{Z{>6)zCbaPI(j_nt5zLT{xF=TS^p;aJnqgBL@*N7VYF*$l z6T&_w$J!%Z%_Se5f^A09l1(>P9;_<}4H3CQ$*TRZ{7mYHGBVA!m&V>n^T4a>O5 zCibg8r-n8alI~x})%qB$0`;gkSyPV!MW9}Yb{Foa@@vO_ zv`I!&V|Y~9kYN>yLFTaw8QN1G#-^p#ft#Fty8UI3vrbQUK!vl}9KM4D$AF>yK4s#Yi3DdeF zNz&iQv;QHJeA}893E~YV;e`JIfHmfA diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_asyncio_selector_thread.py b/venv/lib/python3.12/site-packages/anyio/_core/_asyncio_selector_thread.py deleted file mode 100644 index 9f35bae..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_asyncio_selector_thread.py +++ /dev/null @@ -1,167 +0,0 @@ -from __future__ import annotations - -import asyncio -import socket -import threading -from collections.abc import Callable -from selectors import EVENT_READ, EVENT_WRITE, DefaultSelector -from typing import TYPE_CHECKING, Any - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike - -_selector_lock = threading.Lock() -_selector: Selector | None = None - - -class Selector: - def __init__(self) -> None: - self._thread = threading.Thread(target=self.run, name="AnyIO socket selector") - self._selector = DefaultSelector() - self._send, self._receive = socket.socketpair() - self._send.setblocking(False) - self._receive.setblocking(False) - # This somewhat reduces the amount of memory wasted queueing up data - # for wakeups. With these settings, maximum number of 1-byte sends - # before getting BlockingIOError: - # Linux 4.8: 6 - # macOS (darwin 15.5): 1 - # Windows 10: 525347 - # Windows you're weird. (And on Windows setting SNDBUF to 0 makes send - # blocking, even on non-blocking sockets, so don't do that.) - self._receive.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1) - self._send.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 1) - # On Windows this is a TCP socket so this might matter. On other - # platforms this fails b/c AF_UNIX sockets aren't actually TCP. - try: - self._send.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except OSError: - pass - - self._selector.register(self._receive, EVENT_READ) - self._closed = False - - def start(self) -> None: - self._thread.start() - threading._register_atexit(self._stop) # type: ignore[attr-defined] - - def _stop(self) -> None: - global _selector - self._closed = True - self._notify_self() - self._send.close() - self._thread.join() - self._selector.unregister(self._receive) - self._receive.close() - self._selector.close() - _selector = None - assert not self._selector.get_map(), ( - "selector still has registered file descriptors after shutdown" - ) - - def _notify_self(self) -> None: - try: - self._send.send(b"\x00") - except BlockingIOError: - pass - - def add_reader(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: - loop = asyncio.get_running_loop() - try: - key = self._selector.get_key(fd) - except KeyError: - self._selector.register(fd, EVENT_READ, {EVENT_READ: (loop, callback)}) - else: - if EVENT_READ in key.data: - raise ValueError( - "this file descriptor is already registered for reading" - ) - - key.data[EVENT_READ] = loop, callback - self._selector.modify(fd, key.events | EVENT_READ, key.data) - - self._notify_self() - - def add_writer(self, fd: FileDescriptorLike, callback: Callable[[], Any]) -> None: - loop = asyncio.get_running_loop() - try: - key = self._selector.get_key(fd) - except KeyError: - self._selector.register(fd, EVENT_WRITE, {EVENT_WRITE: (loop, callback)}) - else: - if EVENT_WRITE in key.data: - raise ValueError( - "this file descriptor is already registered for writing" - ) - - key.data[EVENT_WRITE] = loop, callback - self._selector.modify(fd, key.events | EVENT_WRITE, key.data) - - self._notify_self() - - def remove_reader(self, fd: FileDescriptorLike) -> bool: - try: - key = self._selector.get_key(fd) - except KeyError: - return False - - if new_events := key.events ^ EVENT_READ: - del key.data[EVENT_READ] - self._selector.modify(fd, new_events, key.data) - else: - self._selector.unregister(fd) - - return True - - def remove_writer(self, fd: FileDescriptorLike) -> bool: - try: - key = self._selector.get_key(fd) - except KeyError: - return False - - if new_events := key.events ^ EVENT_WRITE: - del key.data[EVENT_WRITE] - self._selector.modify(fd, new_events, key.data) - else: - self._selector.unregister(fd) - - return True - - def run(self) -> None: - while not self._closed: - for key, events in self._selector.select(): - if key.fileobj is self._receive: - try: - while self._receive.recv(4096): - pass - except BlockingIOError: - pass - - continue - - if events & EVENT_READ: - loop, callback = key.data[EVENT_READ] - self.remove_reader(key.fd) - try: - loop.call_soon_threadsafe(callback) - except RuntimeError: - pass # the loop was already closed - - if events & EVENT_WRITE: - loop, callback = key.data[EVENT_WRITE] - self.remove_writer(key.fd) - try: - loop.call_soon_threadsafe(callback) - except RuntimeError: - pass # the loop was already closed - - -def get_selector() -> Selector: - global _selector - - with _selector_lock: - if _selector is None: - _selector = Selector() - _selector.start() - - return _selector diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_eventloop.py b/venv/lib/python3.12/site-packages/anyio/_core/_eventloop.py deleted file mode 100644 index 6dcb458..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_eventloop.py +++ /dev/null @@ -1,166 +0,0 @@ -from __future__ import annotations - -import math -import sys -import threading -from collections.abc import Awaitable, Callable, Generator -from contextlib import contextmanager -from importlib import import_module -from typing import TYPE_CHECKING, Any, TypeVar - -import sniffio - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if TYPE_CHECKING: - from ..abc import AsyncBackend - -# This must be updated when new backends are introduced -BACKENDS = "asyncio", "trio" - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - -threadlocals = threading.local() -loaded_backends: dict[str, type[AsyncBackend]] = {} - - -def run( - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - backend: str = "asyncio", - backend_options: dict[str, Any] | None = None, -) -> T_Retval: - """ - Run the given coroutine function in an asynchronous event loop. - - The current thread must not be already running an event loop. - - :param func: a coroutine function - :param args: positional arguments to ``func`` - :param backend: name of the asynchronous event loop implementation – currently - either ``asyncio`` or ``trio`` - :param backend_options: keyword arguments to call the backend ``run()`` - implementation with (documented :ref:`here `) - :return: the return value of the coroutine function - :raises RuntimeError: if an asynchronous event loop is already running in this - thread - :raises LookupError: if the named backend is not found - - """ - try: - asynclib_name = sniffio.current_async_library() - except sniffio.AsyncLibraryNotFoundError: - pass - else: - raise RuntimeError(f"Already running {asynclib_name} in this thread") - - try: - async_backend = get_async_backend(backend) - except ImportError as exc: - raise LookupError(f"No such backend: {backend}") from exc - - token = None - if sniffio.current_async_library_cvar.get(None) is None: - # Since we're in control of the event loop, we can cache the name of the async - # library - token = sniffio.current_async_library_cvar.set(backend) - - try: - backend_options = backend_options or {} - return async_backend.run(func, args, {}, backend_options) - finally: - if token: - sniffio.current_async_library_cvar.reset(token) - - -async def sleep(delay: float) -> None: - """ - Pause the current task for the specified duration. - - :param delay: the duration, in seconds - - """ - return await get_async_backend().sleep(delay) - - -async def sleep_forever() -> None: - """ - Pause the current task until it's cancelled. - - This is a shortcut for ``sleep(math.inf)``. - - .. versionadded:: 3.1 - - """ - await sleep(math.inf) - - -async def sleep_until(deadline: float) -> None: - """ - Pause the current task until the given time. - - :param deadline: the absolute time to wake up at (according to the internal - monotonic clock of the event loop) - - .. versionadded:: 3.1 - - """ - now = current_time() - await sleep(max(deadline - now, 0)) - - -def current_time() -> float: - """ - Return the current value of the event loop's internal clock. - - :return: the clock value (seconds) - - """ - return get_async_backend().current_time() - - -def get_all_backends() -> tuple[str, ...]: - """Return a tuple of the names of all built-in backends.""" - return BACKENDS - - -def get_cancelled_exc_class() -> type[BaseException]: - """Return the current async library's cancellation exception class.""" - return get_async_backend().cancelled_exception_class() - - -# -# Private API -# - - -@contextmanager -def claim_worker_thread( - backend_class: type[AsyncBackend], token: object -) -> Generator[Any, None, None]: - threadlocals.current_async_backend = backend_class - threadlocals.current_token = token - try: - yield - finally: - del threadlocals.current_async_backend - del threadlocals.current_token - - -def get_async_backend(asynclib_name: str | None = None) -> type[AsyncBackend]: - if asynclib_name is None: - asynclib_name = sniffio.current_async_library() - - # We use our own dict instead of sys.modules to get the already imported back-end - # class because the appropriate modules in sys.modules could potentially be only - # partially initialized - try: - return loaded_backends[asynclib_name] - except KeyError: - module = import_module(f"anyio._backends._{asynclib_name}") - loaded_backends[asynclib_name] = module.backend_class - return module.backend_class diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_exceptions.py b/venv/lib/python3.12/site-packages/anyio/_core/_exceptions.py deleted file mode 100644 index 16b9448..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_exceptions.py +++ /dev/null @@ -1,126 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import Generator -from textwrap import dedent -from typing import Any - -if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - - -class BrokenResourceError(Exception): - """ - Raised when trying to use a resource that has been rendered unusable due to external - causes (e.g. a send stream whose peer has disconnected). - """ - - -class BrokenWorkerProcess(Exception): - """ - Raised by :meth:`~anyio.to_process.run_sync` if the worker process terminates abruptly or - otherwise misbehaves. - """ - - -class BrokenWorkerIntepreter(Exception): - """ - Raised by :meth:`~anyio.to_interpreter.run_sync` if an unexpected exception is - raised in the subinterpreter. - """ - - def __init__(self, excinfo: Any): - # This was adapted from concurrent.futures.interpreter.ExecutionFailed - msg = excinfo.formatted - if not msg: - if excinfo.type and excinfo.msg: - msg = f"{excinfo.type.__name__}: {excinfo.msg}" - else: - msg = excinfo.type.__name__ or excinfo.msg - - super().__init__(msg) - self.excinfo = excinfo - - def __str__(self) -> str: - try: - formatted = self.excinfo.errdisplay - except Exception: - return super().__str__() - else: - return dedent( - f""" - {super().__str__()} - - Uncaught in the interpreter: - - {formatted} - """.strip() - ) - - -class BusyResourceError(Exception): - """ - Raised when two tasks are trying to read from or write to the same resource - concurrently. - """ - - def __init__(self, action: str): - super().__init__(f"Another task is already {action} this resource") - - -class ClosedResourceError(Exception): - """Raised when trying to use a resource that has been closed.""" - - -class DelimiterNotFound(Exception): - """ - Raised during - :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the - maximum number of bytes has been read without the delimiter being found. - """ - - def __init__(self, max_bytes: int) -> None: - super().__init__( - f"The delimiter was not found among the first {max_bytes} bytes" - ) - - -class EndOfStream(Exception): - """ - Raised when trying to read from a stream that has been closed from the other end. - """ - - -class IncompleteRead(Exception): - """ - Raised during - :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_exactly` or - :meth:`~anyio.streams.buffered.BufferedByteReceiveStream.receive_until` if the - connection is closed before the requested amount of bytes has been read. - """ - - def __init__(self) -> None: - super().__init__( - "The stream was closed before the read operation could be completed" - ) - - -class TypedAttributeLookupError(LookupError): - """ - Raised by :meth:`~anyio.TypedAttributeProvider.extra` when the given typed attribute - is not found and no default value has been given. - """ - - -class WouldBlock(Exception): - """Raised by ``X_nowait`` functions if ``X()`` would block.""" - - -def iterate_exceptions( - exception: BaseException, -) -> Generator[BaseException, None, None]: - if isinstance(exception, BaseExceptionGroup): - for exc in exception.exceptions: - yield from iterate_exceptions(exc) - else: - yield exception diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_fileio.py b/venv/lib/python3.12/site-packages/anyio/_core/_fileio.py deleted file mode 100644 index a0d6198..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_fileio.py +++ /dev/null @@ -1,742 +0,0 @@ -from __future__ import annotations - -import os -import pathlib -import sys -from collections.abc import ( - AsyncIterator, - Callable, - Iterable, - Iterator, - Sequence, -) -from dataclasses import dataclass -from functools import partial -from os import PathLike -from typing import ( - IO, - TYPE_CHECKING, - Any, - AnyStr, - ClassVar, - Final, - Generic, - overload, -) - -from .. import to_thread -from ..abc import AsyncResource - -if TYPE_CHECKING: - from types import ModuleType - - from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer -else: - ReadableBuffer = OpenBinaryMode = OpenTextMode = WriteableBuffer = object - - -class AsyncFile(AsyncResource, Generic[AnyStr]): - """ - An asynchronous file object. - - This class wraps a standard file object and provides async friendly versions of the - following blocking methods (where available on the original file object): - - * read - * read1 - * readline - * readlines - * readinto - * readinto1 - * write - * writelines - * truncate - * seek - * tell - * flush - - All other methods are directly passed through. - - This class supports the asynchronous context manager protocol which closes the - underlying file at the end of the context block. - - This class also supports asynchronous iteration:: - - async with await open_file(...) as f: - async for line in f: - print(line) - """ - - def __init__(self, fp: IO[AnyStr]) -> None: - self._fp: Any = fp - - def __getattr__(self, name: str) -> object: - return getattr(self._fp, name) - - @property - def wrapped(self) -> IO[AnyStr]: - """The wrapped file object.""" - return self._fp - - async def __aiter__(self) -> AsyncIterator[AnyStr]: - while True: - line = await self.readline() - if line: - yield line - else: - break - - async def aclose(self) -> None: - return await to_thread.run_sync(self._fp.close) - - async def read(self, size: int = -1) -> AnyStr: - return await to_thread.run_sync(self._fp.read, size) - - async def read1(self: AsyncFile[bytes], size: int = -1) -> bytes: - return await to_thread.run_sync(self._fp.read1, size) - - async def readline(self) -> AnyStr: - return await to_thread.run_sync(self._fp.readline) - - async def readlines(self) -> list[AnyStr]: - return await to_thread.run_sync(self._fp.readlines) - - async def readinto(self: AsyncFile[bytes], b: WriteableBuffer) -> int: - return await to_thread.run_sync(self._fp.readinto, b) - - async def readinto1(self: AsyncFile[bytes], b: WriteableBuffer) -> int: - return await to_thread.run_sync(self._fp.readinto1, b) - - @overload - async def write(self: AsyncFile[bytes], b: ReadableBuffer) -> int: ... - - @overload - async def write(self: AsyncFile[str], b: str) -> int: ... - - async def write(self, b: ReadableBuffer | str) -> int: - return await to_thread.run_sync(self._fp.write, b) - - @overload - async def writelines( - self: AsyncFile[bytes], lines: Iterable[ReadableBuffer] - ) -> None: ... - - @overload - async def writelines(self: AsyncFile[str], lines: Iterable[str]) -> None: ... - - async def writelines(self, lines: Iterable[ReadableBuffer] | Iterable[str]) -> None: - return await to_thread.run_sync(self._fp.writelines, lines) - - async def truncate(self, size: int | None = None) -> int: - return await to_thread.run_sync(self._fp.truncate, size) - - async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: - return await to_thread.run_sync(self._fp.seek, offset, whence) - - async def tell(self) -> int: - return await to_thread.run_sync(self._fp.tell) - - async def flush(self) -> None: - return await to_thread.run_sync(self._fp.flush) - - -@overload -async def open_file( - file: str | PathLike[str] | int, - mode: OpenBinaryMode, - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - closefd: bool = ..., - opener: Callable[[str, int], int] | None = ..., -) -> AsyncFile[bytes]: ... - - -@overload -async def open_file( - file: str | PathLike[str] | int, - mode: OpenTextMode = ..., - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - closefd: bool = ..., - opener: Callable[[str, int], int] | None = ..., -) -> AsyncFile[str]: ... - - -async def open_file( - file: str | PathLike[str] | int, - mode: str = "r", - buffering: int = -1, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - closefd: bool = True, - opener: Callable[[str, int], int] | None = None, -) -> AsyncFile[Any]: - """ - Open a file asynchronously. - - The arguments are exactly the same as for the builtin :func:`open`. - - :return: an asynchronous file object - - """ - fp = await to_thread.run_sync( - open, file, mode, buffering, encoding, errors, newline, closefd, opener - ) - return AsyncFile(fp) - - -def wrap_file(file: IO[AnyStr]) -> AsyncFile[AnyStr]: - """ - Wrap an existing file as an asynchronous file. - - :param file: an existing file-like object - :return: an asynchronous file object - - """ - return AsyncFile(file) - - -@dataclass(eq=False) -class _PathIterator(AsyncIterator["Path"]): - iterator: Iterator[PathLike[str]] - - async def __anext__(self) -> Path: - nextval = await to_thread.run_sync( - next, self.iterator, None, abandon_on_cancel=True - ) - if nextval is None: - raise StopAsyncIteration from None - - return Path(nextval) - - -class Path: - """ - An asynchronous version of :class:`pathlib.Path`. - - This class cannot be substituted for :class:`pathlib.Path` or - :class:`pathlib.PurePath`, but it is compatible with the :class:`os.PathLike` - interface. - - It implements the Python 3.10 version of :class:`pathlib.Path` interface, except for - the deprecated :meth:`~pathlib.Path.link_to` method. - - Some methods may be unavailable or have limited functionality, based on the Python - version: - - * :meth:`~pathlib.Path.copy` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.copy_into` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.from_uri` (available on Python 3.13 or later) - * :meth:`~pathlib.PurePath.full_match` (available on Python 3.13 or later) - * :attr:`~pathlib.Path.info` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.is_junction` (available on Python 3.12 or later) - * :meth:`~pathlib.PurePath.match` (the ``case_sensitive`` parameter is only - available on Python 3.13 or later) - * :meth:`~pathlib.Path.move` (available on Python 3.14 or later) - * :meth:`~pathlib.Path.move_into` (available on Python 3.14 or later) - * :meth:`~pathlib.PurePath.relative_to` (the ``walk_up`` parameter is only available - on Python 3.12 or later) - * :meth:`~pathlib.Path.walk` (available on Python 3.12 or later) - - Any methods that do disk I/O need to be awaited on. These methods are: - - * :meth:`~pathlib.Path.absolute` - * :meth:`~pathlib.Path.chmod` - * :meth:`~pathlib.Path.cwd` - * :meth:`~pathlib.Path.exists` - * :meth:`~pathlib.Path.expanduser` - * :meth:`~pathlib.Path.group` - * :meth:`~pathlib.Path.hardlink_to` - * :meth:`~pathlib.Path.home` - * :meth:`~pathlib.Path.is_block_device` - * :meth:`~pathlib.Path.is_char_device` - * :meth:`~pathlib.Path.is_dir` - * :meth:`~pathlib.Path.is_fifo` - * :meth:`~pathlib.Path.is_file` - * :meth:`~pathlib.Path.is_junction` - * :meth:`~pathlib.Path.is_mount` - * :meth:`~pathlib.Path.is_socket` - * :meth:`~pathlib.Path.is_symlink` - * :meth:`~pathlib.Path.lchmod` - * :meth:`~pathlib.Path.lstat` - * :meth:`~pathlib.Path.mkdir` - * :meth:`~pathlib.Path.open` - * :meth:`~pathlib.Path.owner` - * :meth:`~pathlib.Path.read_bytes` - * :meth:`~pathlib.Path.read_text` - * :meth:`~pathlib.Path.readlink` - * :meth:`~pathlib.Path.rename` - * :meth:`~pathlib.Path.replace` - * :meth:`~pathlib.Path.resolve` - * :meth:`~pathlib.Path.rmdir` - * :meth:`~pathlib.Path.samefile` - * :meth:`~pathlib.Path.stat` - * :meth:`~pathlib.Path.symlink_to` - * :meth:`~pathlib.Path.touch` - * :meth:`~pathlib.Path.unlink` - * :meth:`~pathlib.Path.walk` - * :meth:`~pathlib.Path.write_bytes` - * :meth:`~pathlib.Path.write_text` - - Additionally, the following methods return an async iterator yielding - :class:`~.Path` objects: - - * :meth:`~pathlib.Path.glob` - * :meth:`~pathlib.Path.iterdir` - * :meth:`~pathlib.Path.rglob` - """ - - __slots__ = "_path", "__weakref__" - - __weakref__: Any - - def __init__(self, *args: str | PathLike[str]) -> None: - self._path: Final[pathlib.Path] = pathlib.Path(*args) - - def __fspath__(self) -> str: - return self._path.__fspath__() - - def __str__(self) -> str: - return self._path.__str__() - - def __repr__(self) -> str: - return f"{self.__class__.__name__}({self.as_posix()!r})" - - def __bytes__(self) -> bytes: - return self._path.__bytes__() - - def __hash__(self) -> int: - return self._path.__hash__() - - def __eq__(self, other: object) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__eq__(target) - - def __lt__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__lt__(target) - - def __le__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__le__(target) - - def __gt__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__gt__(target) - - def __ge__(self, other: pathlib.PurePath | Path) -> bool: - target = other._path if isinstance(other, Path) else other - return self._path.__ge__(target) - - def __truediv__(self, other: str | PathLike[str]) -> Path: - return Path(self._path / other) - - def __rtruediv__(self, other: str | PathLike[str]) -> Path: - return Path(other) / self - - @property - def parts(self) -> tuple[str, ...]: - return self._path.parts - - @property - def drive(self) -> str: - return self._path.drive - - @property - def root(self) -> str: - return self._path.root - - @property - def anchor(self) -> str: - return self._path.anchor - - @property - def parents(self) -> Sequence[Path]: - return tuple(Path(p) for p in self._path.parents) - - @property - def parent(self) -> Path: - return Path(self._path.parent) - - @property - def name(self) -> str: - return self._path.name - - @property - def suffix(self) -> str: - return self._path.suffix - - @property - def suffixes(self) -> list[str]: - return self._path.suffixes - - @property - def stem(self) -> str: - return self._path.stem - - async def absolute(self) -> Path: - path = await to_thread.run_sync(self._path.absolute) - return Path(path) - - def as_posix(self) -> str: - return self._path.as_posix() - - def as_uri(self) -> str: - return self._path.as_uri() - - if sys.version_info >= (3, 13): - parser: ClassVar[ModuleType] = pathlib.Path.parser - - @classmethod - def from_uri(cls, uri: str) -> Path: - return Path(pathlib.Path.from_uri(uri)) - - def full_match( - self, path_pattern: str, *, case_sensitive: bool | None = None - ) -> bool: - return self._path.full_match(path_pattern, case_sensitive=case_sensitive) - - def match( - self, path_pattern: str, *, case_sensitive: bool | None = None - ) -> bool: - return self._path.match(path_pattern, case_sensitive=case_sensitive) - else: - - def match(self, path_pattern: str) -> bool: - return self._path.match(path_pattern) - - if sys.version_info >= (3, 14): - - @property - def info(self) -> Any: # TODO: add return type annotation when Typeshed gets it - return self._path.info - - async def copy( - self, - target: str | os.PathLike[str], - *, - follow_symlinks: bool = True, - dirs_exist_ok: bool = False, - preserve_metadata: bool = False, - ) -> Path: - func = partial( - self._path.copy, - follow_symlinks=follow_symlinks, - dirs_exist_ok=dirs_exist_ok, - preserve_metadata=preserve_metadata, - ) - return Path(await to_thread.run_sync(func, target)) - - async def copy_into( - self, - target_dir: str | os.PathLike[str], - *, - follow_symlinks: bool = True, - dirs_exist_ok: bool = False, - preserve_metadata: bool = False, - ) -> Path: - func = partial( - self._path.copy_into, - follow_symlinks=follow_symlinks, - dirs_exist_ok=dirs_exist_ok, - preserve_metadata=preserve_metadata, - ) - return Path(await to_thread.run_sync(func, target_dir)) - - async def move(self, target: str | os.PathLike[str]) -> Path: - # Upstream does not handle anyio.Path properly as a PathLike - target = pathlib.Path(target) - return Path(await to_thread.run_sync(self._path.move, target)) - - async def move_into( - self, - target_dir: str | os.PathLike[str], - ) -> Path: - return Path(await to_thread.run_sync(self._path.move_into, target_dir)) - - def is_relative_to(self, other: str | PathLike[str]) -> bool: - try: - self.relative_to(other) - return True - except ValueError: - return False - - async def chmod(self, mode: int, *, follow_symlinks: bool = True) -> None: - func = partial(os.chmod, follow_symlinks=follow_symlinks) - return await to_thread.run_sync(func, self._path, mode) - - @classmethod - async def cwd(cls) -> Path: - path = await to_thread.run_sync(pathlib.Path.cwd) - return cls(path) - - async def exists(self) -> bool: - return await to_thread.run_sync(self._path.exists, abandon_on_cancel=True) - - async def expanduser(self) -> Path: - return Path( - await to_thread.run_sync(self._path.expanduser, abandon_on_cancel=True) - ) - - def glob(self, pattern: str) -> AsyncIterator[Path]: - gen = self._path.glob(pattern) - return _PathIterator(gen) - - async def group(self) -> str: - return await to_thread.run_sync(self._path.group, abandon_on_cancel=True) - - async def hardlink_to( - self, target: str | bytes | PathLike[str] | PathLike[bytes] - ) -> None: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(os.link, target, self) - - @classmethod - async def home(cls) -> Path: - home_path = await to_thread.run_sync(pathlib.Path.home) - return cls(home_path) - - def is_absolute(self) -> bool: - return self._path.is_absolute() - - async def is_block_device(self) -> bool: - return await to_thread.run_sync( - self._path.is_block_device, abandon_on_cancel=True - ) - - async def is_char_device(self) -> bool: - return await to_thread.run_sync( - self._path.is_char_device, abandon_on_cancel=True - ) - - async def is_dir(self) -> bool: - return await to_thread.run_sync(self._path.is_dir, abandon_on_cancel=True) - - async def is_fifo(self) -> bool: - return await to_thread.run_sync(self._path.is_fifo, abandon_on_cancel=True) - - async def is_file(self) -> bool: - return await to_thread.run_sync(self._path.is_file, abandon_on_cancel=True) - - if sys.version_info >= (3, 12): - - async def is_junction(self) -> bool: - return await to_thread.run_sync(self._path.is_junction) - - async def is_mount(self) -> bool: - return await to_thread.run_sync( - os.path.ismount, self._path, abandon_on_cancel=True - ) - - def is_reserved(self) -> bool: - return self._path.is_reserved() - - async def is_socket(self) -> bool: - return await to_thread.run_sync(self._path.is_socket, abandon_on_cancel=True) - - async def is_symlink(self) -> bool: - return await to_thread.run_sync(self._path.is_symlink, abandon_on_cancel=True) - - async def iterdir(self) -> AsyncIterator[Path]: - gen = ( - self._path.iterdir() - if sys.version_info < (3, 13) - else await to_thread.run_sync(self._path.iterdir, abandon_on_cancel=True) - ) - async for path in _PathIterator(gen): - yield path - - def joinpath(self, *args: str | PathLike[str]) -> Path: - return Path(self._path.joinpath(*args)) - - async def lchmod(self, mode: int) -> None: - await to_thread.run_sync(self._path.lchmod, mode) - - async def lstat(self) -> os.stat_result: - return await to_thread.run_sync(self._path.lstat, abandon_on_cancel=True) - - async def mkdir( - self, mode: int = 0o777, parents: bool = False, exist_ok: bool = False - ) -> None: - await to_thread.run_sync(self._path.mkdir, mode, parents, exist_ok) - - @overload - async def open( - self, - mode: OpenBinaryMode, - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - ) -> AsyncFile[bytes]: ... - - @overload - async def open( - self, - mode: OpenTextMode = ..., - buffering: int = ..., - encoding: str | None = ..., - errors: str | None = ..., - newline: str | None = ..., - ) -> AsyncFile[str]: ... - - async def open( - self, - mode: str = "r", - buffering: int = -1, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - ) -> AsyncFile[Any]: - fp = await to_thread.run_sync( - self._path.open, mode, buffering, encoding, errors, newline - ) - return AsyncFile(fp) - - async def owner(self) -> str: - return await to_thread.run_sync(self._path.owner, abandon_on_cancel=True) - - async def read_bytes(self) -> bytes: - return await to_thread.run_sync(self._path.read_bytes) - - async def read_text( - self, encoding: str | None = None, errors: str | None = None - ) -> str: - return await to_thread.run_sync(self._path.read_text, encoding, errors) - - if sys.version_info >= (3, 12): - - def relative_to( - self, *other: str | PathLike[str], walk_up: bool = False - ) -> Path: - return Path(self._path.relative_to(*other, walk_up=walk_up)) - - else: - - def relative_to(self, *other: str | PathLike[str]) -> Path: - return Path(self._path.relative_to(*other)) - - async def readlink(self) -> Path: - target = await to_thread.run_sync(os.readlink, self._path) - return Path(target) - - async def rename(self, target: str | pathlib.PurePath | Path) -> Path: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(self._path.rename, target) - return Path(target) - - async def replace(self, target: str | pathlib.PurePath | Path) -> Path: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(self._path.replace, target) - return Path(target) - - async def resolve(self, strict: bool = False) -> Path: - func = partial(self._path.resolve, strict=strict) - return Path(await to_thread.run_sync(func, abandon_on_cancel=True)) - - def rglob(self, pattern: str) -> AsyncIterator[Path]: - gen = self._path.rglob(pattern) - return _PathIterator(gen) - - async def rmdir(self) -> None: - await to_thread.run_sync(self._path.rmdir) - - async def samefile(self, other_path: str | PathLike[str]) -> bool: - if isinstance(other_path, Path): - other_path = other_path._path - - return await to_thread.run_sync( - self._path.samefile, other_path, abandon_on_cancel=True - ) - - async def stat(self, *, follow_symlinks: bool = True) -> os.stat_result: - func = partial(os.stat, follow_symlinks=follow_symlinks) - return await to_thread.run_sync(func, self._path, abandon_on_cancel=True) - - async def symlink_to( - self, - target: str | bytes | PathLike[str] | PathLike[bytes], - target_is_directory: bool = False, - ) -> None: - if isinstance(target, Path): - target = target._path - - await to_thread.run_sync(self._path.symlink_to, target, target_is_directory) - - async def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None: - await to_thread.run_sync(self._path.touch, mode, exist_ok) - - async def unlink(self, missing_ok: bool = False) -> None: - try: - await to_thread.run_sync(self._path.unlink) - except FileNotFoundError: - if not missing_ok: - raise - - if sys.version_info >= (3, 12): - - async def walk( - self, - top_down: bool = True, - on_error: Callable[[OSError], object] | None = None, - follow_symlinks: bool = False, - ) -> AsyncIterator[tuple[Path, list[str], list[str]]]: - def get_next_value() -> tuple[pathlib.Path, list[str], list[str]] | None: - try: - return next(gen) - except StopIteration: - return None - - gen = self._path.walk(top_down, on_error, follow_symlinks) - while True: - value = await to_thread.run_sync(get_next_value) - if value is None: - return - - root, dirs, paths = value - yield Path(root), dirs, paths - - def with_name(self, name: str) -> Path: - return Path(self._path.with_name(name)) - - def with_stem(self, stem: str) -> Path: - return Path(self._path.with_name(stem + self._path.suffix)) - - def with_suffix(self, suffix: str) -> Path: - return Path(self._path.with_suffix(suffix)) - - def with_segments(self, *pathsegments: str | PathLike[str]) -> Path: - return Path(*pathsegments) - - async def write_bytes(self, data: bytes) -> int: - return await to_thread.run_sync(self._path.write_bytes, data) - - async def write_text( - self, - data: str, - encoding: str | None = None, - errors: str | None = None, - newline: str | None = None, - ) -> int: - # Path.write_text() does not support the "newline" parameter before Python 3.10 - def sync_write_text() -> int: - with self._path.open( - "w", encoding=encoding, errors=errors, newline=newline - ) as fp: - return fp.write(data) - - return await to_thread.run_sync(sync_write_text) - - -PathLike.register(Path) diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_resources.py b/venv/lib/python3.12/site-packages/anyio/_core/_resources.py deleted file mode 100644 index b9a5344..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_resources.py +++ /dev/null @@ -1,18 +0,0 @@ -from __future__ import annotations - -from ..abc import AsyncResource -from ._tasks import CancelScope - - -async def aclose_forcefully(resource: AsyncResource) -> None: - """ - Close an asynchronous resource in a cancelled scope. - - Doing this closes the resource without waiting on anything. - - :param resource: the resource to close - - """ - with CancelScope() as scope: - scope.cancel() - await resource.aclose() diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_signals.py b/venv/lib/python3.12/site-packages/anyio/_core/_signals.py deleted file mode 100644 index f3451d3..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_signals.py +++ /dev/null @@ -1,27 +0,0 @@ -from __future__ import annotations - -from collections.abc import AsyncIterator -from contextlib import AbstractContextManager -from signal import Signals - -from ._eventloop import get_async_backend - - -def open_signal_receiver( - *signals: Signals, -) -> AbstractContextManager[AsyncIterator[Signals]]: - """ - Start receiving operating system signals. - - :param signals: signals to receive (e.g. ``signal.SIGINT``) - :return: an asynchronous context manager for an asynchronous iterator which yields - signal numbers - - .. warning:: Windows does not support signals natively so it is best to avoid - relying on this in cross-platform applications. - - .. warning:: On asyncio, this permanently replaces any previous signal handler for - the given signals, as set via :meth:`~asyncio.loop.add_signal_handler`. - - """ - return get_async_backend().open_signal_receiver(*signals) diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_sockets.py b/venv/lib/python3.12/site-packages/anyio/_core/_sockets.py deleted file mode 100644 index 054bcdd..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_sockets.py +++ /dev/null @@ -1,792 +0,0 @@ -from __future__ import annotations - -import errno -import os -import socket -import ssl -import stat -import sys -from collections.abc import Awaitable -from ipaddress import IPv6Address, ip_address -from os import PathLike, chmod -from socket import AddressFamily, SocketKind -from typing import TYPE_CHECKING, Any, Literal, cast, overload - -from .. import to_thread -from ..abc import ( - ConnectedUDPSocket, - ConnectedUNIXDatagramSocket, - IPAddressType, - IPSockAddrType, - SocketListener, - SocketStream, - UDPSocket, - UNIXDatagramSocket, - UNIXSocketStream, -) -from ..streams.stapled import MultiListener -from ..streams.tls import TLSStream -from ._eventloop import get_async_backend -from ._resources import aclose_forcefully -from ._synchronization import Event -from ._tasks import create_task_group, move_on_after - -if TYPE_CHECKING: - from _typeshed import FileDescriptorLike -else: - FileDescriptorLike = object - -if sys.version_info < (3, 11): - from exceptiongroup import ExceptionGroup - -if sys.version_info < (3, 13): - from typing_extensions import deprecated -else: - from warnings import deprecated - -IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) # https://bugs.python.org/issue29515 - -AnyIPAddressFamily = Literal[ - AddressFamily.AF_UNSPEC, AddressFamily.AF_INET, AddressFamily.AF_INET6 -] -IPAddressFamily = Literal[AddressFamily.AF_INET, AddressFamily.AF_INET6] - - -# tls_hostname given -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - ssl_context: ssl.SSLContext | None = ..., - tls_standard_compatible: bool = ..., - tls_hostname: str, - happy_eyeballs_delay: float = ..., -) -> TLSStream: ... - - -# ssl_context given -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - ssl_context: ssl.SSLContext, - tls_standard_compatible: bool = ..., - tls_hostname: str | None = ..., - happy_eyeballs_delay: float = ..., -) -> TLSStream: ... - - -# tls=True -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - tls: Literal[True], - ssl_context: ssl.SSLContext | None = ..., - tls_standard_compatible: bool = ..., - tls_hostname: str | None = ..., - happy_eyeballs_delay: float = ..., -) -> TLSStream: ... - - -# tls=False -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - tls: Literal[False], - ssl_context: ssl.SSLContext | None = ..., - tls_standard_compatible: bool = ..., - tls_hostname: str | None = ..., - happy_eyeballs_delay: float = ..., -) -> SocketStream: ... - - -# No TLS arguments -@overload -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = ..., - happy_eyeballs_delay: float = ..., -) -> SocketStream: ... - - -async def connect_tcp( - remote_host: IPAddressType, - remote_port: int, - *, - local_host: IPAddressType | None = None, - tls: bool = False, - ssl_context: ssl.SSLContext | None = None, - tls_standard_compatible: bool = True, - tls_hostname: str | None = None, - happy_eyeballs_delay: float = 0.25, -) -> SocketStream | TLSStream: - """ - Connect to a host using the TCP protocol. - - This function implements the stateless version of the Happy Eyeballs algorithm (RFC - 6555). If ``remote_host`` is a host name that resolves to multiple IP addresses, - each one is tried until one connection attempt succeeds. If the first attempt does - not connected within 250 milliseconds, a second attempt is started using the next - address in the list, and so on. On IPv6 enabled systems, an IPv6 address (if - available) is tried first. - - When the connection has been established, a TLS handshake will be done if either - ``ssl_context`` or ``tls_hostname`` is not ``None``, or if ``tls`` is ``True``. - - :param remote_host: the IP address or host name to connect to - :param remote_port: port on the target host to connect to - :param local_host: the interface address or name to bind the socket to before - connecting - :param tls: ``True`` to do a TLS handshake with the connected stream and return a - :class:`~anyio.streams.tls.TLSStream` instead - :param ssl_context: the SSL context object to use (if omitted, a default context is - created) - :param tls_standard_compatible: If ``True``, performs the TLS shutdown handshake - before closing the stream and requires that the server does this as well. - Otherwise, :exc:`~ssl.SSLEOFError` may be raised during reads from the stream. - Some protocols, such as HTTP, require this option to be ``False``. - See :meth:`~ssl.SSLContext.wrap_socket` for details. - :param tls_hostname: host name to check the server certificate against (defaults to - the value of ``remote_host``) - :param happy_eyeballs_delay: delay (in seconds) before starting the next connection - attempt - :return: a socket stream object if no TLS handshake was done, otherwise a TLS stream - :raises OSError: if the connection attempt fails - - """ - # Placed here due to https://github.com/python/mypy/issues/7057 - connected_stream: SocketStream | None = None - - async def try_connect(remote_host: str, event: Event) -> None: - nonlocal connected_stream - try: - stream = await asynclib.connect_tcp(remote_host, remote_port, local_address) - except OSError as exc: - oserrors.append(exc) - return - else: - if connected_stream is None: - connected_stream = stream - tg.cancel_scope.cancel() - else: - await stream.aclose() - finally: - event.set() - - asynclib = get_async_backend() - local_address: IPSockAddrType | None = None - family = socket.AF_UNSPEC - if local_host: - gai_res = await getaddrinfo(str(local_host), None) - family, *_, local_address = gai_res[0] - - target_host = str(remote_host) - try: - addr_obj = ip_address(remote_host) - except ValueError: - addr_obj = None - - if addr_obj is not None: - if isinstance(addr_obj, IPv6Address): - target_addrs = [(socket.AF_INET6, addr_obj.compressed)] - else: - target_addrs = [(socket.AF_INET, addr_obj.compressed)] - else: - # getaddrinfo() will raise an exception if name resolution fails - gai_res = await getaddrinfo( - target_host, remote_port, family=family, type=socket.SOCK_STREAM - ) - - # Organize the list so that the first address is an IPv6 address (if available) - # and the second one is an IPv4 addresses. The rest can be in whatever order. - v6_found = v4_found = False - target_addrs = [] - for af, *rest, sa in gai_res: - if af == socket.AF_INET6 and not v6_found: - v6_found = True - target_addrs.insert(0, (af, sa[0])) - elif af == socket.AF_INET and not v4_found and v6_found: - v4_found = True - target_addrs.insert(1, (af, sa[0])) - else: - target_addrs.append((af, sa[0])) - - oserrors: list[OSError] = [] - try: - async with create_task_group() as tg: - for i, (af, addr) in enumerate(target_addrs): - event = Event() - tg.start_soon(try_connect, addr, event) - with move_on_after(happy_eyeballs_delay): - await event.wait() - - if connected_stream is None: - cause = ( - oserrors[0] - if len(oserrors) == 1 - else ExceptionGroup("multiple connection attempts failed", oserrors) - ) - raise OSError("All connection attempts failed") from cause - finally: - oserrors.clear() - - if tls or tls_hostname or ssl_context: - try: - return await TLSStream.wrap( - connected_stream, - server_side=False, - hostname=tls_hostname or str(remote_host), - ssl_context=ssl_context, - standard_compatible=tls_standard_compatible, - ) - except BaseException: - await aclose_forcefully(connected_stream) - raise - - return connected_stream - - -async def connect_unix(path: str | bytes | PathLike[Any]) -> UNIXSocketStream: - """ - Connect to the given UNIX socket. - - Not available on Windows. - - :param path: path to the socket - :return: a socket stream object - - """ - path = os.fspath(path) - return await get_async_backend().connect_unix(path) - - -async def create_tcp_listener( - *, - local_host: IPAddressType | None = None, - local_port: int = 0, - family: AnyIPAddressFamily = socket.AddressFamily.AF_UNSPEC, - backlog: int = 65536, - reuse_port: bool = False, -) -> MultiListener[SocketStream]: - """ - Create a TCP socket listener. - - :param local_port: port number to listen on - :param local_host: IP address of the interface to listen on. If omitted, listen on - all IPv4 and IPv6 interfaces. To listen on all interfaces on a specific address - family, use ``0.0.0.0`` for IPv4 or ``::`` for IPv6. - :param family: address family (used if ``local_host`` was omitted) - :param backlog: maximum number of queued incoming connections (up to a maximum of - 2**16, or 65536) - :param reuse_port: ``True`` to allow multiple sockets to bind to the same - address/port (not supported on Windows) - :return: a list of listener objects - - """ - asynclib = get_async_backend() - backlog = min(backlog, 65536) - local_host = str(local_host) if local_host is not None else None - gai_res = await getaddrinfo( - local_host, - local_port, - family=family, - type=socket.SocketKind.SOCK_STREAM if sys.platform == "win32" else 0, - flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, - ) - listeners: list[SocketListener] = [] - try: - # The set() is here to work around a glibc bug: - # https://sourceware.org/bugzilla/show_bug.cgi?id=14969 - sockaddr: tuple[str, int] | tuple[str, int, int, int] - for fam, kind, *_, sockaddr in sorted(set(gai_res)): - # Workaround for an uvloop bug where we don't get the correct scope ID for - # IPv6 link-local addresses when passing type=socket.SOCK_STREAM to - # getaddrinfo(): https://github.com/MagicStack/uvloop/issues/539 - if sys.platform != "win32" and kind is not SocketKind.SOCK_STREAM: - continue - - raw_socket = socket.socket(fam) - raw_socket.setblocking(False) - - # For Windows, enable exclusive address use. For others, enable address - # reuse. - if sys.platform == "win32": - raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1) - else: - raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - - if reuse_port: - raw_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) - - # If only IPv6 was requested, disable dual stack operation - if fam == socket.AF_INET6: - raw_socket.setsockopt(IPPROTO_IPV6, socket.IPV6_V6ONLY, 1) - - # Workaround for #554 - if "%" in sockaddr[0]: - addr, scope_id = sockaddr[0].split("%", 1) - sockaddr = (addr, sockaddr[1], 0, int(scope_id)) - - raw_socket.bind(sockaddr) - raw_socket.listen(backlog) - listener = asynclib.create_tcp_listener(raw_socket) - listeners.append(listener) - except BaseException: - for listener in listeners: - await listener.aclose() - - raise - - return MultiListener(listeners) - - -async def create_unix_listener( - path: str | bytes | PathLike[Any], - *, - mode: int | None = None, - backlog: int = 65536, -) -> SocketListener: - """ - Create a UNIX socket listener. - - Not available on Windows. - - :param path: path of the socket - :param mode: permissions to set on the socket - :param backlog: maximum number of queued incoming connections (up to a maximum of - 2**16, or 65536) - :return: a listener object - - .. versionchanged:: 3.0 - If a socket already exists on the file system in the given path, it will be - removed first. - - """ - backlog = min(backlog, 65536) - raw_socket = await setup_unix_local_socket(path, mode, socket.SOCK_STREAM) - try: - raw_socket.listen(backlog) - return get_async_backend().create_unix_listener(raw_socket) - except BaseException: - raw_socket.close() - raise - - -async def create_udp_socket( - family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, - *, - local_host: IPAddressType | None = None, - local_port: int = 0, - reuse_port: bool = False, -) -> UDPSocket: - """ - Create a UDP socket. - - If ``port`` has been given, the socket will be bound to this port on the local - machine, making this socket suitable for providing UDP based services. - - :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically - determined from ``local_host`` if omitted - :param local_host: IP address or host name of the local interface to bind to - :param local_port: local port to bind to - :param reuse_port: ``True`` to allow multiple sockets to bind to the same - address/port (not supported on Windows) - :return: a UDP socket - - """ - if family is AddressFamily.AF_UNSPEC and not local_host: - raise ValueError('Either "family" or "local_host" must be given') - - if local_host: - gai_res = await getaddrinfo( - str(local_host), - local_port, - family=family, - type=socket.SOCK_DGRAM, - flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, - ) - family = cast(AnyIPAddressFamily, gai_res[0][0]) - local_address = gai_res[0][-1] - elif family is AddressFamily.AF_INET6: - local_address = ("::", 0) - else: - local_address = ("0.0.0.0", 0) - - sock = await get_async_backend().create_udp_socket( - family, local_address, None, reuse_port - ) - return cast(UDPSocket, sock) - - -async def create_connected_udp_socket( - remote_host: IPAddressType, - remote_port: int, - *, - family: AnyIPAddressFamily = AddressFamily.AF_UNSPEC, - local_host: IPAddressType | None = None, - local_port: int = 0, - reuse_port: bool = False, -) -> ConnectedUDPSocket: - """ - Create a connected UDP socket. - - Connected UDP sockets can only communicate with the specified remote host/port, an - any packets sent from other sources are dropped. - - :param remote_host: remote host to set as the default target - :param remote_port: port on the remote host to set as the default target - :param family: address family (``AF_INET`` or ``AF_INET6``) – automatically - determined from ``local_host`` or ``remote_host`` if omitted - :param local_host: IP address or host name of the local interface to bind to - :param local_port: local port to bind to - :param reuse_port: ``True`` to allow multiple sockets to bind to the same - address/port (not supported on Windows) - :return: a connected UDP socket - - """ - local_address = None - if local_host: - gai_res = await getaddrinfo( - str(local_host), - local_port, - family=family, - type=socket.SOCK_DGRAM, - flags=socket.AI_PASSIVE | socket.AI_ADDRCONFIG, - ) - family = cast(AnyIPAddressFamily, gai_res[0][0]) - local_address = gai_res[0][-1] - - gai_res = await getaddrinfo( - str(remote_host), remote_port, family=family, type=socket.SOCK_DGRAM - ) - family = cast(AnyIPAddressFamily, gai_res[0][0]) - remote_address = gai_res[0][-1] - - sock = await get_async_backend().create_udp_socket( - family, local_address, remote_address, reuse_port - ) - return cast(ConnectedUDPSocket, sock) - - -async def create_unix_datagram_socket( - *, - local_path: None | str | bytes | PathLike[Any] = None, - local_mode: int | None = None, -) -> UNIXDatagramSocket: - """ - Create a UNIX datagram socket. - - Not available on Windows. - - If ``local_path`` has been given, the socket will be bound to this path, making this - socket suitable for receiving datagrams from other processes. Other processes can - send datagrams to this socket only if ``local_path`` is set. - - If a socket already exists on the file system in the ``local_path``, it will be - removed first. - - :param local_path: the path on which to bind to - :param local_mode: permissions to set on the local socket - :return: a UNIX datagram socket - - """ - raw_socket = await setup_unix_local_socket( - local_path, local_mode, socket.SOCK_DGRAM - ) - return await get_async_backend().create_unix_datagram_socket(raw_socket, None) - - -async def create_connected_unix_datagram_socket( - remote_path: str | bytes | PathLike[Any], - *, - local_path: None | str | bytes | PathLike[Any] = None, - local_mode: int | None = None, -) -> ConnectedUNIXDatagramSocket: - """ - Create a connected UNIX datagram socket. - - Connected datagram sockets can only communicate with the specified remote path. - - If ``local_path`` has been given, the socket will be bound to this path, making - this socket suitable for receiving datagrams from other processes. Other processes - can send datagrams to this socket only if ``local_path`` is set. - - If a socket already exists on the file system in the ``local_path``, it will be - removed first. - - :param remote_path: the path to set as the default target - :param local_path: the path on which to bind to - :param local_mode: permissions to set on the local socket - :return: a connected UNIX datagram socket - - """ - remote_path = os.fspath(remote_path) - raw_socket = await setup_unix_local_socket( - local_path, local_mode, socket.SOCK_DGRAM - ) - return await get_async_backend().create_unix_datagram_socket( - raw_socket, remote_path - ) - - -async def getaddrinfo( - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, -) -> list[tuple[AddressFamily, SocketKind, int, str, tuple[str, int]]]: - """ - Look up a numeric IP address given a host name. - - Internationalized domain names are translated according to the (non-transitional) - IDNA 2008 standard. - - .. note:: 4-tuple IPv6 socket addresses are automatically converted to 2-tuples of - (host, port), unlike what :func:`socket.getaddrinfo` does. - - :param host: host name - :param port: port number - :param family: socket family (`'AF_INET``, ...) - :param type: socket type (``SOCK_STREAM``, ...) - :param proto: protocol number - :param flags: flags to pass to upstream ``getaddrinfo()`` - :return: list of tuples containing (family, type, proto, canonname, sockaddr) - - .. seealso:: :func:`socket.getaddrinfo` - - """ - # Handle unicode hostnames - if isinstance(host, str): - try: - encoded_host: bytes | None = host.encode("ascii") - except UnicodeEncodeError: - import idna - - encoded_host = idna.encode(host, uts46=True) - else: - encoded_host = host - - gai_res = await get_async_backend().getaddrinfo( - encoded_host, port, family=family, type=type, proto=proto, flags=flags - ) - return [ - (family, type, proto, canonname, convert_ipv6_sockaddr(sockaddr)) - for family, type, proto, canonname, sockaddr in gai_res - # filter out IPv6 results when IPv6 is disabled - if not isinstance(sockaddr[0], int) - ] - - -def getnameinfo(sockaddr: IPSockAddrType, flags: int = 0) -> Awaitable[tuple[str, str]]: - """ - Look up the host name of an IP address. - - :param sockaddr: socket address (e.g. (ipaddress, port) for IPv4) - :param flags: flags to pass to upstream ``getnameinfo()`` - :return: a tuple of (host name, service name) - - .. seealso:: :func:`socket.getnameinfo` - - """ - return get_async_backend().getnameinfo(sockaddr, flags) - - -@deprecated("This function is deprecated; use `wait_readable` instead") -def wait_socket_readable(sock: socket.socket) -> Awaitable[None]: - """ - .. deprecated:: 4.7.0 - Use :func:`wait_readable` instead. - - Wait until the given socket has data to be read. - - .. warning:: Only use this on raw sockets that have not been wrapped by any higher - level constructs like socket streams! - - :param sock: a socket object - :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the - socket to become readable - :raises ~anyio.BusyResourceError: if another task is already waiting for the socket - to become readable - - """ - return get_async_backend().wait_readable(sock.fileno()) - - -@deprecated("This function is deprecated; use `wait_writable` instead") -def wait_socket_writable(sock: socket.socket) -> Awaitable[None]: - """ - .. deprecated:: 4.7.0 - Use :func:`wait_writable` instead. - - Wait until the given socket can be written to. - - This does **NOT** work on Windows when using the asyncio backend with a proactor - event loop (default on py3.8+). - - .. warning:: Only use this on raw sockets that have not been wrapped by any higher - level constructs like socket streams! - - :param sock: a socket object - :raises ~anyio.ClosedResourceError: if the socket was closed while waiting for the - socket to become writable - :raises ~anyio.BusyResourceError: if another task is already waiting for the socket - to become writable - - """ - return get_async_backend().wait_writable(sock.fileno()) - - -def wait_readable(obj: FileDescriptorLike) -> Awaitable[None]: - """ - Wait until the given object has data to be read. - - On Unix systems, ``obj`` must either be an integer file descriptor, or else an - object with a ``.fileno()`` method which returns an integer file descriptor. Any - kind of file descriptor can be passed, though the exact semantics will depend on - your kernel. For example, this probably won't do anything useful for on-disk files. - - On Windows systems, ``obj`` must either be an integer ``SOCKET`` handle, or else an - object with a ``.fileno()`` method which returns an integer ``SOCKET`` handle. File - descriptors aren't supported, and neither are handles that refer to anything besides - a ``SOCKET``. - - On backends where this functionality is not natively provided (asyncio - ``ProactorEventLoop`` on Windows), it is provided using a separate selector thread - which is set to shut down when the interpreter shuts down. - - .. warning:: Don't use this on raw sockets that have been wrapped by any higher - level constructs like socket streams! - - :param obj: an object with a ``.fileno()`` method or an integer handle - :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the - object to become readable - :raises ~anyio.BusyResourceError: if another task is already waiting for the object - to become readable - - """ - return get_async_backend().wait_readable(obj) - - -def wait_writable(obj: FileDescriptorLike) -> Awaitable[None]: - """ - Wait until the given object can be written to. - - :param obj: an object with a ``.fileno()`` method or an integer handle - :raises ~anyio.ClosedResourceError: if the object was closed while waiting for the - object to become writable - :raises ~anyio.BusyResourceError: if another task is already waiting for the object - to become writable - - .. seealso:: See the documentation of :func:`wait_readable` for the definition of - ``obj`` and notes on backend compatibility. - - .. warning:: Don't use this on raw sockets that have been wrapped by any higher - level constructs like socket streams! - - """ - return get_async_backend().wait_writable(obj) - - -# -# Private API -# - - -def convert_ipv6_sockaddr( - sockaddr: tuple[str, int, int, int] | tuple[str, int], -) -> tuple[str, int]: - """ - Convert a 4-tuple IPv6 socket address to a 2-tuple (address, port) format. - - If the scope ID is nonzero, it is added to the address, separated with ``%``. - Otherwise the flow id and scope id are simply cut off from the tuple. - Any other kinds of socket addresses are returned as-is. - - :param sockaddr: the result of :meth:`~socket.socket.getsockname` - :return: the converted socket address - - """ - # This is more complicated than it should be because of MyPy - if isinstance(sockaddr, tuple) and len(sockaddr) == 4: - host, port, flowinfo, scope_id = sockaddr - if scope_id: - # PyPy (as of v7.3.11) leaves the interface name in the result, so - # we discard it and only get the scope ID from the end - # (https://foss.heptapod.net/pypy/pypy/-/issues/3938) - host = host.split("%")[0] - - # Add scope_id to the address - return f"{host}%{scope_id}", port - else: - return host, port - else: - return sockaddr - - -async def setup_unix_local_socket( - path: None | str | bytes | PathLike[Any], - mode: int | None, - socktype: int, -) -> socket.socket: - """ - Create a UNIX local socket object, deleting the socket at the given path if it - exists. - - Not available on Windows. - - :param path: path of the socket - :param mode: permissions to set on the socket - :param socktype: socket.SOCK_STREAM or socket.SOCK_DGRAM - - """ - path_str: str | None - if path is not None: - path_str = os.fsdecode(path) - - # Linux abstract namespace sockets aren't backed by a concrete file so skip stat call - if not path_str.startswith("\0"): - # Copied from pathlib... - try: - stat_result = os.stat(path) - except OSError as e: - if e.errno not in ( - errno.ENOENT, - errno.ENOTDIR, - errno.EBADF, - errno.ELOOP, - ): - raise - else: - if stat.S_ISSOCK(stat_result.st_mode): - os.unlink(path) - else: - path_str = None - - raw_socket = socket.socket(socket.AF_UNIX, socktype) - raw_socket.setblocking(False) - - if path_str is not None: - try: - await to_thread.run_sync(raw_socket.bind, path_str, abandon_on_cancel=True) - if mode is not None: - await to_thread.run_sync(chmod, path_str, mode, abandon_on_cancel=True) - except BaseException: - raw_socket.close() - raise - - return raw_socket diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_streams.py b/venv/lib/python3.12/site-packages/anyio/_core/_streams.py deleted file mode 100644 index 6a9814e..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_streams.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import annotations - -import math -from typing import TypeVar -from warnings import warn - -from ..streams.memory import ( - MemoryObjectReceiveStream, - MemoryObjectSendStream, - MemoryObjectStreamState, -) - -T_Item = TypeVar("T_Item") - - -class create_memory_object_stream( - tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]], -): - """ - Create a memory object stream. - - The stream's item type can be annotated like - :func:`create_memory_object_stream[T_Item]`. - - :param max_buffer_size: number of items held in the buffer until ``send()`` starts - blocking - :param item_type: old way of marking the streams with the right generic type for - static typing (does nothing on AnyIO 4) - - .. deprecated:: 4.0 - Use ``create_memory_object_stream[YourItemType](...)`` instead. - :return: a tuple of (send stream, receive stream) - - """ - - def __new__( # type: ignore[misc] - cls, max_buffer_size: float = 0, item_type: object = None - ) -> tuple[MemoryObjectSendStream[T_Item], MemoryObjectReceiveStream[T_Item]]: - if max_buffer_size != math.inf and not isinstance(max_buffer_size, int): - raise ValueError("max_buffer_size must be either an integer or math.inf") - if max_buffer_size < 0: - raise ValueError("max_buffer_size cannot be negative") - if item_type is not None: - warn( - "The item_type argument has been deprecated in AnyIO 4.0. " - "Use create_memory_object_stream[YourItemType](...) instead.", - DeprecationWarning, - stacklevel=2, - ) - - state = MemoryObjectStreamState[T_Item](max_buffer_size) - return (MemoryObjectSendStream(state), MemoryObjectReceiveStream(state)) diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_subprocesses.py b/venv/lib/python3.12/site-packages/anyio/_core/_subprocesses.py deleted file mode 100644 index 36d9b30..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_subprocesses.py +++ /dev/null @@ -1,202 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import AsyncIterable, Iterable, Mapping, Sequence -from io import BytesIO -from os import PathLike -from subprocess import PIPE, CalledProcessError, CompletedProcess -from typing import IO, Any, Union, cast - -from ..abc import Process -from ._eventloop import get_async_backend -from ._tasks import create_task_group - -if sys.version_info >= (3, 10): - from typing import TypeAlias -else: - from typing_extensions import TypeAlias - -StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"] - - -async def run_process( - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - input: bytes | None = None, - stdin: int | IO[Any] | None = None, - stdout: int | IO[Any] | None = PIPE, - stderr: int | IO[Any] | None = PIPE, - check: bool = True, - cwd: StrOrBytesPath | None = None, - env: Mapping[str, str] | None = None, - startupinfo: Any = None, - creationflags: int = 0, - start_new_session: bool = False, - pass_fds: Sequence[int] = (), - user: str | int | None = None, - group: str | int | None = None, - extra_groups: Iterable[str | int] | None = None, - umask: int = -1, -) -> CompletedProcess[bytes]: - """ - Run an external command in a subprocess and wait until it completes. - - .. seealso:: :func:`subprocess.run` - - :param command: either a string to pass to the shell, or an iterable of strings - containing the executable name or path and its arguments - :param input: bytes passed to the standard input of the subprocess - :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - a file-like object, or `None`; ``input`` overrides this - :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - a file-like object, or `None` - :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - :data:`subprocess.STDOUT`, a file-like object, or `None` - :param check: if ``True``, raise :exc:`~subprocess.CalledProcessError` if the - process terminates with a return code other than 0 - :param cwd: If not ``None``, change the working directory to this before running the - command - :param env: if not ``None``, this mapping replaces the inherited environment - variables from the parent process - :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used - to specify process startup parameters (Windows only) - :param creationflags: flags that can be used to control the creation of the - subprocess (see :class:`subprocess.Popen` for the specifics) - :param start_new_session: if ``true`` the setsid() system call will be made in the - child process prior to the execution of the subprocess. (POSIX only) - :param pass_fds: sequence of file descriptors to keep open between the parent and - child processes. (POSIX only) - :param user: effective user to run the process as (Python >= 3.9, POSIX only) - :param group: effective group to run the process as (Python >= 3.9, POSIX only) - :param extra_groups: supplementary groups to set in the subprocess (Python >= 3.9, - POSIX only) - :param umask: if not negative, this umask is applied in the child process before - running the given command (Python >= 3.9, POSIX only) - :return: an object representing the completed process - :raises ~subprocess.CalledProcessError: if ``check`` is ``True`` and the process - exits with a nonzero return code - - """ - - async def drain_stream(stream: AsyncIterable[bytes], index: int) -> None: - buffer = BytesIO() - async for chunk in stream: - buffer.write(chunk) - - stream_contents[index] = buffer.getvalue() - - if stdin is not None and input is not None: - raise ValueError("only one of stdin and input is allowed") - - async with await open_process( - command, - stdin=PIPE if input else stdin, - stdout=stdout, - stderr=stderr, - cwd=cwd, - env=env, - startupinfo=startupinfo, - creationflags=creationflags, - start_new_session=start_new_session, - pass_fds=pass_fds, - user=user, - group=group, - extra_groups=extra_groups, - umask=umask, - ) as process: - stream_contents: list[bytes | None] = [None, None] - async with create_task_group() as tg: - if process.stdout: - tg.start_soon(drain_stream, process.stdout, 0) - - if process.stderr: - tg.start_soon(drain_stream, process.stderr, 1) - - if process.stdin and input: - await process.stdin.send(input) - await process.stdin.aclose() - - await process.wait() - - output, errors = stream_contents - if check and process.returncode != 0: - raise CalledProcessError(cast(int, process.returncode), command, output, errors) - - return CompletedProcess(command, cast(int, process.returncode), output, errors) - - -async def open_process( - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None = PIPE, - stdout: int | IO[Any] | None = PIPE, - stderr: int | IO[Any] | None = PIPE, - cwd: StrOrBytesPath | None = None, - env: Mapping[str, str] | None = None, - startupinfo: Any = None, - creationflags: int = 0, - start_new_session: bool = False, - pass_fds: Sequence[int] = (), - user: str | int | None = None, - group: str | int | None = None, - extra_groups: Iterable[str | int] | None = None, - umask: int = -1, -) -> Process: - """ - Start an external command in a subprocess. - - .. seealso:: :class:`subprocess.Popen` - - :param command: either a string to pass to the shell, or an iterable of strings - containing the executable name or path and its arguments - :param stdin: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, a - file-like object, or ``None`` - :param stdout: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - a file-like object, or ``None`` - :param stderr: one of :data:`subprocess.PIPE`, :data:`subprocess.DEVNULL`, - :data:`subprocess.STDOUT`, a file-like object, or ``None`` - :param cwd: If not ``None``, the working directory is changed before executing - :param env: If env is not ``None``, it must be a mapping that defines the - environment variables for the new process - :param creationflags: flags that can be used to control the creation of the - subprocess (see :class:`subprocess.Popen` for the specifics) - :param startupinfo: an instance of :class:`subprocess.STARTUPINFO` that can be used - to specify process startup parameters (Windows only) - :param start_new_session: if ``true`` the setsid() system call will be made in the - child process prior to the execution of the subprocess. (POSIX only) - :param pass_fds: sequence of file descriptors to keep open between the parent and - child processes. (POSIX only) - :param user: effective user to run the process as (POSIX only) - :param group: effective group to run the process as (POSIX only) - :param extra_groups: supplementary groups to set in the subprocess (POSIX only) - :param umask: if not negative, this umask is applied in the child process before - running the given command (POSIX only) - :return: an asynchronous process object - - """ - kwargs: dict[str, Any] = {} - if user is not None: - kwargs["user"] = user - - if group is not None: - kwargs["group"] = group - - if extra_groups is not None: - kwargs["extra_groups"] = group - - if umask >= 0: - kwargs["umask"] = umask - - return await get_async_backend().open_process( - command, - stdin=stdin, - stdout=stdout, - stderr=stderr, - cwd=cwd, - env=env, - startupinfo=startupinfo, - creationflags=creationflags, - start_new_session=start_new_session, - pass_fds=pass_fds, - **kwargs, - ) diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_synchronization.py b/venv/lib/python3.12/site-packages/anyio/_core/_synchronization.py deleted file mode 100644 index a633132..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_synchronization.py +++ /dev/null @@ -1,732 +0,0 @@ -from __future__ import annotations - -import math -from collections import deque -from dataclasses import dataclass -from types import TracebackType - -from sniffio import AsyncLibraryNotFoundError - -from ..lowlevel import checkpoint -from ._eventloop import get_async_backend -from ._exceptions import BusyResourceError -from ._tasks import CancelScope -from ._testing import TaskInfo, get_current_task - - -@dataclass(frozen=True) -class EventStatistics: - """ - :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Event.wait` - """ - - tasks_waiting: int - - -@dataclass(frozen=True) -class CapacityLimiterStatistics: - """ - :ivar int borrowed_tokens: number of tokens currently borrowed by tasks - :ivar float total_tokens: total number of available tokens - :ivar tuple borrowers: tasks or other objects currently holding tokens borrowed from - this limiter - :ivar int tasks_waiting: number of tasks waiting on - :meth:`~.CapacityLimiter.acquire` or - :meth:`~.CapacityLimiter.acquire_on_behalf_of` - """ - - borrowed_tokens: int - total_tokens: float - borrowers: tuple[object, ...] - tasks_waiting: int - - -@dataclass(frozen=True) -class LockStatistics: - """ - :ivar bool locked: flag indicating if this lock is locked or not - :ivar ~anyio.TaskInfo owner: task currently holding the lock (or ``None`` if the - lock is not held by any task) - :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Lock.acquire` - """ - - locked: bool - owner: TaskInfo | None - tasks_waiting: int - - -@dataclass(frozen=True) -class ConditionStatistics: - """ - :ivar int tasks_waiting: number of tasks blocked on :meth:`~.Condition.wait` - :ivar ~anyio.LockStatistics lock_statistics: statistics of the underlying - :class:`~.Lock` - """ - - tasks_waiting: int - lock_statistics: LockStatistics - - -@dataclass(frozen=True) -class SemaphoreStatistics: - """ - :ivar int tasks_waiting: number of tasks waiting on :meth:`~.Semaphore.acquire` - - """ - - tasks_waiting: int - - -class Event: - def __new__(cls) -> Event: - try: - return get_async_backend().create_event() - except AsyncLibraryNotFoundError: - return EventAdapter() - - def set(self) -> None: - """Set the flag, notifying all listeners.""" - raise NotImplementedError - - def is_set(self) -> bool: - """Return ``True`` if the flag is set, ``False`` if not.""" - raise NotImplementedError - - async def wait(self) -> None: - """ - Wait until the flag has been set. - - If the flag has already been set when this method is called, it returns - immediately. - - """ - raise NotImplementedError - - def statistics(self) -> EventStatistics: - """Return statistics about the current state of this event.""" - raise NotImplementedError - - -class EventAdapter(Event): - _internal_event: Event | None = None - _is_set: bool = False - - def __new__(cls) -> EventAdapter: - return object.__new__(cls) - - @property - def _event(self) -> Event: - if self._internal_event is None: - self._internal_event = get_async_backend().create_event() - if self._is_set: - self._internal_event.set() - - return self._internal_event - - def set(self) -> None: - if self._internal_event is None: - self._is_set = True - else: - self._event.set() - - def is_set(self) -> bool: - if self._internal_event is None: - return self._is_set - - return self._internal_event.is_set() - - async def wait(self) -> None: - await self._event.wait() - - def statistics(self) -> EventStatistics: - if self._internal_event is None: - return EventStatistics(tasks_waiting=0) - - return self._internal_event.statistics() - - -class Lock: - def __new__(cls, *, fast_acquire: bool = False) -> Lock: - try: - return get_async_backend().create_lock(fast_acquire=fast_acquire) - except AsyncLibraryNotFoundError: - return LockAdapter(fast_acquire=fast_acquire) - - async def __aenter__(self) -> None: - await self.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - async def acquire(self) -> None: - """Acquire the lock.""" - raise NotImplementedError - - def acquire_nowait(self) -> None: - """ - Acquire the lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - raise NotImplementedError - - def release(self) -> None: - """Release the lock.""" - raise NotImplementedError - - def locked(self) -> bool: - """Return True if the lock is currently held.""" - raise NotImplementedError - - def statistics(self) -> LockStatistics: - """ - Return statistics about the current state of this lock. - - .. versionadded:: 3.0 - """ - raise NotImplementedError - - -class LockAdapter(Lock): - _internal_lock: Lock | None = None - - def __new__(cls, *, fast_acquire: bool = False) -> LockAdapter: - return object.__new__(cls) - - def __init__(self, *, fast_acquire: bool = False): - self._fast_acquire = fast_acquire - - @property - def _lock(self) -> Lock: - if self._internal_lock is None: - self._internal_lock = get_async_backend().create_lock( - fast_acquire=self._fast_acquire - ) - - return self._internal_lock - - async def __aenter__(self) -> None: - await self._lock.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - if self._internal_lock is not None: - self._internal_lock.release() - - async def acquire(self) -> None: - """Acquire the lock.""" - await self._lock.acquire() - - def acquire_nowait(self) -> None: - """ - Acquire the lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - self._lock.acquire_nowait() - - def release(self) -> None: - """Release the lock.""" - self._lock.release() - - def locked(self) -> bool: - """Return True if the lock is currently held.""" - return self._lock.locked() - - def statistics(self) -> LockStatistics: - """ - Return statistics about the current state of this lock. - - .. versionadded:: 3.0 - - """ - if self._internal_lock is None: - return LockStatistics(False, None, 0) - - return self._internal_lock.statistics() - - -class Condition: - _owner_task: TaskInfo | None = None - - def __init__(self, lock: Lock | None = None): - self._lock = lock or Lock() - self._waiters: deque[Event] = deque() - - async def __aenter__(self) -> None: - await self.acquire() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - def _check_acquired(self) -> None: - if self._owner_task != get_current_task(): - raise RuntimeError("The current task is not holding the underlying lock") - - async def acquire(self) -> None: - """Acquire the underlying lock.""" - await self._lock.acquire() - self._owner_task = get_current_task() - - def acquire_nowait(self) -> None: - """ - Acquire the underlying lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - self._lock.acquire_nowait() - self._owner_task = get_current_task() - - def release(self) -> None: - """Release the underlying lock.""" - self._lock.release() - - def locked(self) -> bool: - """Return True if the lock is set.""" - return self._lock.locked() - - def notify(self, n: int = 1) -> None: - """Notify exactly n listeners.""" - self._check_acquired() - for _ in range(n): - try: - event = self._waiters.popleft() - except IndexError: - break - - event.set() - - def notify_all(self) -> None: - """Notify all the listeners.""" - self._check_acquired() - for event in self._waiters: - event.set() - - self._waiters.clear() - - async def wait(self) -> None: - """Wait for a notification.""" - await checkpoint() - event = Event() - self._waiters.append(event) - self.release() - try: - await event.wait() - except BaseException: - if not event.is_set(): - self._waiters.remove(event) - - raise - finally: - with CancelScope(shield=True): - await self.acquire() - - def statistics(self) -> ConditionStatistics: - """ - Return statistics about the current state of this condition. - - .. versionadded:: 3.0 - """ - return ConditionStatistics(len(self._waiters), self._lock.statistics()) - - -class Semaphore: - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - try: - return get_async_backend().create_semaphore( - initial_value, max_value=max_value, fast_acquire=fast_acquire - ) - except AsyncLibraryNotFoundError: - return SemaphoreAdapter(initial_value, max_value=max_value) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ): - if not isinstance(initial_value, int): - raise TypeError("initial_value must be an integer") - if initial_value < 0: - raise ValueError("initial_value must be >= 0") - if max_value is not None: - if not isinstance(max_value, int): - raise TypeError("max_value must be an integer or None") - if max_value < initial_value: - raise ValueError( - "max_value must be equal to or higher than initial_value" - ) - - self._fast_acquire = fast_acquire - - async def __aenter__(self) -> Semaphore: - await self.acquire() - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.release() - - async def acquire(self) -> None: - """Decrement the semaphore value, blocking if necessary.""" - raise NotImplementedError - - def acquire_nowait(self) -> None: - """ - Acquire the underlying lock, without blocking. - - :raises ~anyio.WouldBlock: if the operation would block - - """ - raise NotImplementedError - - def release(self) -> None: - """Increment the semaphore value.""" - raise NotImplementedError - - @property - def value(self) -> int: - """The current value of the semaphore.""" - raise NotImplementedError - - @property - def max_value(self) -> int | None: - """The maximum value of the semaphore.""" - raise NotImplementedError - - def statistics(self) -> SemaphoreStatistics: - """ - Return statistics about the current state of this semaphore. - - .. versionadded:: 3.0 - """ - raise NotImplementedError - - -class SemaphoreAdapter(Semaphore): - _internal_semaphore: Semaphore | None = None - - def __new__( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> SemaphoreAdapter: - return object.__new__(cls) - - def __init__( - self, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> None: - super().__init__(initial_value, max_value=max_value, fast_acquire=fast_acquire) - self._initial_value = initial_value - self._max_value = max_value - - @property - def _semaphore(self) -> Semaphore: - if self._internal_semaphore is None: - self._internal_semaphore = get_async_backend().create_semaphore( - self._initial_value, max_value=self._max_value - ) - - return self._internal_semaphore - - async def acquire(self) -> None: - await self._semaphore.acquire() - - def acquire_nowait(self) -> None: - self._semaphore.acquire_nowait() - - def release(self) -> None: - self._semaphore.release() - - @property - def value(self) -> int: - if self._internal_semaphore is None: - return self._initial_value - - return self._semaphore.value - - @property - def max_value(self) -> int | None: - return self._max_value - - def statistics(self) -> SemaphoreStatistics: - if self._internal_semaphore is None: - return SemaphoreStatistics(tasks_waiting=0) - - return self._semaphore.statistics() - - -class CapacityLimiter: - def __new__(cls, total_tokens: float) -> CapacityLimiter: - try: - return get_async_backend().create_capacity_limiter(total_tokens) - except AsyncLibraryNotFoundError: - return CapacityLimiterAdapter(total_tokens) - - async def __aenter__(self) -> None: - raise NotImplementedError - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - raise NotImplementedError - - @property - def total_tokens(self) -> float: - """ - The total number of tokens available for borrowing. - - This is a read-write property. If the total number of tokens is increased, the - proportionate number of tasks waiting on this limiter will be granted their - tokens. - - .. versionchanged:: 3.0 - The property is now writable. - - """ - raise NotImplementedError - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - raise NotImplementedError - - @property - def borrowed_tokens(self) -> int: - """The number of tokens that have currently been borrowed.""" - raise NotImplementedError - - @property - def available_tokens(self) -> float: - """The number of tokens currently available to be borrowed""" - raise NotImplementedError - - def acquire_nowait(self) -> None: - """ - Acquire a token for the current task without waiting for one to become - available. - - :raises ~anyio.WouldBlock: if there are no tokens available for borrowing - - """ - raise NotImplementedError - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - """ - Acquire a token without waiting for one to become available. - - :param borrower: the entity borrowing a token - :raises ~anyio.WouldBlock: if there are no tokens available for borrowing - - """ - raise NotImplementedError - - async def acquire(self) -> None: - """ - Acquire a token for the current task, waiting if necessary for one to become - available. - - """ - raise NotImplementedError - - async def acquire_on_behalf_of(self, borrower: object) -> None: - """ - Acquire a token, waiting if necessary for one to become available. - - :param borrower: the entity borrowing a token - - """ - raise NotImplementedError - - def release(self) -> None: - """ - Release the token held by the current task. - - :raises RuntimeError: if the current task has not borrowed a token from this - limiter. - - """ - raise NotImplementedError - - def release_on_behalf_of(self, borrower: object) -> None: - """ - Release the token held by the given borrower. - - :raises RuntimeError: if the borrower has not borrowed a token from this - limiter. - - """ - raise NotImplementedError - - def statistics(self) -> CapacityLimiterStatistics: - """ - Return statistics about the current state of this limiter. - - .. versionadded:: 3.0 - - """ - raise NotImplementedError - - -class CapacityLimiterAdapter(CapacityLimiter): - _internal_limiter: CapacityLimiter | None = None - - def __new__(cls, total_tokens: float) -> CapacityLimiterAdapter: - return object.__new__(cls) - - def __init__(self, total_tokens: float) -> None: - self.total_tokens = total_tokens - - @property - def _limiter(self) -> CapacityLimiter: - if self._internal_limiter is None: - self._internal_limiter = get_async_backend().create_capacity_limiter( - self._total_tokens - ) - - return self._internal_limiter - - async def __aenter__(self) -> None: - await self._limiter.__aenter__() - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - return await self._limiter.__aexit__(exc_type, exc_val, exc_tb) - - @property - def total_tokens(self) -> float: - if self._internal_limiter is None: - return self._total_tokens - - return self._internal_limiter.total_tokens - - @total_tokens.setter - def total_tokens(self, value: float) -> None: - if not isinstance(value, int) and value is not math.inf: - raise TypeError("total_tokens must be an int or math.inf") - elif value < 1: - raise ValueError("total_tokens must be >= 1") - - if self._internal_limiter is None: - self._total_tokens = value - return - - self._limiter.total_tokens = value - - @property - def borrowed_tokens(self) -> int: - if self._internal_limiter is None: - return 0 - - return self._internal_limiter.borrowed_tokens - - @property - def available_tokens(self) -> float: - if self._internal_limiter is None: - return self._total_tokens - - return self._internal_limiter.available_tokens - - def acquire_nowait(self) -> None: - self._limiter.acquire_nowait() - - def acquire_on_behalf_of_nowait(self, borrower: object) -> None: - self._limiter.acquire_on_behalf_of_nowait(borrower) - - async def acquire(self) -> None: - await self._limiter.acquire() - - async def acquire_on_behalf_of(self, borrower: object) -> None: - await self._limiter.acquire_on_behalf_of(borrower) - - def release(self) -> None: - self._limiter.release() - - def release_on_behalf_of(self, borrower: object) -> None: - self._limiter.release_on_behalf_of(borrower) - - def statistics(self) -> CapacityLimiterStatistics: - if self._internal_limiter is None: - return CapacityLimiterStatistics( - borrowed_tokens=0, - total_tokens=self.total_tokens, - borrowers=(), - tasks_waiting=0, - ) - - return self._internal_limiter.statistics() - - -class ResourceGuard: - """ - A context manager for ensuring that a resource is only used by a single task at a - time. - - Entering this context manager while the previous has not exited it yet will trigger - :exc:`BusyResourceError`. - - :param action: the action to guard against (visible in the :exc:`BusyResourceError` - when triggered, e.g. "Another task is already {action} this resource") - - .. versionadded:: 4.1 - """ - - __slots__ = "action", "_guarded" - - def __init__(self, action: str = "using"): - self.action: str = action - self._guarded = False - - def __enter__(self) -> None: - if self._guarded: - raise BusyResourceError(self.action) - - self._guarded = True - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self._guarded = False diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_tasks.py b/venv/lib/python3.12/site-packages/anyio/_core/_tasks.py deleted file mode 100644 index fe49015..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_tasks.py +++ /dev/null @@ -1,158 +0,0 @@ -from __future__ import annotations - -import math -from collections.abc import Generator -from contextlib import contextmanager -from types import TracebackType - -from ..abc._tasks import TaskGroup, TaskStatus -from ._eventloop import get_async_backend - - -class _IgnoredTaskStatus(TaskStatus[object]): - def started(self, value: object = None) -> None: - pass - - -TASK_STATUS_IGNORED = _IgnoredTaskStatus() - - -class CancelScope: - """ - Wraps a unit of work that can be made separately cancellable. - - :param deadline: The time (clock value) when this scope is cancelled automatically - :param shield: ``True`` to shield the cancel scope from external cancellation - """ - - def __new__( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - return get_async_backend().create_cancel_scope(shield=shield, deadline=deadline) - - def cancel(self) -> None: - """Cancel this scope immediately.""" - raise NotImplementedError - - @property - def deadline(self) -> float: - """ - The time (clock value) when this scope is cancelled automatically. - - Will be ``float('inf')`` if no timeout has been set. - - """ - raise NotImplementedError - - @deadline.setter - def deadline(self, value: float) -> None: - raise NotImplementedError - - @property - def cancel_called(self) -> bool: - """``True`` if :meth:`cancel` has been called.""" - raise NotImplementedError - - @property - def cancelled_caught(self) -> bool: - """ - ``True`` if this scope suppressed a cancellation exception it itself raised. - - This is typically used to check if any work was interrupted, or to see if the - scope was cancelled due to its deadline being reached. The value will, however, - only be ``True`` if the cancellation was triggered by the scope itself (and not - an outer scope). - - """ - raise NotImplementedError - - @property - def shield(self) -> bool: - """ - ``True`` if this scope is shielded from external cancellation. - - While a scope is shielded, it will not receive cancellations from outside. - - """ - raise NotImplementedError - - @shield.setter - def shield(self, value: bool) -> None: - raise NotImplementedError - - def __enter__(self) -> CancelScope: - raise NotImplementedError - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - raise NotImplementedError - - -@contextmanager -def fail_after( - delay: float | None, shield: bool = False -) -> Generator[CancelScope, None, None]: - """ - Create a context manager which raises a :class:`TimeoutError` if does not finish in - time. - - :param delay: maximum allowed time (in seconds) before raising the exception, or - ``None`` to disable the timeout - :param shield: ``True`` to shield the cancel scope from external cancellation - :return: a context manager that yields a cancel scope - :rtype: :class:`~typing.ContextManager`\\[:class:`~anyio.CancelScope`\\] - - """ - current_time = get_async_backend().current_time - deadline = (current_time() + delay) if delay is not None else math.inf - with get_async_backend().create_cancel_scope( - deadline=deadline, shield=shield - ) as cancel_scope: - yield cancel_scope - - if cancel_scope.cancelled_caught and current_time() >= cancel_scope.deadline: - raise TimeoutError - - -def move_on_after(delay: float | None, shield: bool = False) -> CancelScope: - """ - Create a cancel scope with a deadline that expires after the given delay. - - :param delay: maximum allowed time (in seconds) before exiting the context block, or - ``None`` to disable the timeout - :param shield: ``True`` to shield the cancel scope from external cancellation - :return: a cancel scope - - """ - deadline = ( - (get_async_backend().current_time() + delay) if delay is not None else math.inf - ) - return get_async_backend().create_cancel_scope(deadline=deadline, shield=shield) - - -def current_effective_deadline() -> float: - """ - Return the nearest deadline among all the cancel scopes effective for the current - task. - - :return: a clock value from the event loop's internal clock (or ``float('inf')`` if - there is no deadline in effect, or ``float('-inf')`` if the current scope has - been cancelled) - :rtype: float - - """ - return get_async_backend().current_effective_deadline() - - -def create_task_group() -> TaskGroup: - """ - Create a task group. - - :return: a task group - - """ - return get_async_backend().create_task_group() diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_tempfile.py b/venv/lib/python3.12/site-packages/anyio/_core/_tempfile.py deleted file mode 100644 index 26d70ec..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_tempfile.py +++ /dev/null @@ -1,616 +0,0 @@ -from __future__ import annotations - -import os -import sys -import tempfile -from collections.abc import Iterable -from io import BytesIO, TextIOWrapper -from types import TracebackType -from typing import ( - TYPE_CHECKING, - Any, - AnyStr, - Generic, - overload, -) - -from .. import to_thread -from .._core._fileio import AsyncFile -from ..lowlevel import checkpoint_if_cancelled - -if TYPE_CHECKING: - from _typeshed import OpenBinaryMode, OpenTextMode, ReadableBuffer, WriteableBuffer - - -class TemporaryFile(Generic[AnyStr]): - """ - An asynchronous temporary file that is automatically created and cleaned up. - - This class provides an asynchronous context manager interface to a temporary file. - The file is created using Python's standard `tempfile.TemporaryFile` function in a - background thread, and is wrapped as an asynchronous file using `AsyncFile`. - - :param mode: The mode in which the file is opened. Defaults to "w+b". - :param buffering: The buffering policy (-1 means the default buffering). - :param encoding: The encoding used to decode or encode the file. Only applicable in - text mode. - :param newline: Controls how universal newlines mode works (only applicable in text - mode). - :param suffix: The suffix for the temporary file name. - :param prefix: The prefix for the temporary file name. - :param dir: The directory in which the temporary file is created. - :param errors: The error handling scheme used for encoding/decoding errors. - """ - - _async_file: AsyncFile[AnyStr] - - @overload - def __init__( - self: TemporaryFile[bytes], - mode: OpenBinaryMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - @overload - def __init__( - self: TemporaryFile[str], - mode: OpenTextMode, - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - - def __init__( - self, - mode: OpenTextMode | OpenBinaryMode = "w+b", - buffering: int = -1, - encoding: str | None = None, - newline: str | None = None, - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - *, - errors: str | None = None, - ) -> None: - self.mode = mode - self.buffering = buffering - self.encoding = encoding - self.newline = newline - self.suffix: str | None = suffix - self.prefix: str | None = prefix - self.dir: str | None = dir - self.errors = errors - - async def __aenter__(self) -> AsyncFile[AnyStr]: - fp = await to_thread.run_sync( - lambda: tempfile.TemporaryFile( - self.mode, - self.buffering, - self.encoding, - self.newline, - self.suffix, - self.prefix, - self.dir, - errors=self.errors, - ) - ) - self._async_file = AsyncFile(fp) - return self._async_file - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: TracebackType | None, - ) -> None: - await self._async_file.aclose() - - -class NamedTemporaryFile(Generic[AnyStr]): - """ - An asynchronous named temporary file that is automatically created and cleaned up. - - This class provides an asynchronous context manager for a temporary file with a - visible name in the file system. It uses Python's standard - :func:`~tempfile.NamedTemporaryFile` function and wraps the file object with - :class:`AsyncFile` for asynchronous operations. - - :param mode: The mode in which the file is opened. Defaults to "w+b". - :param buffering: The buffering policy (-1 means the default buffering). - :param encoding: The encoding used to decode or encode the file. Only applicable in - text mode. - :param newline: Controls how universal newlines mode works (only applicable in text - mode). - :param suffix: The suffix for the temporary file name. - :param prefix: The prefix for the temporary file name. - :param dir: The directory in which the temporary file is created. - :param delete: Whether to delete the file when it is closed. - :param errors: The error handling scheme used for encoding/decoding errors. - :param delete_on_close: (Python 3.12+) Whether to delete the file on close. - """ - - _async_file: AsyncFile[AnyStr] - - @overload - def __init__( - self: NamedTemporaryFile[bytes], - mode: OpenBinaryMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - delete: bool = ..., - *, - errors: str | None = ..., - delete_on_close: bool = ..., - ): ... - @overload - def __init__( - self: NamedTemporaryFile[str], - mode: OpenTextMode, - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - delete: bool = ..., - *, - errors: str | None = ..., - delete_on_close: bool = ..., - ): ... - - def __init__( - self, - mode: OpenBinaryMode | OpenTextMode = "w+b", - buffering: int = -1, - encoding: str | None = None, - newline: str | None = None, - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - delete: bool = True, - *, - errors: str | None = None, - delete_on_close: bool = True, - ) -> None: - self._params: dict[str, Any] = { - "mode": mode, - "buffering": buffering, - "encoding": encoding, - "newline": newline, - "suffix": suffix, - "prefix": prefix, - "dir": dir, - "delete": delete, - "errors": errors, - } - if sys.version_info >= (3, 12): - self._params["delete_on_close"] = delete_on_close - - async def __aenter__(self) -> AsyncFile[AnyStr]: - fp = await to_thread.run_sync( - lambda: tempfile.NamedTemporaryFile(**self._params) - ) - self._async_file = AsyncFile(fp) - return self._async_file - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: TracebackType | None, - ) -> None: - await self._async_file.aclose() - - -class SpooledTemporaryFile(AsyncFile[AnyStr]): - """ - An asynchronous spooled temporary file that starts in memory and is spooled to disk. - - This class provides an asynchronous interface to a spooled temporary file, much like - Python's standard :class:`~tempfile.SpooledTemporaryFile`. It supports asynchronous - write operations and provides a method to force a rollover to disk. - - :param max_size: Maximum size in bytes before the file is rolled over to disk. - :param mode: The mode in which the file is opened. Defaults to "w+b". - :param buffering: The buffering policy (-1 means the default buffering). - :param encoding: The encoding used to decode or encode the file (text mode only). - :param newline: Controls how universal newlines mode works (text mode only). - :param suffix: The suffix for the temporary file name. - :param prefix: The prefix for the temporary file name. - :param dir: The directory in which the temporary file is created. - :param errors: The error handling scheme used for encoding/decoding errors. - """ - - _rolled: bool = False - - @overload - def __init__( - self: SpooledTemporaryFile[bytes], - max_size: int = ..., - mode: OpenBinaryMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - @overload - def __init__( - self: SpooledTemporaryFile[str], - max_size: int = ..., - mode: OpenTextMode = ..., - buffering: int = ..., - encoding: str | None = ..., - newline: str | None = ..., - suffix: str | None = ..., - prefix: str | None = ..., - dir: str | None = ..., - *, - errors: str | None = ..., - ): ... - - def __init__( - self, - max_size: int = 0, - mode: OpenBinaryMode | OpenTextMode = "w+b", - buffering: int = -1, - encoding: str | None = None, - newline: str | None = None, - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - *, - errors: str | None = None, - ) -> None: - self._tempfile_params: dict[str, Any] = { - "mode": mode, - "buffering": buffering, - "encoding": encoding, - "newline": newline, - "suffix": suffix, - "prefix": prefix, - "dir": dir, - "errors": errors, - } - self._max_size = max_size - if "b" in mode: - super().__init__(BytesIO()) # type: ignore[arg-type] - else: - super().__init__( - TextIOWrapper( # type: ignore[arg-type] - BytesIO(), - encoding=encoding, - errors=errors, - newline=newline, - write_through=True, - ) - ) - - async def aclose(self) -> None: - if not self._rolled: - self._fp.close() - return - - await super().aclose() - - async def _check(self) -> None: - if self._rolled or self._fp.tell() < self._max_size: - return - - await self.rollover() - - async def rollover(self) -> None: - if self._rolled: - return - - self._rolled = True - buffer = self._fp - buffer.seek(0) - self._fp = await to_thread.run_sync( - lambda: tempfile.TemporaryFile(**self._tempfile_params) - ) - await self.write(buffer.read()) - buffer.close() - - @property - def closed(self) -> bool: - return self._fp.closed - - async def read(self, size: int = -1) -> AnyStr: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.read(size) - - return await super().read(size) # type: ignore[return-value] - - async def read1(self: SpooledTemporaryFile[bytes], size: int = -1) -> bytes: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.read1(size) - - return await super().read1(size) - - async def readline(self) -> AnyStr: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.readline() - - return await super().readline() # type: ignore[return-value] - - async def readlines(self) -> list[AnyStr]: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.readlines() - - return await super().readlines() # type: ignore[return-value] - - async def readinto(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - self._fp.readinto(b) - - return await super().readinto(b) - - async def readinto1(self: SpooledTemporaryFile[bytes], b: WriteableBuffer) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - self._fp.readinto(b) - - return await super().readinto1(b) - - async def seek(self, offset: int, whence: int | None = os.SEEK_SET) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.seek(offset, whence) - - return await super().seek(offset, whence) - - async def tell(self) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.tell() - - return await super().tell() - - async def truncate(self, size: int | None = None) -> int: - if not self._rolled: - await checkpoint_if_cancelled() - return self._fp.truncate(size) - - return await super().truncate(size) - - @overload - async def write(self: SpooledTemporaryFile[bytes], b: ReadableBuffer) -> int: ... - @overload - async def write(self: SpooledTemporaryFile[str], b: str) -> int: ... - - async def write(self, b: ReadableBuffer | str) -> int: - """ - Asynchronously write data to the spooled temporary file. - - If the file has not yet been rolled over, the data is written synchronously, - and a rollover is triggered if the size exceeds the maximum size. - - :param s: The data to write. - :return: The number of bytes written. - :raises RuntimeError: If the underlying file is not initialized. - - """ - if not self._rolled: - await checkpoint_if_cancelled() - result = self._fp.write(b) - await self._check() - return result - - return await super().write(b) # type: ignore[misc] - - @overload - async def writelines( - self: SpooledTemporaryFile[bytes], lines: Iterable[ReadableBuffer] - ) -> None: ... - @overload - async def writelines( - self: SpooledTemporaryFile[str], lines: Iterable[str] - ) -> None: ... - - async def writelines(self, lines: Iterable[str] | Iterable[ReadableBuffer]) -> None: - """ - Asynchronously write a list of lines to the spooled temporary file. - - If the file has not yet been rolled over, the lines are written synchronously, - and a rollover is triggered if the size exceeds the maximum size. - - :param lines: An iterable of lines to write. - :raises RuntimeError: If the underlying file is not initialized. - - """ - if not self._rolled: - await checkpoint_if_cancelled() - result = self._fp.writelines(lines) - await self._check() - return result - - return await super().writelines(lines) # type: ignore[misc] - - -class TemporaryDirectory(Generic[AnyStr]): - """ - An asynchronous temporary directory that is created and cleaned up automatically. - - This class provides an asynchronous context manager for creating a temporary - directory. It wraps Python's standard :class:`~tempfile.TemporaryDirectory` to - perform directory creation and cleanup operations in a background thread. - - :param suffix: Suffix to be added to the temporary directory name. - :param prefix: Prefix to be added to the temporary directory name. - :param dir: The parent directory where the temporary directory is created. - :param ignore_cleanup_errors: Whether to ignore errors during cleanup - (Python 3.10+). - :param delete: Whether to delete the directory upon closing (Python 3.12+). - """ - - def __init__( - self, - suffix: AnyStr | None = None, - prefix: AnyStr | None = None, - dir: AnyStr | None = None, - *, - ignore_cleanup_errors: bool = False, - delete: bool = True, - ) -> None: - self.suffix: AnyStr | None = suffix - self.prefix: AnyStr | None = prefix - self.dir: AnyStr | None = dir - self.ignore_cleanup_errors = ignore_cleanup_errors - self.delete = delete - - self._tempdir: tempfile.TemporaryDirectory | None = None - - async def __aenter__(self) -> str: - params: dict[str, Any] = { - "suffix": self.suffix, - "prefix": self.prefix, - "dir": self.dir, - } - if sys.version_info >= (3, 10): - params["ignore_cleanup_errors"] = self.ignore_cleanup_errors - - if sys.version_info >= (3, 12): - params["delete"] = self.delete - - self._tempdir = await to_thread.run_sync( - lambda: tempfile.TemporaryDirectory(**params) - ) - return await to_thread.run_sync(self._tempdir.__enter__) - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_value: BaseException | None, - traceback: TracebackType | None, - ) -> None: - if self._tempdir is not None: - await to_thread.run_sync( - self._tempdir.__exit__, exc_type, exc_value, traceback - ) - - async def cleanup(self) -> None: - if self._tempdir is not None: - await to_thread.run_sync(self._tempdir.cleanup) - - -@overload -async def mkstemp( - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, - text: bool = False, -) -> tuple[int, str]: ... - - -@overload -async def mkstemp( - suffix: bytes | None = None, - prefix: bytes | None = None, - dir: bytes | None = None, - text: bool = False, -) -> tuple[int, bytes]: ... - - -async def mkstemp( - suffix: AnyStr | None = None, - prefix: AnyStr | None = None, - dir: AnyStr | None = None, - text: bool = False, -) -> tuple[int, str | bytes]: - """ - Asynchronously create a temporary file and return an OS-level handle and the file - name. - - This function wraps `tempfile.mkstemp` and executes it in a background thread. - - :param suffix: Suffix to be added to the file name. - :param prefix: Prefix to be added to the file name. - :param dir: Directory in which the temporary file is created. - :param text: Whether the file is opened in text mode. - :return: A tuple containing the file descriptor and the file name. - - """ - return await to_thread.run_sync(tempfile.mkstemp, suffix, prefix, dir, text) - - -@overload -async def mkdtemp( - suffix: str | None = None, - prefix: str | None = None, - dir: str | None = None, -) -> str: ... - - -@overload -async def mkdtemp( - suffix: bytes | None = None, - prefix: bytes | None = None, - dir: bytes | None = None, -) -> bytes: ... - - -async def mkdtemp( - suffix: AnyStr | None = None, - prefix: AnyStr | None = None, - dir: AnyStr | None = None, -) -> str | bytes: - """ - Asynchronously create a temporary directory and return its path. - - This function wraps `tempfile.mkdtemp` and executes it in a background thread. - - :param suffix: Suffix to be added to the directory name. - :param prefix: Prefix to be added to the directory name. - :param dir: Parent directory where the temporary directory is created. - :return: The path of the created temporary directory. - - """ - return await to_thread.run_sync(tempfile.mkdtemp, suffix, prefix, dir) - - -async def gettempdir() -> str: - """ - Asynchronously return the name of the directory used for temporary files. - - This function wraps `tempfile.gettempdir` and executes it in a background thread. - - :return: The path of the temporary directory as a string. - - """ - return await to_thread.run_sync(tempfile.gettempdir) - - -async def gettempdirb() -> bytes: - """ - Asynchronously return the name of the directory used for temporary files in bytes. - - This function wraps `tempfile.gettempdirb` and executes it in a background thread. - - :return: The path of the temporary directory as bytes. - - """ - return await to_thread.run_sync(tempfile.gettempdirb) diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_testing.py b/venv/lib/python3.12/site-packages/anyio/_core/_testing.py deleted file mode 100644 index 9e28b22..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_testing.py +++ /dev/null @@ -1,78 +0,0 @@ -from __future__ import annotations - -from collections.abc import Awaitable, Generator -from typing import Any, cast - -from ._eventloop import get_async_backend - - -class TaskInfo: - """ - Represents an asynchronous task. - - :ivar int id: the unique identifier of the task - :ivar parent_id: the identifier of the parent task, if any - :vartype parent_id: Optional[int] - :ivar str name: the description of the task (if any) - :ivar ~collections.abc.Coroutine coro: the coroutine object of the task - """ - - __slots__ = "_name", "id", "parent_id", "name", "coro" - - def __init__( - self, - id: int, - parent_id: int | None, - name: str | None, - coro: Generator[Any, Any, Any] | Awaitable[Any], - ): - func = get_current_task - self._name = f"{func.__module__}.{func.__qualname__}" - self.id: int = id - self.parent_id: int | None = parent_id - self.name: str | None = name - self.coro: Generator[Any, Any, Any] | Awaitable[Any] = coro - - def __eq__(self, other: object) -> bool: - if isinstance(other, TaskInfo): - return self.id == other.id - - return NotImplemented - - def __hash__(self) -> int: - return hash(self.id) - - def __repr__(self) -> str: - return f"{self.__class__.__name__}(id={self.id!r}, name={self.name!r})" - - def has_pending_cancellation(self) -> bool: - """ - Return ``True`` if the task has a cancellation pending, ``False`` otherwise. - - """ - return False - - -def get_current_task() -> TaskInfo: - """ - Return the current task. - - :return: a representation of the current task - - """ - return get_async_backend().get_current_task() - - -def get_running_tasks() -> list[TaskInfo]: - """ - Return a list of running tasks in the current event loop. - - :return: a list of task info objects - - """ - return cast("list[TaskInfo]", get_async_backend().get_running_tasks()) - - -async def wait_all_tasks_blocked() -> None: - """Wait until all other tasks are waiting for something.""" - await get_async_backend().wait_all_tasks_blocked() diff --git a/venv/lib/python3.12/site-packages/anyio/_core/_typedattr.py b/venv/lib/python3.12/site-packages/anyio/_core/_typedattr.py deleted file mode 100644 index f358a44..0000000 --- a/venv/lib/python3.12/site-packages/anyio/_core/_typedattr.py +++ /dev/null @@ -1,81 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, Mapping -from typing import Any, TypeVar, final, overload - -from ._exceptions import TypedAttributeLookupError - -T_Attr = TypeVar("T_Attr") -T_Default = TypeVar("T_Default") -undefined = object() - - -def typed_attribute() -> Any: - """Return a unique object, used to mark typed attributes.""" - return object() - - -class TypedAttributeSet: - """ - Superclass for typed attribute collections. - - Checks that every public attribute of every subclass has a type annotation. - """ - - def __init_subclass__(cls) -> None: - annotations: dict[str, Any] = getattr(cls, "__annotations__", {}) - for attrname in dir(cls): - if not attrname.startswith("_") and attrname not in annotations: - raise TypeError( - f"Attribute {attrname!r} is missing its type annotation" - ) - - super().__init_subclass__() - - -class TypedAttributeProvider: - """Base class for classes that wish to provide typed extra attributes.""" - - @property - def extra_attributes(self) -> Mapping[T_Attr, Callable[[], T_Attr]]: - """ - A mapping of the extra attributes to callables that return the corresponding - values. - - If the provider wraps another provider, the attributes from that wrapper should - also be included in the returned mapping (but the wrapper may override the - callables from the wrapped instance). - - """ - return {} - - @overload - def extra(self, attribute: T_Attr) -> T_Attr: ... - - @overload - def extra(self, attribute: T_Attr, default: T_Default) -> T_Attr | T_Default: ... - - @final - def extra(self, attribute: Any, default: object = undefined) -> object: - """ - extra(attribute, default=undefined) - - Return the value of the given typed extra attribute. - - :param attribute: the attribute (member of a :class:`~TypedAttributeSet`) to - look for - :param default: the value that should be returned if no value is found for the - attribute - :raises ~anyio.TypedAttributeLookupError: if the search failed and no default - value was given - - """ - try: - getter = self.extra_attributes[attribute] - except KeyError: - if default is undefined: - raise TypedAttributeLookupError("Attribute not found") from None - else: - return default - - return getter() diff --git a/venv/lib/python3.12/site-packages/anyio/abc/__init__.py b/venv/lib/python3.12/site-packages/anyio/abc/__init__.py deleted file mode 100644 index 3d3b61c..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -from __future__ import annotations - -from ._eventloop import AsyncBackend as AsyncBackend -from ._resources import AsyncResource as AsyncResource -from ._sockets import ConnectedUDPSocket as ConnectedUDPSocket -from ._sockets import ConnectedUNIXDatagramSocket as ConnectedUNIXDatagramSocket -from ._sockets import IPAddressType as IPAddressType -from ._sockets import IPSockAddrType as IPSockAddrType -from ._sockets import SocketAttribute as SocketAttribute -from ._sockets import SocketListener as SocketListener -from ._sockets import SocketStream as SocketStream -from ._sockets import UDPPacketType as UDPPacketType -from ._sockets import UDPSocket as UDPSocket -from ._sockets import UNIXDatagramPacketType as UNIXDatagramPacketType -from ._sockets import UNIXDatagramSocket as UNIXDatagramSocket -from ._sockets import UNIXSocketStream as UNIXSocketStream -from ._streams import AnyByteReceiveStream as AnyByteReceiveStream -from ._streams import AnyByteSendStream as AnyByteSendStream -from ._streams import AnyByteStream as AnyByteStream -from ._streams import AnyUnreliableByteReceiveStream as AnyUnreliableByteReceiveStream -from ._streams import AnyUnreliableByteSendStream as AnyUnreliableByteSendStream -from ._streams import AnyUnreliableByteStream as AnyUnreliableByteStream -from ._streams import ByteReceiveStream as ByteReceiveStream -from ._streams import ByteSendStream as ByteSendStream -from ._streams import ByteStream as ByteStream -from ._streams import Listener as Listener -from ._streams import ObjectReceiveStream as ObjectReceiveStream -from ._streams import ObjectSendStream as ObjectSendStream -from ._streams import ObjectStream as ObjectStream -from ._streams import UnreliableObjectReceiveStream as UnreliableObjectReceiveStream -from ._streams import UnreliableObjectSendStream as UnreliableObjectSendStream -from ._streams import UnreliableObjectStream as UnreliableObjectStream -from ._subprocesses import Process as Process -from ._tasks import TaskGroup as TaskGroup -from ._tasks import TaskStatus as TaskStatus -from ._testing import TestRunner as TestRunner - -# Re-exported here, for backwards compatibility -# isort: off -from .._core._synchronization import ( - CapacityLimiter as CapacityLimiter, - Condition as Condition, - Event as Event, - Lock as Lock, - Semaphore as Semaphore, -) -from .._core._tasks import CancelScope as CancelScope -from ..from_thread import BlockingPortal as BlockingPortal - -# Re-export imports so they look like they live directly in this package -for __value in list(locals().values()): - if getattr(__value, "__module__", "").startswith("anyio.abc."): - __value.__module__ = __name__ - -del __value diff --git a/venv/lib/python3.12/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/abc/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index e4ed155b017e3629771902bf77584b92fe91a525..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2221 zcmZvd%WqRh6vpQ!@%xpB<2;=wc{s#2gcPNeq9&v~Bm_|ss%lDgd+j?U7w*HFI}S3d zE?KZaUC?E>6`TGKU3OI=)b>hVRb8NNps1?Es^=Wrc>tF3`8VI0bMAQN+{rJgRGh(Q z;q~8pcYyxHLFW^0f%fK`F2$9F1!lGrP=gyUXe3-NZe1j}zh{;*cG7B0NGI z29EM5aRfNVW5iM5IFA#@fD=4H90yMFByj>b#Z$yd;51JYr+_m&L!1Wg<-Noi;6C0* z+zZ^#`-%JP0Vm6|#Qng7e2{nmILC9uS>Pc)L_7#Q%!i3{z$1KwcnEluj}i|9kMS|$ z5#Vt?PCN>n=Xv5W;0ZoKJPtg`CyDdGQ+$ee0(hEF6Hfxq@EPJM;8{LPJZ+zH=J*`( zj6Lrx@CD*o;6=Vje9A63OMD4<&YZVTJIj38De|II;w7id%gz~ohGGl$S!ac>5HH&2 zoK?Q6u`VV)g1__6+UI`H>oma8cPI8tYk8aO>siM58svQ}*35#r^sKuTxmQ2R>X3Q5 zljm!X^Wqb+reEyD9?$i#uhtsNh2l%J3R;jbT-Q^EvOL#+iO&Nsx$ZaI>V{FhFI*GG zDH?AJ->b{20Hgo1=enY*gn4^&YsZ6m3f!?H_vZC4Hw|U%Ny9k|r><|Uo2C@LzuTx` zmGpJWMYHW>T9en6l2)azXj03%Vfjk9LPA=yA``B7e zOzS@$Ib3Bgy6-$8yY4nN8cJ-7s;~~k;gkE?{tj%@p_%HKo%KzCaod%`wv37`K2&Gy zy%{Ge4!s}l)b9IGxip$5D#Xd@Bt?&H=D@AWJvhjBe_3zKK2apu_Bv(qM?dPrMMmG9 zaH3r9y=bR!WJ`KgXcIWw*skH>_D&9F%;hwzS^!sAIg_-W3oah$XqsR zM%7Y{8|xw+8!lxL#TUT`nL5Z&<7y_STdtOb3S_X7H zy*IwZD?W(oKD{u$jKEMvQDP|guR$hIk|-&ZG)e}g7o`uS9|Wt=cKLDuy)4QgN)BZR zWf)}yWfWx$WgI1sGJ!IQGKDgYG6NE%biZDywN60z5-uJVgmnd5@5@s-YYv^Lu3-CN zm*hMSb9xmvv!vs_u`fN>dPp~lT*QO|$`ZEMAwOe$ew^^P%?=7%8<%`V5xmrnC==5o<|u<{K(#bvbWpi zea{i)yKo`-#i~)ZZKtR#yfe;~;k*vYwpA(D8fxEj&y~)ulznKQBJ|RIV^8>HI`cA| zd0E#j*HXG(sx{t5FSh#PlDquBnrx%VE|U2LO}<7$$SpP5Qj>kwWH1M^cAM-bWfjSX3Z?&|VXf<5hLUC)q+EC% zX1&=bSH8RU^wyJG&$DySGxPtjE^YqXtA9k&j~;xV{GswZQur;h`fFtMr#mkq8^7o0 W9z|Y6M_+|t*6Sz>CFLgkj{gCfbA1y4 diff --git a/venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_eventloop.cpython-312.pyc deleted file mode 100644 index 5a43c9b8c8a26f7cd1088eb67223873a2abca016..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14970 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 diff --git a/venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/abc/__pycache__/_subprocesses.cpython-312.pyc deleted file mode 100644 index 74127e72d30f808ce0a3c894b3f56f131018b470..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3236 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�Mh{Ii2XIpErOTS0?tOIl(m)d0>`$@RU{gatOiq|KXAODazs;9 zKn`#j^q1qD OEEzw2@(+PQtm$7E!R$8x diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_eventloop.py b/venv/lib/python3.12/site-packages/anyio/abc/_eventloop.py deleted file mode 100644 index 4cfce83..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_eventloop.py +++ /dev/null @@ -1,376 +0,0 @@ -from __future__ import annotations - -import math -import sys -from abc import ABCMeta, abstractmethod -from collections.abc import AsyncIterator, Awaitable, Callable, Sequence -from contextlib import AbstractContextManager -from os import PathLike -from signal import Signals -from socket import AddressFamily, SocketKind, socket -from typing import ( - IO, - TYPE_CHECKING, - Any, - TypeVar, - Union, - overload, -) - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if sys.version_info >= (3, 10): - from typing import TypeAlias -else: - from typing_extensions import TypeAlias - -if TYPE_CHECKING: - from _typeshed import HasFileno - - from .._core._synchronization import CapacityLimiter, Event, Lock, Semaphore - from .._core._tasks import CancelScope - from .._core._testing import TaskInfo - from ..from_thread import BlockingPortal - from ._sockets import ( - ConnectedUDPSocket, - ConnectedUNIXDatagramSocket, - IPSockAddrType, - SocketListener, - SocketStream, - UDPSocket, - UNIXDatagramSocket, - UNIXSocketStream, - ) - from ._subprocesses import Process - from ._tasks import TaskGroup - from ._testing import TestRunner - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") -StrOrBytesPath: TypeAlias = Union[str, bytes, "PathLike[str]", "PathLike[bytes]"] - - -class AsyncBackend(metaclass=ABCMeta): - @classmethod - @abstractmethod - def run( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - options: dict[str, Any], - ) -> T_Retval: - """ - Run the given coroutine function in an asynchronous event loop. - - The current thread must not be already running an event loop. - - :param func: a coroutine function - :param args: positional arguments to ``func`` - :param kwargs: positional arguments to ``func`` - :param options: keyword arguments to call the backend ``run()`` implementation - with - :return: the return value of the coroutine function - """ - - @classmethod - @abstractmethod - def current_token(cls) -> object: - """ - - :return: - """ - - @classmethod - @abstractmethod - def current_time(cls) -> float: - """ - Return the current value of the event loop's internal clock. - - :return: the clock value (seconds) - """ - - @classmethod - @abstractmethod - def cancelled_exception_class(cls) -> type[BaseException]: - """Return the exception class that is raised in a task if it's cancelled.""" - - @classmethod - @abstractmethod - async def checkpoint(cls) -> None: - """ - Check if the task has been cancelled, and allow rescheduling of other tasks. - - This is effectively the same as running :meth:`checkpoint_if_cancelled` and then - :meth:`cancel_shielded_checkpoint`. - """ - - @classmethod - async def checkpoint_if_cancelled(cls) -> None: - """ - Check if the current task group has been cancelled. - - This will check if the task has been cancelled, but will not allow other tasks - to be scheduled if not. - - """ - if cls.current_effective_deadline() == -math.inf: - await cls.checkpoint() - - @classmethod - async def cancel_shielded_checkpoint(cls) -> None: - """ - Allow the rescheduling of other tasks. - - This will give other tasks the opportunity to run, but without checking if the - current task group has been cancelled, unlike with :meth:`checkpoint`. - - """ - with cls.create_cancel_scope(shield=True): - await cls.sleep(0) - - @classmethod - @abstractmethod - async def sleep(cls, delay: float) -> None: - """ - Pause the current task for the specified duration. - - :param delay: the duration, in seconds - """ - - @classmethod - @abstractmethod - def create_cancel_scope( - cls, *, deadline: float = math.inf, shield: bool = False - ) -> CancelScope: - pass - - @classmethod - @abstractmethod - def current_effective_deadline(cls) -> float: - """ - Return the nearest deadline among all the cancel scopes effective for the - current task. - - :return: - - a clock value from the event loop's internal clock - - ``inf`` if there is no deadline in effect - - ``-inf`` if the current scope has been cancelled - :rtype: float - """ - - @classmethod - @abstractmethod - def create_task_group(cls) -> TaskGroup: - pass - - @classmethod - @abstractmethod - def create_event(cls) -> Event: - pass - - @classmethod - @abstractmethod - def create_lock(cls, *, fast_acquire: bool) -> Lock: - pass - - @classmethod - @abstractmethod - def create_semaphore( - cls, - initial_value: int, - *, - max_value: int | None = None, - fast_acquire: bool = False, - ) -> Semaphore: - pass - - @classmethod - @abstractmethod - def create_capacity_limiter(cls, total_tokens: float) -> CapacityLimiter: - pass - - @classmethod - @abstractmethod - async def run_sync_in_worker_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - abandon_on_cancel: bool = False, - limiter: CapacityLimiter | None = None, - ) -> T_Retval: - pass - - @classmethod - @abstractmethod - def check_cancelled(cls) -> None: - pass - - @classmethod - @abstractmethod - def run_async_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - pass - - @classmethod - @abstractmethod - def run_sync_from_thread( - cls, - func: Callable[[Unpack[PosArgsT]], T_Retval], - args: tuple[Unpack[PosArgsT]], - token: object, - ) -> T_Retval: - pass - - @classmethod - @abstractmethod - def create_blocking_portal(cls) -> BlockingPortal: - pass - - @classmethod - @abstractmethod - async def open_process( - cls, - command: StrOrBytesPath | Sequence[StrOrBytesPath], - *, - stdin: int | IO[Any] | None, - stdout: int | IO[Any] | None, - stderr: int | IO[Any] | None, - **kwargs: Any, - ) -> Process: - pass - - @classmethod - @abstractmethod - def setup_process_pool_exit_at_shutdown(cls, workers: set[Process]) -> None: - pass - - @classmethod - @abstractmethod - async def connect_tcp( - cls, host: str, port: int, local_address: IPSockAddrType | None = None - ) -> SocketStream: - pass - - @classmethod - @abstractmethod - async def connect_unix(cls, path: str | bytes) -> UNIXSocketStream: - pass - - @classmethod - @abstractmethod - def create_tcp_listener(cls, sock: socket) -> SocketListener: - pass - - @classmethod - @abstractmethod - def create_unix_listener(cls, sock: socket) -> SocketListener: - pass - - @classmethod - @abstractmethod - async def create_udp_socket( - cls, - family: AddressFamily, - local_address: IPSockAddrType | None, - remote_address: IPSockAddrType | None, - reuse_port: bool, - ) -> UDPSocket | ConnectedUDPSocket: - pass - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket, remote_path: None - ) -> UNIXDatagramSocket: ... - - @classmethod - @overload - async def create_unix_datagram_socket( - cls, raw_socket: socket, remote_path: str | bytes - ) -> ConnectedUNIXDatagramSocket: ... - - @classmethod - @abstractmethod - async def create_unix_datagram_socket( - cls, raw_socket: socket, remote_path: str | bytes | None - ) -> UNIXDatagramSocket | ConnectedUNIXDatagramSocket: - pass - - @classmethod - @abstractmethod - async def getaddrinfo( - cls, - host: bytes | str | None, - port: str | int | None, - *, - family: int | AddressFamily = 0, - type: int | SocketKind = 0, - proto: int = 0, - flags: int = 0, - ) -> Sequence[ - tuple[ - AddressFamily, - SocketKind, - int, - str, - tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes], - ] - ]: - pass - - @classmethod - @abstractmethod - async def getnameinfo( - cls, sockaddr: IPSockAddrType, flags: int = 0 - ) -> tuple[str, str]: - pass - - @classmethod - @abstractmethod - async def wait_readable(cls, obj: HasFileno | int) -> None: - pass - - @classmethod - @abstractmethod - async def wait_writable(cls, obj: HasFileno | int) -> None: - pass - - @classmethod - @abstractmethod - def current_default_thread_limiter(cls) -> CapacityLimiter: - pass - - @classmethod - @abstractmethod - def open_signal_receiver( - cls, *signals: Signals - ) -> AbstractContextManager[AsyncIterator[Signals]]: - pass - - @classmethod - @abstractmethod - def get_current_task(cls) -> TaskInfo: - pass - - @classmethod - @abstractmethod - def get_running_tasks(cls) -> Sequence[TaskInfo]: - pass - - @classmethod - @abstractmethod - async def wait_all_tasks_blocked(cls) -> None: - pass - - @classmethod - @abstractmethod - def create_test_runner(cls, options: dict[str, Any]) -> TestRunner: - pass diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_resources.py b/venv/lib/python3.12/site-packages/anyio/abc/_resources.py deleted file mode 100644 index 10df115..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_resources.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import annotations - -from abc import ABCMeta, abstractmethod -from types import TracebackType -from typing import TypeVar - -T = TypeVar("T") - - -class AsyncResource(metaclass=ABCMeta): - """ - Abstract base class for all closeable asynchronous resources. - - Works as an asynchronous context manager which returns the instance itself on enter, - and calls :meth:`aclose` on exit. - """ - - __slots__ = () - - async def __aenter__(self: T) -> T: - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - await self.aclose() - - @abstractmethod - async def aclose(self) -> None: - """Close the resource.""" diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_sockets.py b/venv/lib/python3.12/site-packages/anyio/abc/_sockets.py deleted file mode 100644 index 1c6a450..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_sockets.py +++ /dev/null @@ -1,194 +0,0 @@ -from __future__ import annotations - -import socket -from abc import abstractmethod -from collections.abc import Callable, Collection, Mapping -from contextlib import AsyncExitStack -from io import IOBase -from ipaddress import IPv4Address, IPv6Address -from socket import AddressFamily -from types import TracebackType -from typing import Any, TypeVar, Union - -from .._core._typedattr import ( - TypedAttributeProvider, - TypedAttributeSet, - typed_attribute, -) -from ._streams import ByteStream, Listener, UnreliableObjectStream -from ._tasks import TaskGroup - -IPAddressType = Union[str, IPv4Address, IPv6Address] -IPSockAddrType = tuple[str, int] -SockAddrType = Union[IPSockAddrType, str] -UDPPacketType = tuple[bytes, IPSockAddrType] -UNIXDatagramPacketType = tuple[bytes, str] -T_Retval = TypeVar("T_Retval") - - -class _NullAsyncContextManager: - async def __aenter__(self) -> None: - pass - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - return None - - -class SocketAttribute(TypedAttributeSet): - #: the address family of the underlying socket - family: AddressFamily = typed_attribute() - #: the local socket address of the underlying socket - local_address: SockAddrType = typed_attribute() - #: for IP addresses, the local port the underlying socket is bound to - local_port: int = typed_attribute() - #: the underlying stdlib socket object - raw_socket: socket.socket = typed_attribute() - #: the remote address the underlying socket is connected to - remote_address: SockAddrType = typed_attribute() - #: for IP addresses, the remote port the underlying socket is connected to - remote_port: int = typed_attribute() - - -class _SocketProvider(TypedAttributeProvider): - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - from .._core._sockets import convert_ipv6_sockaddr as convert - - attributes: dict[Any, Callable[[], Any]] = { - SocketAttribute.family: lambda: self._raw_socket.family, - SocketAttribute.local_address: lambda: convert( - self._raw_socket.getsockname() - ), - SocketAttribute.raw_socket: lambda: self._raw_socket, - } - try: - peername: tuple[str, int] | None = convert(self._raw_socket.getpeername()) - except OSError: - peername = None - - # Provide the remote address for connected sockets - if peername is not None: - attributes[SocketAttribute.remote_address] = lambda: peername - - # Provide local and remote ports for IP based sockets - if self._raw_socket.family in (AddressFamily.AF_INET, AddressFamily.AF_INET6): - attributes[SocketAttribute.local_port] = ( - lambda: self._raw_socket.getsockname()[1] - ) - if peername is not None: - remote_port = peername[1] - attributes[SocketAttribute.remote_port] = lambda: remote_port - - return attributes - - @property - @abstractmethod - def _raw_socket(self) -> socket.socket: - pass - - -class SocketStream(ByteStream, _SocketProvider): - """ - Transports bytes over a socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - -class UNIXSocketStream(SocketStream): - @abstractmethod - async def send_fds(self, message: bytes, fds: Collection[int | IOBase]) -> None: - """ - Send file descriptors along with a message to the peer. - - :param message: a non-empty bytestring - :param fds: a collection of files (either numeric file descriptors or open file - or socket objects) - """ - - @abstractmethod - async def receive_fds(self, msglen: int, maxfds: int) -> tuple[bytes, list[int]]: - """ - Receive file descriptors along with a message from the peer. - - :param msglen: length of the message to expect from the peer - :param maxfds: maximum number of file descriptors to expect from the peer - :return: a tuple of (message, file descriptors) - """ - - -class SocketListener(Listener[SocketStream], _SocketProvider): - """ - Listens to incoming socket connections. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - @abstractmethod - async def accept(self) -> SocketStream: - """Accept an incoming connection.""" - - async def serve( - self, - handler: Callable[[SocketStream], Any], - task_group: TaskGroup | None = None, - ) -> None: - from .. import create_task_group - - async with AsyncExitStack() as stack: - if task_group is None: - task_group = await stack.enter_async_context(create_task_group()) - - while True: - stream = await self.accept() - task_group.start_soon(handler, stream) - - -class UDPSocket(UnreliableObjectStream[UDPPacketType], _SocketProvider): - """ - Represents an unconnected UDP socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - async def sendto(self, data: bytes, host: str, port: int) -> None: - """ - Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, (host, port))). - - """ - return await self.send((data, (host, port))) - - -class ConnectedUDPSocket(UnreliableObjectStream[bytes], _SocketProvider): - """ - Represents an connected UDP socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - -class UNIXDatagramSocket( - UnreliableObjectStream[UNIXDatagramPacketType], _SocketProvider -): - """ - Represents an unconnected Unix datagram socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ - - async def sendto(self, data: bytes, path: str) -> None: - """Alias for :meth:`~.UnreliableObjectSendStream.send` ((data, path)).""" - return await self.send((data, path)) - - -class ConnectedUNIXDatagramSocket(UnreliableObjectStream[bytes], _SocketProvider): - """ - Represents a connected Unix datagram socket. - - Supports all relevant extra attributes from :class:`~SocketAttribute`. - """ diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_streams.py b/venv/lib/python3.12/site-packages/anyio/abc/_streams.py deleted file mode 100644 index f11d97b..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_streams.py +++ /dev/null @@ -1,203 +0,0 @@ -from __future__ import annotations - -from abc import abstractmethod -from collections.abc import Callable -from typing import Any, Generic, TypeVar, Union - -from .._core._exceptions import EndOfStream -from .._core._typedattr import TypedAttributeProvider -from ._resources import AsyncResource -from ._tasks import TaskGroup - -T_Item = TypeVar("T_Item") -T_co = TypeVar("T_co", covariant=True) -T_contra = TypeVar("T_contra", contravariant=True) - - -class UnreliableObjectReceiveStream( - Generic[T_co], AsyncResource, TypedAttributeProvider -): - """ - An interface for receiving objects. - - This interface makes no guarantees that the received messages arrive in the order in - which they were sent, or that no messages are missed. - - Asynchronously iterating over objects of this type will yield objects matching the - given type parameter. - """ - - def __aiter__(self) -> UnreliableObjectReceiveStream[T_co]: - return self - - async def __anext__(self) -> T_co: - try: - return await self.receive() - except EndOfStream: - raise StopAsyncIteration - - @abstractmethod - async def receive(self) -> T_co: - """ - Receive the next item. - - :raises ~anyio.ClosedResourceError: if the receive stream has been explicitly - closed - :raises ~anyio.EndOfStream: if this stream has been closed from the other end - :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable - due to external causes - """ - - -class UnreliableObjectSendStream( - Generic[T_contra], AsyncResource, TypedAttributeProvider -): - """ - An interface for sending objects. - - This interface makes no guarantees that the messages sent will reach the - recipient(s) in the same order in which they were sent, or at all. - """ - - @abstractmethod - async def send(self, item: T_contra) -> None: - """ - Send an item to the peer(s). - - :param item: the item to send - :raises ~anyio.ClosedResourceError: if the send stream has been explicitly - closed - :raises ~anyio.BrokenResourceError: if this stream has been rendered unusable - due to external causes - """ - - -class UnreliableObjectStream( - UnreliableObjectReceiveStream[T_Item], UnreliableObjectSendStream[T_Item] -): - """ - A bidirectional message stream which does not guarantee the order or reliability of - message delivery. - """ - - -class ObjectReceiveStream(UnreliableObjectReceiveStream[T_co]): - """ - A receive message stream which guarantees that messages are received in the same - order in which they were sent, and that no messages are missed. - """ - - -class ObjectSendStream(UnreliableObjectSendStream[T_contra]): - """ - A send message stream which guarantees that messages are delivered in the same order - in which they were sent, without missing any messages in the middle. - """ - - -class ObjectStream( - ObjectReceiveStream[T_Item], - ObjectSendStream[T_Item], - UnreliableObjectStream[T_Item], -): - """ - A bidirectional message stream which guarantees the order and reliability of message - delivery. - """ - - @abstractmethod - async def send_eof(self) -> None: - """ - Send an end-of-file indication to the peer. - - You should not try to send any further data to this stream after calling this - method. This method is idempotent (does nothing on successive calls). - """ - - -class ByteReceiveStream(AsyncResource, TypedAttributeProvider): - """ - An interface for receiving bytes from a single peer. - - Iterating this byte stream will yield a byte string of arbitrary length, but no more - than 65536 bytes. - """ - - def __aiter__(self) -> ByteReceiveStream: - return self - - async def __anext__(self) -> bytes: - try: - return await self.receive() - except EndOfStream: - raise StopAsyncIteration - - @abstractmethod - async def receive(self, max_bytes: int = 65536) -> bytes: - """ - Receive at most ``max_bytes`` bytes from the peer. - - .. note:: Implementers of this interface should not return an empty - :class:`bytes` object, and users should ignore them. - - :param max_bytes: maximum number of bytes to receive - :return: the received bytes - :raises ~anyio.EndOfStream: if this stream has been closed from the other end - """ - - -class ByteSendStream(AsyncResource, TypedAttributeProvider): - """An interface for sending bytes to a single peer.""" - - @abstractmethod - async def send(self, item: bytes) -> None: - """ - Send the given bytes to the peer. - - :param item: the bytes to send - """ - - -class ByteStream(ByteReceiveStream, ByteSendStream): - """A bidirectional byte stream.""" - - @abstractmethod - async def send_eof(self) -> None: - """ - Send an end-of-file indication to the peer. - - You should not try to send any further data to this stream after calling this - method. This method is idempotent (does nothing on successive calls). - """ - - -#: Type alias for all unreliable bytes-oriented receive streams. -AnyUnreliableByteReceiveStream = Union[ - UnreliableObjectReceiveStream[bytes], ByteReceiveStream -] -#: Type alias for all unreliable bytes-oriented send streams. -AnyUnreliableByteSendStream = Union[UnreliableObjectSendStream[bytes], ByteSendStream] -#: Type alias for all unreliable bytes-oriented streams. -AnyUnreliableByteStream = Union[UnreliableObjectStream[bytes], ByteStream] -#: Type alias for all bytes-oriented receive streams. -AnyByteReceiveStream = Union[ObjectReceiveStream[bytes], ByteReceiveStream] -#: Type alias for all bytes-oriented send streams. -AnyByteSendStream = Union[ObjectSendStream[bytes], ByteSendStream] -#: Type alias for all bytes-oriented streams. -AnyByteStream = Union[ObjectStream[bytes], ByteStream] - - -class Listener(Generic[T_co], AsyncResource, TypedAttributeProvider): - """An interface for objects that let you accept incoming connections.""" - - @abstractmethod - async def serve( - self, handler: Callable[[T_co], Any], task_group: TaskGroup | None = None - ) -> None: - """ - Accept incoming connections as they come in and start tasks to handle them. - - :param handler: a callable that will be used to handle each accepted connection - :param task_group: the task group that will be used to start tasks for handling - each accepted connection (if omitted, an ad-hoc task group will be created) - """ diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_subprocesses.py b/venv/lib/python3.12/site-packages/anyio/abc/_subprocesses.py deleted file mode 100644 index ce0564c..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_subprocesses.py +++ /dev/null @@ -1,79 +0,0 @@ -from __future__ import annotations - -from abc import abstractmethod -from signal import Signals - -from ._resources import AsyncResource -from ._streams import ByteReceiveStream, ByteSendStream - - -class Process(AsyncResource): - """An asynchronous version of :class:`subprocess.Popen`.""" - - @abstractmethod - async def wait(self) -> int: - """ - Wait until the process exits. - - :return: the exit code of the process - """ - - @abstractmethod - def terminate(self) -> None: - """ - Terminates the process, gracefully if possible. - - On Windows, this calls ``TerminateProcess()``. - On POSIX systems, this sends ``SIGTERM`` to the process. - - .. seealso:: :meth:`subprocess.Popen.terminate` - """ - - @abstractmethod - def kill(self) -> None: - """ - Kills the process. - - On Windows, this calls ``TerminateProcess()``. - On POSIX systems, this sends ``SIGKILL`` to the process. - - .. seealso:: :meth:`subprocess.Popen.kill` - """ - - @abstractmethod - def send_signal(self, signal: Signals) -> None: - """ - Send a signal to the subprocess. - - .. seealso:: :meth:`subprocess.Popen.send_signal` - - :param signal: the signal number (e.g. :data:`signal.SIGHUP`) - """ - - @property - @abstractmethod - def pid(self) -> int: - """The process ID of the process.""" - - @property - @abstractmethod - def returncode(self) -> int | None: - """ - The return code of the process. If the process has not yet terminated, this will - be ``None``. - """ - - @property - @abstractmethod - def stdin(self) -> ByteSendStream | None: - """The stream for the standard input of the process.""" - - @property - @abstractmethod - def stdout(self) -> ByteReceiveStream | None: - """The stream for the standard output of the process.""" - - @property - @abstractmethod - def stderr(self) -> ByteReceiveStream | None: - """The stream for the standard error output of the process.""" diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_tasks.py b/venv/lib/python3.12/site-packages/anyio/abc/_tasks.py deleted file mode 100644 index f6e5c40..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_tasks.py +++ /dev/null @@ -1,101 +0,0 @@ -from __future__ import annotations - -import sys -from abc import ABCMeta, abstractmethod -from collections.abc import Awaitable, Callable -from types import TracebackType -from typing import TYPE_CHECKING, Any, Protocol, TypeVar, overload - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -if TYPE_CHECKING: - from .._core._tasks import CancelScope - -T_Retval = TypeVar("T_Retval") -T_contra = TypeVar("T_contra", contravariant=True) -PosArgsT = TypeVarTuple("PosArgsT") - - -class TaskStatus(Protocol[T_contra]): - @overload - def started(self: TaskStatus[None]) -> None: ... - - @overload - def started(self, value: T_contra) -> None: ... - - def started(self, value: T_contra | None = None) -> None: - """ - Signal that the task has started. - - :param value: object passed back to the starter of the task - """ - - -class TaskGroup(metaclass=ABCMeta): - """ - Groups several asynchronous tasks together. - - :ivar cancel_scope: the cancel scope inherited by all child tasks - :vartype cancel_scope: CancelScope - - .. note:: On asyncio, support for eager task factories is considered to be - **experimental**. In particular, they don't follow the usual semantics of new - tasks being scheduled on the next iteration of the event loop, and may thus - cause unexpected behavior in code that wasn't written with such semantics in - mind. - """ - - cancel_scope: CancelScope - - @abstractmethod - def start_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[Any]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> None: - """ - Start a new task in this task group. - - :param func: a coroutine function - :param args: positional arguments to call the function with - :param name: name of the task, for the purposes of introspection and debugging - - .. versionadded:: 3.0 - """ - - @abstractmethod - async def start( - self, - func: Callable[..., Awaitable[Any]], - *args: object, - name: object = None, - ) -> Any: - """ - Start a new task and wait until it signals for readiness. - - :param func: a coroutine function - :param args: positional arguments to call the function with - :param name: name of the task, for the purposes of introspection and debugging - :return: the value passed to ``task_status.started()`` - :raises RuntimeError: if the task finishes without calling - ``task_status.started()`` - - .. versionadded:: 3.0 - """ - - @abstractmethod - async def __aenter__(self) -> TaskGroup: - """Enter the task group context and allow starting new tasks.""" - - @abstractmethod - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - """Exit the task group context waiting for all tasks to finish.""" diff --git a/venv/lib/python3.12/site-packages/anyio/abc/_testing.py b/venv/lib/python3.12/site-packages/anyio/abc/_testing.py deleted file mode 100644 index 7c50ed7..0000000 --- a/venv/lib/python3.12/site-packages/anyio/abc/_testing.py +++ /dev/null @@ -1,65 +0,0 @@ -from __future__ import annotations - -import types -from abc import ABCMeta, abstractmethod -from collections.abc import AsyncGenerator, Callable, Coroutine, Iterable -from typing import Any, TypeVar - -_T = TypeVar("_T") - - -class TestRunner(metaclass=ABCMeta): - """ - Encapsulates a running event loop. Every call made through this object will use the - same event loop. - """ - - def __enter__(self) -> TestRunner: - return self - - @abstractmethod - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: types.TracebackType | None, - ) -> bool | None: ... - - @abstractmethod - def run_asyncgen_fixture( - self, - fixture_func: Callable[..., AsyncGenerator[_T, Any]], - kwargs: dict[str, Any], - ) -> Iterable[_T]: - """ - Run an async generator fixture. - - :param fixture_func: the fixture function - :param kwargs: keyword arguments to call the fixture function with - :return: an iterator yielding the value yielded from the async generator - """ - - @abstractmethod - def run_fixture( - self, - fixture_func: Callable[..., Coroutine[Any, Any, _T]], - kwargs: dict[str, Any], - ) -> _T: - """ - Run an async fixture. - - :param fixture_func: the fixture function - :param kwargs: keyword arguments to call the fixture function with - :return: the return value of the fixture function - """ - - @abstractmethod - def run_test( - self, test_func: Callable[..., Coroutine[Any, Any, Any]], kwargs: dict[str, Any] - ) -> None: - """ - Run an async test function. - - :param test_func: the test function - :param kwargs: keyword arguments to call the test function with - """ diff --git a/venv/lib/python3.12/site-packages/anyio/from_thread.py b/venv/lib/python3.12/site-packages/anyio/from_thread.py deleted file mode 100644 index 6179097..0000000 --- a/venv/lib/python3.12/site-packages/anyio/from_thread.py +++ /dev/null @@ -1,527 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import Awaitable, Callable, Generator -from concurrent.futures import Future -from contextlib import ( - AbstractAsyncContextManager, - AbstractContextManager, - contextmanager, -) -from dataclasses import dataclass, field -from inspect import isawaitable -from threading import Lock, Thread, get_ident -from types import TracebackType -from typing import ( - Any, - Generic, - TypeVar, - cast, - overload, -) - -from ._core import _eventloop -from ._core._eventloop import get_async_backend, get_cancelled_exc_class, threadlocals -from ._core._synchronization import Event -from ._core._tasks import CancelScope, create_task_group -from .abc import AsyncBackend -from .abc._tasks import TaskStatus - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -T_Retval = TypeVar("T_Retval") -T_co = TypeVar("T_co", covariant=True) -PosArgsT = TypeVarTuple("PosArgsT") - - -def run( - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], *args: Unpack[PosArgsT] -) -> T_Retval: - """ - Call a coroutine function from a worker thread. - - :param func: a coroutine function - :param args: positional arguments for the callable - :return: the return value of the coroutine function - - """ - try: - async_backend = threadlocals.current_async_backend - token = threadlocals.current_token - except AttributeError: - raise RuntimeError( - "This function can only be run from an AnyIO worker thread" - ) from None - - return async_backend.run_async_from_thread(func, args, token=token) - - -def run_sync( - func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] -) -> T_Retval: - """ - Call a function in the event loop thread from a worker thread. - - :param func: a callable - :param args: positional arguments for the callable - :return: the return value of the callable - - """ - try: - async_backend = threadlocals.current_async_backend - token = threadlocals.current_token - except AttributeError: - raise RuntimeError( - "This function can only be run from an AnyIO worker thread" - ) from None - - return async_backend.run_sync_from_thread(func, args, token=token) - - -class _BlockingAsyncContextManager(Generic[T_co], AbstractContextManager): - _enter_future: Future[T_co] - _exit_future: Future[bool | None] - _exit_event: Event - _exit_exc_info: tuple[ - type[BaseException] | None, BaseException | None, TracebackType | None - ] = (None, None, None) - - def __init__( - self, async_cm: AbstractAsyncContextManager[T_co], portal: BlockingPortal - ): - self._async_cm = async_cm - self._portal = portal - - async def run_async_cm(self) -> bool | None: - try: - self._exit_event = Event() - value = await self._async_cm.__aenter__() - except BaseException as exc: - self._enter_future.set_exception(exc) - raise - else: - self._enter_future.set_result(value) - - try: - # Wait for the sync context manager to exit. - # This next statement can raise `get_cancelled_exc_class()` if - # something went wrong in a task group in this async context - # manager. - await self._exit_event.wait() - finally: - # In case of cancellation, it could be that we end up here before - # `_BlockingAsyncContextManager.__exit__` is called, and an - # `_exit_exc_info` has been set. - result = await self._async_cm.__aexit__(*self._exit_exc_info) - return result - - def __enter__(self) -> T_co: - self._enter_future = Future() - self._exit_future = self._portal.start_task_soon(self.run_async_cm) - return self._enter_future.result() - - def __exit__( - self, - __exc_type: type[BaseException] | None, - __exc_value: BaseException | None, - __traceback: TracebackType | None, - ) -> bool | None: - self._exit_exc_info = __exc_type, __exc_value, __traceback - self._portal.call(self._exit_event.set) - return self._exit_future.result() - - -class _BlockingPortalTaskStatus(TaskStatus): - def __init__(self, future: Future): - self._future = future - - def started(self, value: object = None) -> None: - self._future.set_result(value) - - -class BlockingPortal: - """An object that lets external threads run code in an asynchronous event loop.""" - - def __new__(cls) -> BlockingPortal: - return get_async_backend().create_blocking_portal() - - def __init__(self) -> None: - self._event_loop_thread_id: int | None = get_ident() - self._stop_event = Event() - self._task_group = create_task_group() - self._cancelled_exc_class = get_cancelled_exc_class() - - async def __aenter__(self) -> BlockingPortal: - await self._task_group.__aenter__() - return self - - async def __aexit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool | None: - await self.stop() - return await self._task_group.__aexit__(exc_type, exc_val, exc_tb) - - def _check_running(self) -> None: - if self._event_loop_thread_id is None: - raise RuntimeError("This portal is not running") - if self._event_loop_thread_id == get_ident(): - raise RuntimeError( - "This method cannot be called from the event loop thread" - ) - - async def sleep_until_stopped(self) -> None: - """Sleep until :meth:`stop` is called.""" - await self._stop_event.wait() - - async def stop(self, cancel_remaining: bool = False) -> None: - """ - Signal the portal to shut down. - - This marks the portal as no longer accepting new calls and exits from - :meth:`sleep_until_stopped`. - - :param cancel_remaining: ``True`` to cancel all the remaining tasks, ``False`` - to let them finish before returning - - """ - self._event_loop_thread_id = None - self._stop_event.set() - if cancel_remaining: - self._task_group.cancel_scope.cancel() - - async def _call_func( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - future: Future[T_Retval], - ) -> None: - def callback(f: Future[T_Retval]) -> None: - if f.cancelled() and self._event_loop_thread_id not in ( - None, - get_ident(), - ): - self.call(scope.cancel) - - try: - retval_or_awaitable = func(*args, **kwargs) - if isawaitable(retval_or_awaitable): - with CancelScope() as scope: - if future.cancelled(): - scope.cancel() - else: - future.add_done_callback(callback) - - retval = await retval_or_awaitable - else: - retval = retval_or_awaitable - except self._cancelled_exc_class: - future.cancel() - future.set_running_or_notify_cancel() - except BaseException as exc: - if not future.cancelled(): - future.set_exception(exc) - - # Let base exceptions fall through - if not isinstance(exc, Exception): - raise - else: - if not future.cancelled(): - future.set_result(retval) - finally: - scope = None # type: ignore[assignment] - - def _spawn_task_from_thread( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - args: tuple[Unpack[PosArgsT]], - kwargs: dict[str, Any], - name: object, - future: Future[T_Retval], - ) -> None: - """ - Spawn a new task using the given callable. - - Implementers must ensure that the future is resolved when the task finishes. - - :param func: a callable - :param args: positional arguments to be passed to the callable - :param kwargs: keyword arguments to be passed to the callable - :param name: name of the task (will be coerced to a string if not ``None``) - :param future: a future that will resolve to the return value of the callable, - or the exception raised during its execution - - """ - raise NotImplementedError - - @overload - def call( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - ) -> T_Retval: ... - - @overload - def call( - self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] - ) -> T_Retval: ... - - def call( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - *args: Unpack[PosArgsT], - ) -> T_Retval: - """ - Call the given function in the event loop thread. - - If the callable returns a coroutine object, it is awaited on. - - :param func: any callable - :raises RuntimeError: if the portal is not running or if this method is called - from within the event loop thread - - """ - return cast(T_Retval, self.start_task_soon(func, *args).result()) - - @overload - def start_task_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], - *args: Unpack[PosArgsT], - name: object = None, - ) -> Future[T_Retval]: ... - - @overload - def start_task_soon( - self, - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - name: object = None, - ) -> Future[T_Retval]: ... - - def start_task_soon( - self, - func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval] | T_Retval], - *args: Unpack[PosArgsT], - name: object = None, - ) -> Future[T_Retval]: - """ - Start a task in the portal's task group. - - The task will be run inside a cancel scope which can be cancelled by cancelling - the returned future. - - :param func: the target function - :param args: positional arguments passed to ``func`` - :param name: name of the task (will be coerced to a string if not ``None``) - :return: a future that resolves with the return value of the callable if the - task completes successfully, or with the exception raised in the task - :raises RuntimeError: if the portal is not running or if this method is called - from within the event loop thread - :rtype: concurrent.futures.Future[T_Retval] - - .. versionadded:: 3.0 - - """ - self._check_running() - f: Future[T_Retval] = Future() - self._spawn_task_from_thread(func, args, {}, name, f) - return f - - def start_task( - self, - func: Callable[..., Awaitable[T_Retval]], - *args: object, - name: object = None, - ) -> tuple[Future[T_Retval], Any]: - """ - Start a task in the portal's task group and wait until it signals for readiness. - - This method works the same way as :meth:`.abc.TaskGroup.start`. - - :param func: the target function - :param args: positional arguments passed to ``func`` - :param name: name of the task (will be coerced to a string if not ``None``) - :return: a tuple of (future, task_status_value) where the ``task_status_value`` - is the value passed to ``task_status.started()`` from within the target - function - :rtype: tuple[concurrent.futures.Future[T_Retval], Any] - - .. versionadded:: 3.0 - - """ - - def task_done(future: Future[T_Retval]) -> None: - if not task_status_future.done(): - if future.cancelled(): - task_status_future.cancel() - elif future.exception(): - task_status_future.set_exception(future.exception()) - else: - exc = RuntimeError( - "Task exited without calling task_status.started()" - ) - task_status_future.set_exception(exc) - - self._check_running() - task_status_future: Future = Future() - task_status = _BlockingPortalTaskStatus(task_status_future) - f: Future = Future() - f.add_done_callback(task_done) - self._spawn_task_from_thread(func, args, {"task_status": task_status}, name, f) - return f, task_status_future.result() - - def wrap_async_context_manager( - self, cm: AbstractAsyncContextManager[T_co] - ) -> AbstractContextManager[T_co]: - """ - Wrap an async context manager as a synchronous context manager via this portal. - - Spawns a task that will call both ``__aenter__()`` and ``__aexit__()``, stopping - in the middle until the synchronous context manager exits. - - :param cm: an asynchronous context manager - :return: a synchronous context manager - - .. versionadded:: 2.1 - - """ - return _BlockingAsyncContextManager(cm, self) - - -@dataclass -class BlockingPortalProvider: - """ - A manager for a blocking portal. Used as a context manager. The first thread to - enter this context manager causes a blocking portal to be started with the specific - parameters, and the last thread to exit causes the portal to be shut down. Thus, - there will be exactly one blocking portal running in this context as long as at - least one thread has entered this context manager. - - The parameters are the same as for :func:`~anyio.run`. - - :param backend: name of the backend - :param backend_options: backend options - - .. versionadded:: 4.4 - """ - - backend: str = "asyncio" - backend_options: dict[str, Any] | None = None - _lock: Lock = field(init=False, default_factory=Lock) - _leases: int = field(init=False, default=0) - _portal: BlockingPortal = field(init=False) - _portal_cm: AbstractContextManager[BlockingPortal] | None = field( - init=False, default=None - ) - - def __enter__(self) -> BlockingPortal: - with self._lock: - if self._portal_cm is None: - self._portal_cm = start_blocking_portal( - self.backend, self.backend_options - ) - self._portal = self._portal_cm.__enter__() - - self._leases += 1 - return self._portal - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - portal_cm: AbstractContextManager[BlockingPortal] | None = None - with self._lock: - assert self._portal_cm - assert self._leases > 0 - self._leases -= 1 - if not self._leases: - portal_cm = self._portal_cm - self._portal_cm = None - del self._portal - - if portal_cm: - portal_cm.__exit__(None, None, None) - - -@contextmanager -def start_blocking_portal( - backend: str = "asyncio", backend_options: dict[str, Any] | None = None -) -> Generator[BlockingPortal, Any, None]: - """ - Start a new event loop in a new thread and run a blocking portal in its main task. - - The parameters are the same as for :func:`~anyio.run`. - - :param backend: name of the backend - :param backend_options: backend options - :return: a context manager that yields a blocking portal - - .. versionchanged:: 3.0 - Usage as a context manager is now required. - - """ - - async def run_portal() -> None: - async with BlockingPortal() as portal_: - future.set_result(portal_) - await portal_.sleep_until_stopped() - - def run_blocking_portal() -> None: - if future.set_running_or_notify_cancel(): - try: - _eventloop.run( - run_portal, backend=backend, backend_options=backend_options - ) - except BaseException as exc: - if not future.done(): - future.set_exception(exc) - - future: Future[BlockingPortal] = Future() - thread = Thread(target=run_blocking_portal, daemon=True) - thread.start() - try: - cancel_remaining_tasks = False - portal = future.result() - try: - yield portal - except BaseException: - cancel_remaining_tasks = True - raise - finally: - try: - portal.call(portal.stop, cancel_remaining_tasks) - except RuntimeError: - pass - finally: - thread.join() - - -def check_cancelled() -> None: - """ - Check if the cancel scope of the host task's running the current worker thread has - been cancelled. - - If the host task's current cancel scope has indeed been cancelled, the - backend-specific cancellation exception will be raised. - - :raises RuntimeError: if the current thread was not spawned by - :func:`.to_thread.run_sync` - - """ - try: - async_backend: AsyncBackend = threadlocals.current_async_backend - except AttributeError: - raise RuntimeError( - "This function can only be run from an AnyIO worker thread" - ) from None - - async_backend.check_cancelled() diff --git a/venv/lib/python3.12/site-packages/anyio/lowlevel.py b/venv/lib/python3.12/site-packages/anyio/lowlevel.py deleted file mode 100644 index 14c7668..0000000 --- a/venv/lib/python3.12/site-packages/anyio/lowlevel.py +++ /dev/null @@ -1,161 +0,0 @@ -from __future__ import annotations - -import enum -from dataclasses import dataclass -from typing import Any, Generic, Literal, TypeVar, overload -from weakref import WeakKeyDictionary - -from ._core._eventloop import get_async_backend - -T = TypeVar("T") -D = TypeVar("D") - - -async def checkpoint() -> None: - """ - Check for cancellation and allow the scheduler to switch to another task. - - Equivalent to (but more efficient than):: - - await checkpoint_if_cancelled() - await cancel_shielded_checkpoint() - - - .. versionadded:: 3.0 - - """ - await get_async_backend().checkpoint() - - -async def checkpoint_if_cancelled() -> None: - """ - Enter a checkpoint if the enclosing cancel scope has been cancelled. - - This does not allow the scheduler to switch to a different task. - - .. versionadded:: 3.0 - - """ - await get_async_backend().checkpoint_if_cancelled() - - -async def cancel_shielded_checkpoint() -> None: - """ - Allow the scheduler to switch to another task but without checking for cancellation. - - Equivalent to (but potentially more efficient than):: - - with CancelScope(shield=True): - await checkpoint() - - - .. versionadded:: 3.0 - - """ - await get_async_backend().cancel_shielded_checkpoint() - - -def current_token() -> object: - """ - Return a backend specific token object that can be used to get back to the event - loop. - - """ - return get_async_backend().current_token() - - -_run_vars: WeakKeyDictionary[Any, dict[str, Any]] = WeakKeyDictionary() -_token_wrappers: dict[Any, _TokenWrapper] = {} - - -@dataclass(frozen=True) -class _TokenWrapper: - __slots__ = "_token", "__weakref__" - _token: object - - -class _NoValueSet(enum.Enum): - NO_VALUE_SET = enum.auto() - - -class RunvarToken(Generic[T]): - __slots__ = "_var", "_value", "_redeemed" - - def __init__(self, var: RunVar[T], value: T | Literal[_NoValueSet.NO_VALUE_SET]): - self._var = var - self._value: T | Literal[_NoValueSet.NO_VALUE_SET] = value - self._redeemed = False - - -class RunVar(Generic[T]): - """ - Like a :class:`~contextvars.ContextVar`, except scoped to the running event loop. - """ - - __slots__ = "_name", "_default" - - NO_VALUE_SET: Literal[_NoValueSet.NO_VALUE_SET] = _NoValueSet.NO_VALUE_SET - - _token_wrappers: set[_TokenWrapper] = set() - - def __init__( - self, name: str, default: T | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET - ): - self._name = name - self._default = default - - @property - def _current_vars(self) -> dict[str, T]: - token = current_token() - try: - return _run_vars[token] - except KeyError: - run_vars = _run_vars[token] = {} - return run_vars - - @overload - def get(self, default: D) -> T | D: ... - - @overload - def get(self) -> T: ... - - def get( - self, default: D | Literal[_NoValueSet.NO_VALUE_SET] = NO_VALUE_SET - ) -> T | D: - try: - return self._current_vars[self._name] - except KeyError: - if default is not RunVar.NO_VALUE_SET: - return default - elif self._default is not RunVar.NO_VALUE_SET: - return self._default - - raise LookupError( - f'Run variable "{self._name}" has no value and no default set' - ) - - def set(self, value: T) -> RunvarToken[T]: - current_vars = self._current_vars - token = RunvarToken(self, current_vars.get(self._name, RunVar.NO_VALUE_SET)) - current_vars[self._name] = value - return token - - def reset(self, token: RunvarToken[T]) -> None: - if token._var is not self: - raise ValueError("This token does not belong to this RunVar") - - if token._redeemed: - raise ValueError("This token has already been used") - - if token._value is _NoValueSet.NO_VALUE_SET: - try: - del self._current_vars[self._name] - except KeyError: - pass - else: - self._current_vars[self._name] = token._value - - token._redeemed = True - - def __repr__(self) -> str: - return f"" diff --git a/venv/lib/python3.12/site-packages/anyio/py.typed b/venv/lib/python3.12/site-packages/anyio/py.typed deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/anyio/pytest_plugin.py b/venv/lib/python3.12/site-packages/anyio/pytest_plugin.py deleted file mode 100644 index 21e4ab2..0000000 --- a/venv/lib/python3.12/site-packages/anyio/pytest_plugin.py +++ /dev/null @@ -1,272 +0,0 @@ -from __future__ import annotations - -import socket -import sys -from collections.abc import Callable, Generator, Iterator -from contextlib import ExitStack, contextmanager -from inspect import isasyncgenfunction, iscoroutinefunction, ismethod -from typing import Any, cast - -import pytest -import sniffio -from _pytest.fixtures import SubRequest -from _pytest.outcomes import Exit - -from ._core._eventloop import get_all_backends, get_async_backend -from ._core._exceptions import iterate_exceptions -from .abc import TestRunner - -if sys.version_info < (3, 11): - from exceptiongroup import ExceptionGroup - -_current_runner: TestRunner | None = None -_runner_stack: ExitStack | None = None -_runner_leases = 0 - - -def extract_backend_and_options(backend: object) -> tuple[str, dict[str, Any]]: - if isinstance(backend, str): - return backend, {} - elif isinstance(backend, tuple) and len(backend) == 2: - if isinstance(backend[0], str) and isinstance(backend[1], dict): - return cast(tuple[str, dict[str, Any]], backend) - - raise TypeError("anyio_backend must be either a string or tuple of (string, dict)") - - -@contextmanager -def get_runner( - backend_name: str, backend_options: dict[str, Any] -) -> Iterator[TestRunner]: - global _current_runner, _runner_leases, _runner_stack - if _current_runner is None: - asynclib = get_async_backend(backend_name) - _runner_stack = ExitStack() - if sniffio.current_async_library_cvar.get(None) is None: - # Since we're in control of the event loop, we can cache the name of the - # async library - token = sniffio.current_async_library_cvar.set(backend_name) - _runner_stack.callback(sniffio.current_async_library_cvar.reset, token) - - backend_options = backend_options or {} - _current_runner = _runner_stack.enter_context( - asynclib.create_test_runner(backend_options) - ) - - _runner_leases += 1 - try: - yield _current_runner - finally: - _runner_leases -= 1 - if not _runner_leases: - assert _runner_stack is not None - _runner_stack.close() - _runner_stack = _current_runner = None - - -def pytest_configure(config: Any) -> None: - config.addinivalue_line( - "markers", - "anyio: mark the (coroutine function) test to be run asynchronously via anyio.", - ) - - -@pytest.hookimpl(hookwrapper=True) -def pytest_fixture_setup(fixturedef: Any, request: Any) -> Generator[Any]: - def wrapper( - *args: Any, anyio_backend: Any, request: SubRequest, **kwargs: Any - ) -> Any: - # Rebind any fixture methods to the request instance - if ( - request.instance - and ismethod(func) - and type(func.__self__) is type(request.instance) - ): - local_func = func.__func__.__get__(request.instance) - else: - local_func = func - - backend_name, backend_options = extract_backend_and_options(anyio_backend) - if has_backend_arg: - kwargs["anyio_backend"] = anyio_backend - - if has_request_arg: - kwargs["request"] = request - - with get_runner(backend_name, backend_options) as runner: - if isasyncgenfunction(local_func): - yield from runner.run_asyncgen_fixture(local_func, kwargs) - else: - yield runner.run_fixture(local_func, kwargs) - - # Only apply this to coroutine functions and async generator functions in requests - # that involve the anyio_backend fixture - func = fixturedef.func - if isasyncgenfunction(func) or iscoroutinefunction(func): - if "anyio_backend" in request.fixturenames: - fixturedef.func = wrapper - original_argname = fixturedef.argnames - - if not (has_backend_arg := "anyio_backend" in fixturedef.argnames): - fixturedef.argnames += ("anyio_backend",) - - if not (has_request_arg := "request" in fixturedef.argnames): - fixturedef.argnames += ("request",) - - try: - return (yield) - finally: - fixturedef.func = func - fixturedef.argnames = original_argname - - return (yield) - - -@pytest.hookimpl(tryfirst=True) -def pytest_pycollect_makeitem(collector: Any, name: Any, obj: Any) -> None: - if collector.istestfunction(obj, name): - inner_func = obj.hypothesis.inner_test if hasattr(obj, "hypothesis") else obj - if iscoroutinefunction(inner_func): - marker = collector.get_closest_marker("anyio") - own_markers = getattr(obj, "pytestmark", ()) - if marker or any(marker.name == "anyio" for marker in own_markers): - pytest.mark.usefixtures("anyio_backend")(obj) - - -@pytest.hookimpl(tryfirst=True) -def pytest_pyfunc_call(pyfuncitem: Any) -> bool | None: - def run_with_hypothesis(**kwargs: Any) -> None: - with get_runner(backend_name, backend_options) as runner: - runner.run_test(original_func, kwargs) - - backend = pyfuncitem.funcargs.get("anyio_backend") - if backend: - backend_name, backend_options = extract_backend_and_options(backend) - - if hasattr(pyfuncitem.obj, "hypothesis"): - # Wrap the inner test function unless it's already wrapped - original_func = pyfuncitem.obj.hypothesis.inner_test - if original_func.__qualname__ != run_with_hypothesis.__qualname__: - if iscoroutinefunction(original_func): - pyfuncitem.obj.hypothesis.inner_test = run_with_hypothesis - - return None - - if iscoroutinefunction(pyfuncitem.obj): - funcargs = pyfuncitem.funcargs - testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames} - with get_runner(backend_name, backend_options) as runner: - try: - runner.run_test(pyfuncitem.obj, testargs) - except ExceptionGroup as excgrp: - for exc in iterate_exceptions(excgrp): - if isinstance(exc, (Exit, KeyboardInterrupt, SystemExit)): - raise exc from excgrp - - raise - - return True - - return None - - -@pytest.fixture(scope="module", params=get_all_backends()) -def anyio_backend(request: Any) -> Any: - return request.param - - -@pytest.fixture -def anyio_backend_name(anyio_backend: Any) -> str: - if isinstance(anyio_backend, str): - return anyio_backend - else: - return anyio_backend[0] - - -@pytest.fixture -def anyio_backend_options(anyio_backend: Any) -> dict[str, Any]: - if isinstance(anyio_backend, str): - return {} - else: - return anyio_backend[1] - - -class FreePortFactory: - """ - Manages port generation based on specified socket kind, ensuring no duplicate - ports are generated. - - This class provides functionality for generating available free ports on the - system. It is initialized with a specific socket kind and can generate ports - for given address families while avoiding reuse of previously generated ports. - - Users should not instantiate this class directly, but use the - ``free_tcp_port_factory`` and ``free_udp_port_factory`` fixtures instead. For simple - uses cases, ``free_tcp_port`` and ``free_udp_port`` can be used instead. - """ - - def __init__(self, kind: socket.SocketKind) -> None: - self._kind = kind - self._generated = set[int]() - - @property - def kind(self) -> socket.SocketKind: - """ - The type of socket connection (e.g., :data:`~socket.SOCK_STREAM` or - :data:`~socket.SOCK_DGRAM`) used to bind for checking port availability - - """ - return self._kind - - def __call__(self, family: socket.AddressFamily | None = None) -> int: - """ - Return an unbound port for the given address family. - - :param family: if omitted, both IPv4 and IPv6 addresses will be tried - :return: a port number - - """ - if family is not None: - families = [family] - else: - families = [socket.AF_INET] - if socket.has_ipv6: - families.append(socket.AF_INET6) - - while True: - port = 0 - with ExitStack() as stack: - for family in families: - sock = stack.enter_context(socket.socket(family, self._kind)) - addr = "::1" if family == socket.AF_INET6 else "127.0.0.1" - try: - sock.bind((addr, port)) - except OSError: - break - - if not port: - port = sock.getsockname()[1] - else: - if port not in self._generated: - self._generated.add(port) - return port - - -@pytest.fixture(scope="session") -def free_tcp_port_factory() -> FreePortFactory: - return FreePortFactory(socket.SOCK_STREAM) - - -@pytest.fixture(scope="session") -def free_udp_port_factory() -> FreePortFactory: - return FreePortFactory(socket.SOCK_DGRAM) - - -@pytest.fixture -def free_tcp_port(free_tcp_port_factory: Callable[[], int]) -> int: - return free_tcp_port_factory() - - -@pytest.fixture -def free_udp_port(free_udp_port_factory: Callable[[], int]) -> int: - return free_udp_port_factory() diff --git a/venv/lib/python3.12/site-packages/anyio/streams/__init__.py b/venv/lib/python3.12/site-packages/anyio/streams/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index edce2b43d3cae6ea43390e91921bba8147018e3b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 183 zcmX@j%ge<81nM7Or-SInAOanHW&w&!XQ*V*Wb|9fP{ah}eFmxd6{eq&pPQJXUz}Nzs#}nloSm4STCAU# zSDBfwUtCg@nwVRxA0MBYmst`YuUAm{i^C>2KczG$)vkyYXbmF}7lRldnHd=wi<{9 diff --git a/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/buffered.cpython-312.pyc deleted file mode 100644 index e7dea36d0f598fe3695cde7bcb089d10ecd2307e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6112 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 SC|ylsFBzB4{(}I+$Nvu$vz^KS diff --git a/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/memory.cpython-312.pyc deleted file mode 100644 index 0596edadf93def957d9d75a404ab96a7c58e0535..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14944 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 NnY6(J6DH|m{SO{T!S4V7 diff --git a/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/stapled.cpython-312.pyc deleted file mode 100644 index 4ceba34de9dee0cdb06a26d37954084bd5dfac1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7544 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 M&A9H1K(Sr_8|jmx!~g&Q diff --git a/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc b/venv/lib/python3.12/site-packages/anyio/streams/__pycache__/tls.cpython-312.pyc deleted file mode 100644 index 439ed559cbe3ce7af8490f995b747ba6c0d7b273..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17567 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 diff --git a/venv/lib/python3.12/site-packages/anyio/streams/buffered.py b/venv/lib/python3.12/site-packages/anyio/streams/buffered.py deleted file mode 100644 index f5d5e83..0000000 --- a/venv/lib/python3.12/site-packages/anyio/streams/buffered.py +++ /dev/null @@ -1,119 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, Mapping -from dataclasses import dataclass, field -from typing import Any - -from .. import ClosedResourceError, DelimiterNotFound, EndOfStream, IncompleteRead -from ..abc import AnyByteReceiveStream, ByteReceiveStream - - -@dataclass(eq=False) -class BufferedByteReceiveStream(ByteReceiveStream): - """ - Wraps any bytes-based receive stream and uses a buffer to provide sophisticated - receiving capabilities in the form of a byte stream. - """ - - receive_stream: AnyByteReceiveStream - _buffer: bytearray = field(init=False, default_factory=bytearray) - _closed: bool = field(init=False, default=False) - - async def aclose(self) -> None: - await self.receive_stream.aclose() - self._closed = True - - @property - def buffer(self) -> bytes: - """The bytes currently in the buffer.""" - return bytes(self._buffer) - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return self.receive_stream.extra_attributes - - async def receive(self, max_bytes: int = 65536) -> bytes: - if self._closed: - raise ClosedResourceError - - if self._buffer: - chunk = bytes(self._buffer[:max_bytes]) - del self._buffer[:max_bytes] - return chunk - elif isinstance(self.receive_stream, ByteReceiveStream): - return await self.receive_stream.receive(max_bytes) - else: - # With a bytes-oriented object stream, we need to handle any surplus bytes - # we get from the receive() call - chunk = await self.receive_stream.receive() - if len(chunk) > max_bytes: - # Save the surplus bytes in the buffer - self._buffer.extend(chunk[max_bytes:]) - return chunk[:max_bytes] - else: - return chunk - - async def receive_exactly(self, nbytes: int) -> bytes: - """ - Read exactly the given amount of bytes from the stream. - - :param nbytes: the number of bytes to read - :return: the bytes read - :raises ~anyio.IncompleteRead: if the stream was closed before the requested - amount of bytes could be read from the stream - - """ - while True: - remaining = nbytes - len(self._buffer) - if remaining <= 0: - retval = self._buffer[:nbytes] - del self._buffer[:nbytes] - return bytes(retval) - - try: - if isinstance(self.receive_stream, ByteReceiveStream): - chunk = await self.receive_stream.receive(remaining) - else: - chunk = await self.receive_stream.receive() - except EndOfStream as exc: - raise IncompleteRead from exc - - self._buffer.extend(chunk) - - async def receive_until(self, delimiter: bytes, max_bytes: int) -> bytes: - """ - Read from the stream until the delimiter is found or max_bytes have been read. - - :param delimiter: the marker to look for in the stream - :param max_bytes: maximum number of bytes that will be read before raising - :exc:`~anyio.DelimiterNotFound` - :return: the bytes read (not including the delimiter) - :raises ~anyio.IncompleteRead: if the stream was closed before the delimiter - was found - :raises ~anyio.DelimiterNotFound: if the delimiter is not found within the - bytes read up to the maximum allowed - - """ - delimiter_size = len(delimiter) - offset = 0 - while True: - # Check if the delimiter can be found in the current buffer - index = self._buffer.find(delimiter, offset) - if index >= 0: - found = self._buffer[:index] - del self._buffer[: index + len(delimiter) :] - return bytes(found) - - # Check if the buffer is already at or over the limit - if len(self._buffer) >= max_bytes: - raise DelimiterNotFound(max_bytes) - - # Read more data into the buffer from the socket - try: - data = await self.receive_stream.receive() - except EndOfStream as exc: - raise IncompleteRead from exc - - # Move the offset forward and add the new data to the buffer - offset = max(len(self._buffer) - delimiter_size + 1, 0) - self._buffer.extend(data) diff --git a/venv/lib/python3.12/site-packages/anyio/streams/file.py b/venv/lib/python3.12/site-packages/anyio/streams/file.py deleted file mode 100644 index f492464..0000000 --- a/venv/lib/python3.12/site-packages/anyio/streams/file.py +++ /dev/null @@ -1,148 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, Mapping -from io import SEEK_SET, UnsupportedOperation -from os import PathLike -from pathlib import Path -from typing import Any, BinaryIO, cast - -from .. import ( - BrokenResourceError, - ClosedResourceError, - EndOfStream, - TypedAttributeSet, - to_thread, - typed_attribute, -) -from ..abc import ByteReceiveStream, ByteSendStream - - -class FileStreamAttribute(TypedAttributeSet): - #: the open file descriptor - file: BinaryIO = typed_attribute() - #: the path of the file on the file system, if available (file must be a real file) - path: Path = typed_attribute() - #: the file number, if available (file must be a real file or a TTY) - fileno: int = typed_attribute() - - -class _BaseFileStream: - def __init__(self, file: BinaryIO): - self._file = file - - async def aclose(self) -> None: - await to_thread.run_sync(self._file.close) - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - attributes: dict[Any, Callable[[], Any]] = { - FileStreamAttribute.file: lambda: self._file, - } - - if hasattr(self._file, "name"): - attributes[FileStreamAttribute.path] = lambda: Path(self._file.name) - - try: - self._file.fileno() - except UnsupportedOperation: - pass - else: - attributes[FileStreamAttribute.fileno] = lambda: self._file.fileno() - - return attributes - - -class FileReadStream(_BaseFileStream, ByteReceiveStream): - """ - A byte stream that reads from a file in the file system. - - :param file: a file that has been opened for reading in binary mode - - .. versionadded:: 3.0 - """ - - @classmethod - async def from_path(cls, path: str | PathLike[str]) -> FileReadStream: - """ - Create a file read stream by opening the given file. - - :param path: path of the file to read from - - """ - file = await to_thread.run_sync(Path(path).open, "rb") - return cls(cast(BinaryIO, file)) - - async def receive(self, max_bytes: int = 65536) -> bytes: - try: - data = await to_thread.run_sync(self._file.read, max_bytes) - except ValueError: - raise ClosedResourceError from None - except OSError as exc: - raise BrokenResourceError from exc - - if data: - return data - else: - raise EndOfStream - - async def seek(self, position: int, whence: int = SEEK_SET) -> int: - """ - Seek the file to the given position. - - .. seealso:: :meth:`io.IOBase.seek` - - .. note:: Not all file descriptors are seekable. - - :param position: position to seek the file to - :param whence: controls how ``position`` is interpreted - :return: the new absolute position - :raises OSError: if the file is not seekable - - """ - return await to_thread.run_sync(self._file.seek, position, whence) - - async def tell(self) -> int: - """ - Return the current stream position. - - .. note:: Not all file descriptors are seekable. - - :return: the current absolute position - :raises OSError: if the file is not seekable - - """ - return await to_thread.run_sync(self._file.tell) - - -class FileWriteStream(_BaseFileStream, ByteSendStream): - """ - A byte stream that writes to a file in the file system. - - :param file: a file that has been opened for writing in binary mode - - .. versionadded:: 3.0 - """ - - @classmethod - async def from_path( - cls, path: str | PathLike[str], append: bool = False - ) -> FileWriteStream: - """ - Create a file write stream by opening the given file for writing. - - :param path: path of the file to write to - :param append: if ``True``, open the file for appending; if ``False``, any - existing file at the given path will be truncated - - """ - mode = "ab" if append else "wb" - file = await to_thread.run_sync(Path(path).open, mode) - return cls(cast(BinaryIO, file)) - - async def send(self, item: bytes) -> None: - try: - await to_thread.run_sync(self._file.write, item) - except ValueError: - raise ClosedResourceError from None - except OSError as exc: - raise BrokenResourceError from exc diff --git a/venv/lib/python3.12/site-packages/anyio/streams/memory.py b/venv/lib/python3.12/site-packages/anyio/streams/memory.py deleted file mode 100644 index 83bf1d9..0000000 --- a/venv/lib/python3.12/site-packages/anyio/streams/memory.py +++ /dev/null @@ -1,317 +0,0 @@ -from __future__ import annotations - -import warnings -from collections import OrderedDict, deque -from dataclasses import dataclass, field -from types import TracebackType -from typing import Generic, NamedTuple, TypeVar - -from .. import ( - BrokenResourceError, - ClosedResourceError, - EndOfStream, - WouldBlock, -) -from .._core._testing import TaskInfo, get_current_task -from ..abc import Event, ObjectReceiveStream, ObjectSendStream -from ..lowlevel import checkpoint - -T_Item = TypeVar("T_Item") -T_co = TypeVar("T_co", covariant=True) -T_contra = TypeVar("T_contra", contravariant=True) - - -class MemoryObjectStreamStatistics(NamedTuple): - current_buffer_used: int #: number of items stored in the buffer - #: maximum number of items that can be stored on this stream (or :data:`math.inf`) - max_buffer_size: float - open_send_streams: int #: number of unclosed clones of the send stream - open_receive_streams: int #: number of unclosed clones of the receive stream - #: number of tasks blocked on :meth:`MemoryObjectSendStream.send` - tasks_waiting_send: int - #: number of tasks blocked on :meth:`MemoryObjectReceiveStream.receive` - tasks_waiting_receive: int - - -@dataclass(eq=False) -class MemoryObjectItemReceiver(Generic[T_Item]): - task_info: TaskInfo = field(init=False, default_factory=get_current_task) - item: T_Item = field(init=False) - - def __repr__(self) -> str: - # When item is not defined, we get following error with default __repr__: - # AttributeError: 'MemoryObjectItemReceiver' object has no attribute 'item' - item = getattr(self, "item", None) - return f"{self.__class__.__name__}(task_info={self.task_info}, item={item!r})" - - -@dataclass(eq=False) -class MemoryObjectStreamState(Generic[T_Item]): - max_buffer_size: float = field() - buffer: deque[T_Item] = field(init=False, default_factory=deque) - open_send_channels: int = field(init=False, default=0) - open_receive_channels: int = field(init=False, default=0) - waiting_receivers: OrderedDict[Event, MemoryObjectItemReceiver[T_Item]] = field( - init=False, default_factory=OrderedDict - ) - waiting_senders: OrderedDict[Event, T_Item] = field( - init=False, default_factory=OrderedDict - ) - - def statistics(self) -> MemoryObjectStreamStatistics: - return MemoryObjectStreamStatistics( - len(self.buffer), - self.max_buffer_size, - self.open_send_channels, - self.open_receive_channels, - len(self.waiting_senders), - len(self.waiting_receivers), - ) - - -@dataclass(eq=False) -class MemoryObjectReceiveStream(Generic[T_co], ObjectReceiveStream[T_co]): - _state: MemoryObjectStreamState[T_co] - _closed: bool = field(init=False, default=False) - - def __post_init__(self) -> None: - self._state.open_receive_channels += 1 - - def receive_nowait(self) -> T_co: - """ - Receive the next item if it can be done without waiting. - - :return: the received item - :raises ~anyio.ClosedResourceError: if this send stream has been closed - :raises ~anyio.EndOfStream: if the buffer is empty and this stream has been - closed from the sending end - :raises ~anyio.WouldBlock: if there are no items in the buffer and no tasks - waiting to send - - """ - if self._closed: - raise ClosedResourceError - - if self._state.waiting_senders: - # Get the item from the next sender - send_event, item = self._state.waiting_senders.popitem(last=False) - self._state.buffer.append(item) - send_event.set() - - if self._state.buffer: - return self._state.buffer.popleft() - elif not self._state.open_send_channels: - raise EndOfStream - - raise WouldBlock - - async def receive(self) -> T_co: - await checkpoint() - try: - return self.receive_nowait() - except WouldBlock: - # Add ourselves in the queue - receive_event = Event() - receiver = MemoryObjectItemReceiver[T_co]() - self._state.waiting_receivers[receive_event] = receiver - - try: - await receive_event.wait() - finally: - self._state.waiting_receivers.pop(receive_event, None) - - try: - return receiver.item - except AttributeError: - raise EndOfStream from None - - def clone(self) -> MemoryObjectReceiveStream[T_co]: - """ - Create a clone of this receive stream. - - Each clone can be closed separately. Only when all clones have been closed will - the receiving end of the memory stream be considered closed by the sending ends. - - :return: the cloned stream - - """ - if self._closed: - raise ClosedResourceError - - return MemoryObjectReceiveStream(_state=self._state) - - def close(self) -> None: - """ - Close the stream. - - This works the exact same way as :meth:`aclose`, but is provided as a special - case for the benefit of synchronous callbacks. - - """ - if not self._closed: - self._closed = True - self._state.open_receive_channels -= 1 - if self._state.open_receive_channels == 0: - send_events = list(self._state.waiting_senders.keys()) - for event in send_events: - event.set() - - async def aclose(self) -> None: - self.close() - - def statistics(self) -> MemoryObjectStreamStatistics: - """ - Return statistics about the current state of this stream. - - .. versionadded:: 3.0 - """ - return self._state.statistics() - - def __enter__(self) -> MemoryObjectReceiveStream[T_co]: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.close() - - def __del__(self) -> None: - if not self._closed: - warnings.warn( - f"Unclosed <{self.__class__.__name__} at {id(self):x}>", - ResourceWarning, - source=self, - ) - - -@dataclass(eq=False) -class MemoryObjectSendStream(Generic[T_contra], ObjectSendStream[T_contra]): - _state: MemoryObjectStreamState[T_contra] - _closed: bool = field(init=False, default=False) - - def __post_init__(self) -> None: - self._state.open_send_channels += 1 - - def send_nowait(self, item: T_contra) -> None: - """ - Send an item immediately if it can be done without waiting. - - :param item: the item to send - :raises ~anyio.ClosedResourceError: if this send stream has been closed - :raises ~anyio.BrokenResourceError: if the stream has been closed from the - receiving end - :raises ~anyio.WouldBlock: if the buffer is full and there are no tasks waiting - to receive - - """ - if self._closed: - raise ClosedResourceError - if not self._state.open_receive_channels: - raise BrokenResourceError - - while self._state.waiting_receivers: - receive_event, receiver = self._state.waiting_receivers.popitem(last=False) - if not receiver.task_info.has_pending_cancellation(): - receiver.item = item - receive_event.set() - return - - if len(self._state.buffer) < self._state.max_buffer_size: - self._state.buffer.append(item) - else: - raise WouldBlock - - async def send(self, item: T_contra) -> None: - """ - Send an item to the stream. - - If the buffer is full, this method blocks until there is again room in the - buffer or the item can be sent directly to a receiver. - - :param item: the item to send - :raises ~anyio.ClosedResourceError: if this send stream has been closed - :raises ~anyio.BrokenResourceError: if the stream has been closed from the - receiving end - - """ - await checkpoint() - try: - self.send_nowait(item) - except WouldBlock: - # Wait until there's someone on the receiving end - send_event = Event() - self._state.waiting_senders[send_event] = item - try: - await send_event.wait() - except BaseException: - self._state.waiting_senders.pop(send_event, None) - raise - - if send_event in self._state.waiting_senders: - del self._state.waiting_senders[send_event] - raise BrokenResourceError from None - - def clone(self) -> MemoryObjectSendStream[T_contra]: - """ - Create a clone of this send stream. - - Each clone can be closed separately. Only when all clones have been closed will - the sending end of the memory stream be considered closed by the receiving ends. - - :return: the cloned stream - - """ - if self._closed: - raise ClosedResourceError - - return MemoryObjectSendStream(_state=self._state) - - def close(self) -> None: - """ - Close the stream. - - This works the exact same way as :meth:`aclose`, but is provided as a special - case for the benefit of synchronous callbacks. - - """ - if not self._closed: - self._closed = True - self._state.open_send_channels -= 1 - if self._state.open_send_channels == 0: - receive_events = list(self._state.waiting_receivers.keys()) - self._state.waiting_receivers.clear() - for event in receive_events: - event.set() - - async def aclose(self) -> None: - self.close() - - def statistics(self) -> MemoryObjectStreamStatistics: - """ - Return statistics about the current state of this stream. - - .. versionadded:: 3.0 - """ - return self._state.statistics() - - def __enter__(self) -> MemoryObjectSendStream[T_contra]: - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - self.close() - - def __del__(self) -> None: - if not self._closed: - warnings.warn( - f"Unclosed <{self.__class__.__name__} at {id(self):x}>", - ResourceWarning, - source=self, - ) diff --git a/venv/lib/python3.12/site-packages/anyio/streams/stapled.py b/venv/lib/python3.12/site-packages/anyio/streams/stapled.py deleted file mode 100644 index 80f64a2..0000000 --- a/venv/lib/python3.12/site-packages/anyio/streams/stapled.py +++ /dev/null @@ -1,141 +0,0 @@ -from __future__ import annotations - -from collections.abc import Callable, Mapping, Sequence -from dataclasses import dataclass -from typing import Any, Generic, TypeVar - -from ..abc import ( - ByteReceiveStream, - ByteSendStream, - ByteStream, - Listener, - ObjectReceiveStream, - ObjectSendStream, - ObjectStream, - TaskGroup, -) - -T_Item = TypeVar("T_Item") -T_Stream = TypeVar("T_Stream") - - -@dataclass(eq=False) -class StapledByteStream(ByteStream): - """ - Combines two byte streams into a single, bidirectional byte stream. - - Extra attributes will be provided from both streams, with the receive stream - providing the values in case of a conflict. - - :param ByteSendStream send_stream: the sending byte stream - :param ByteReceiveStream receive_stream: the receiving byte stream - """ - - send_stream: ByteSendStream - receive_stream: ByteReceiveStream - - async def receive(self, max_bytes: int = 65536) -> bytes: - return await self.receive_stream.receive(max_bytes) - - async def send(self, item: bytes) -> None: - await self.send_stream.send(item) - - async def send_eof(self) -> None: - await self.send_stream.aclose() - - async def aclose(self) -> None: - await self.send_stream.aclose() - await self.receive_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self.send_stream.extra_attributes, - **self.receive_stream.extra_attributes, - } - - -@dataclass(eq=False) -class StapledObjectStream(Generic[T_Item], ObjectStream[T_Item]): - """ - Combines two object streams into a single, bidirectional object stream. - - Extra attributes will be provided from both streams, with the receive stream - providing the values in case of a conflict. - - :param ObjectSendStream send_stream: the sending object stream - :param ObjectReceiveStream receive_stream: the receiving object stream - """ - - send_stream: ObjectSendStream[T_Item] - receive_stream: ObjectReceiveStream[T_Item] - - async def receive(self) -> T_Item: - return await self.receive_stream.receive() - - async def send(self, item: T_Item) -> None: - await self.send_stream.send(item) - - async def send_eof(self) -> None: - await self.send_stream.aclose() - - async def aclose(self) -> None: - await self.send_stream.aclose() - await self.receive_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self.send_stream.extra_attributes, - **self.receive_stream.extra_attributes, - } - - -@dataclass(eq=False) -class MultiListener(Generic[T_Stream], Listener[T_Stream]): - """ - Combines multiple listeners into one, serving connections from all of them at once. - - Any MultiListeners in the given collection of listeners will have their listeners - moved into this one. - - Extra attributes are provided from each listener, with each successive listener - overriding any conflicting attributes from the previous one. - - :param listeners: listeners to serve - :type listeners: Sequence[Listener[T_Stream]] - """ - - listeners: Sequence[Listener[T_Stream]] - - def __post_init__(self) -> None: - listeners: list[Listener[T_Stream]] = [] - for listener in self.listeners: - if isinstance(listener, MultiListener): - listeners.extend(listener.listeners) - del listener.listeners[:] # type: ignore[attr-defined] - else: - listeners.append(listener) - - self.listeners = listeners - - async def serve( - self, handler: Callable[[T_Stream], Any], task_group: TaskGroup | None = None - ) -> None: - from .. import create_task_group - - async with create_task_group() as tg: - for listener in self.listeners: - tg.start_soon(listener.serve, handler, task_group) - - async def aclose(self) -> None: - for listener in self.listeners: - await listener.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - attributes: dict = {} - for listener in self.listeners: - attributes.update(listener.extra_attributes) - - return attributes diff --git a/venv/lib/python3.12/site-packages/anyio/streams/text.py b/venv/lib/python3.12/site-packages/anyio/streams/text.py deleted file mode 100644 index f1a1127..0000000 --- a/venv/lib/python3.12/site-packages/anyio/streams/text.py +++ /dev/null @@ -1,147 +0,0 @@ -from __future__ import annotations - -import codecs -from collections.abc import Callable, Mapping -from dataclasses import InitVar, dataclass, field -from typing import Any - -from ..abc import ( - AnyByteReceiveStream, - AnyByteSendStream, - AnyByteStream, - ObjectReceiveStream, - ObjectSendStream, - ObjectStream, -) - - -@dataclass(eq=False) -class TextReceiveStream(ObjectReceiveStream[str]): - """ - Stream wrapper that decodes bytes to strings using the given encoding. - - Decoding is done using :class:`~codecs.IncrementalDecoder` which returns any - completely received unicode characters as soon as they come in. - - :param transport_stream: any bytes-based receive stream - :param encoding: character encoding to use for decoding bytes to strings (defaults - to ``utf-8``) - :param errors: handling scheme for decoding errors (defaults to ``strict``; see the - `codecs module documentation`_ for a comprehensive list of options) - - .. _codecs module documentation: - https://docs.python.org/3/library/codecs.html#codec-objects - """ - - transport_stream: AnyByteReceiveStream - encoding: InitVar[str] = "utf-8" - errors: InitVar[str] = "strict" - _decoder: codecs.IncrementalDecoder = field(init=False) - - def __post_init__(self, encoding: str, errors: str) -> None: - decoder_class = codecs.getincrementaldecoder(encoding) - self._decoder = decoder_class(errors=errors) - - async def receive(self) -> str: - while True: - chunk = await self.transport_stream.receive() - decoded = self._decoder.decode(chunk) - if decoded: - return decoded - - async def aclose(self) -> None: - await self.transport_stream.aclose() - self._decoder.reset() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return self.transport_stream.extra_attributes - - -@dataclass(eq=False) -class TextSendStream(ObjectSendStream[str]): - """ - Sends strings to the wrapped stream as bytes using the given encoding. - - :param AnyByteSendStream transport_stream: any bytes-based send stream - :param str encoding: character encoding to use for encoding strings to bytes - (defaults to ``utf-8``) - :param str errors: handling scheme for encoding errors (defaults to ``strict``; see - the `codecs module documentation`_ for a comprehensive list of options) - - .. _codecs module documentation: - https://docs.python.org/3/library/codecs.html#codec-objects - """ - - transport_stream: AnyByteSendStream - encoding: InitVar[str] = "utf-8" - errors: str = "strict" - _encoder: Callable[..., tuple[bytes, int]] = field(init=False) - - def __post_init__(self, encoding: str) -> None: - self._encoder = codecs.getencoder(encoding) - - async def send(self, item: str) -> None: - encoded = self._encoder(item, self.errors)[0] - await self.transport_stream.send(encoded) - - async def aclose(self) -> None: - await self.transport_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return self.transport_stream.extra_attributes - - -@dataclass(eq=False) -class TextStream(ObjectStream[str]): - """ - A bidirectional stream that decodes bytes to strings on receive and encodes strings - to bytes on send. - - Extra attributes will be provided from both streams, with the receive stream - providing the values in case of a conflict. - - :param AnyByteStream transport_stream: any bytes-based stream - :param str encoding: character encoding to use for encoding/decoding strings to/from - bytes (defaults to ``utf-8``) - :param str errors: handling scheme for encoding errors (defaults to ``strict``; see - the `codecs module documentation`_ for a comprehensive list of options) - - .. _codecs module documentation: - https://docs.python.org/3/library/codecs.html#codec-objects - """ - - transport_stream: AnyByteStream - encoding: InitVar[str] = "utf-8" - errors: InitVar[str] = "strict" - _receive_stream: TextReceiveStream = field(init=False) - _send_stream: TextSendStream = field(init=False) - - def __post_init__(self, encoding: str, errors: str) -> None: - self._receive_stream = TextReceiveStream( - self.transport_stream, encoding=encoding, errors=errors - ) - self._send_stream = TextSendStream( - self.transport_stream, encoding=encoding, errors=errors - ) - - async def receive(self) -> str: - return await self._receive_stream.receive() - - async def send(self, item: str) -> None: - await self._send_stream.send(item) - - async def send_eof(self) -> None: - await self.transport_stream.send_eof() - - async def aclose(self) -> None: - await self._send_stream.aclose() - await self._receive_stream.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self._send_stream.extra_attributes, - **self._receive_stream.extra_attributes, - } diff --git a/venv/lib/python3.12/site-packages/anyio/streams/tls.py b/venv/lib/python3.12/site-packages/anyio/streams/tls.py deleted file mode 100644 index 70a41cc..0000000 --- a/venv/lib/python3.12/site-packages/anyio/streams/tls.py +++ /dev/null @@ -1,352 +0,0 @@ -from __future__ import annotations - -import logging -import re -import ssl -import sys -from collections.abc import Callable, Mapping -from dataclasses import dataclass -from functools import wraps -from typing import Any, TypeVar - -from .. import ( - BrokenResourceError, - EndOfStream, - aclose_forcefully, - get_cancelled_exc_class, - to_thread, -) -from .._core._typedattr import TypedAttributeSet, typed_attribute -from ..abc import AnyByteStream, ByteStream, Listener, TaskGroup - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") -_PCTRTT = tuple[tuple[str, str], ...] -_PCTRTTT = tuple[_PCTRTT, ...] - - -class TLSAttribute(TypedAttributeSet): - """Contains Transport Layer Security related attributes.""" - - #: the selected ALPN protocol - alpn_protocol: str | None = typed_attribute() - #: the channel binding for type ``tls-unique`` - channel_binding_tls_unique: bytes = typed_attribute() - #: the selected cipher - cipher: tuple[str, str, int] = typed_attribute() - #: the peer certificate in dictionary form (see :meth:`ssl.SSLSocket.getpeercert` - # for more information) - peer_certificate: None | (dict[str, str | _PCTRTTT | _PCTRTT]) = typed_attribute() - #: the peer certificate in binary form - peer_certificate_binary: bytes | None = typed_attribute() - #: ``True`` if this is the server side of the connection - server_side: bool = typed_attribute() - #: ciphers shared by the client during the TLS handshake (``None`` if this is the - #: client side) - shared_ciphers: list[tuple[str, str, int]] | None = typed_attribute() - #: the :class:`~ssl.SSLObject` used for encryption - ssl_object: ssl.SSLObject = typed_attribute() - #: ``True`` if this stream does (and expects) a closing TLS handshake when the - #: stream is being closed - standard_compatible: bool = typed_attribute() - #: the TLS protocol version (e.g. ``TLSv1.2``) - tls_version: str = typed_attribute() - - -@dataclass(eq=False) -class TLSStream(ByteStream): - """ - A stream wrapper that encrypts all sent data and decrypts received data. - - This class has no public initializer; use :meth:`wrap` instead. - All extra attributes from :class:`~TLSAttribute` are supported. - - :var AnyByteStream transport_stream: the wrapped stream - - """ - - transport_stream: AnyByteStream - standard_compatible: bool - _ssl_object: ssl.SSLObject - _read_bio: ssl.MemoryBIO - _write_bio: ssl.MemoryBIO - - @classmethod - async def wrap( - cls, - transport_stream: AnyByteStream, - *, - server_side: bool | None = None, - hostname: str | None = None, - ssl_context: ssl.SSLContext | None = None, - standard_compatible: bool = True, - ) -> TLSStream: - """ - Wrap an existing stream with Transport Layer Security. - - This performs a TLS handshake with the peer. - - :param transport_stream: a bytes-transporting stream to wrap - :param server_side: ``True`` if this is the server side of the connection, - ``False`` if this is the client side (if omitted, will be set to ``False`` - if ``hostname`` has been provided, ``False`` otherwise). Used only to create - a default context when an explicit context has not been provided. - :param hostname: host name of the peer (if host name checking is desired) - :param ssl_context: the SSLContext object to use (if not provided, a secure - default will be created) - :param standard_compatible: if ``False``, skip the closing handshake when - closing the connection, and don't raise an exception if the peer does the - same - :raises ~ssl.SSLError: if the TLS handshake fails - - """ - if server_side is None: - server_side = not hostname - - if not ssl_context: - purpose = ( - ssl.Purpose.CLIENT_AUTH if server_side else ssl.Purpose.SERVER_AUTH - ) - ssl_context = ssl.create_default_context(purpose) - - # Re-enable detection of unexpected EOFs if it was disabled by Python - if hasattr(ssl, "OP_IGNORE_UNEXPECTED_EOF"): - ssl_context.options &= ~ssl.OP_IGNORE_UNEXPECTED_EOF - - bio_in = ssl.MemoryBIO() - bio_out = ssl.MemoryBIO() - - # External SSLContext implementations may do blocking I/O in wrap_bio(), - # but the standard library implementation won't - if type(ssl_context) is ssl.SSLContext: - ssl_object = ssl_context.wrap_bio( - bio_in, bio_out, server_side=server_side, server_hostname=hostname - ) - else: - ssl_object = await to_thread.run_sync( - ssl_context.wrap_bio, - bio_in, - bio_out, - server_side, - hostname, - None, - ) - - wrapper = cls( - transport_stream=transport_stream, - standard_compatible=standard_compatible, - _ssl_object=ssl_object, - _read_bio=bio_in, - _write_bio=bio_out, - ) - await wrapper._call_sslobject_method(ssl_object.do_handshake) - return wrapper - - async def _call_sslobject_method( - self, func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT] - ) -> T_Retval: - while True: - try: - result = func(*args) - except ssl.SSLWantReadError: - try: - # Flush any pending writes first - if self._write_bio.pending: - await self.transport_stream.send(self._write_bio.read()) - - data = await self.transport_stream.receive() - except EndOfStream: - self._read_bio.write_eof() - except OSError as exc: - self._read_bio.write_eof() - self._write_bio.write_eof() - raise BrokenResourceError from exc - else: - self._read_bio.write(data) - except ssl.SSLWantWriteError: - await self.transport_stream.send(self._write_bio.read()) - except ssl.SSLSyscallError as exc: - self._read_bio.write_eof() - self._write_bio.write_eof() - raise BrokenResourceError from exc - except ssl.SSLError as exc: - self._read_bio.write_eof() - self._write_bio.write_eof() - if isinstance(exc, ssl.SSLEOFError) or ( - exc.strerror and "UNEXPECTED_EOF_WHILE_READING" in exc.strerror - ): - if self.standard_compatible: - raise BrokenResourceError from exc - else: - raise EndOfStream from None - - raise - else: - # Flush any pending writes first - if self._write_bio.pending: - await self.transport_stream.send(self._write_bio.read()) - - return result - - async def unwrap(self) -> tuple[AnyByteStream, bytes]: - """ - Does the TLS closing handshake. - - :return: a tuple of (wrapped byte stream, bytes left in the read buffer) - - """ - await self._call_sslobject_method(self._ssl_object.unwrap) - self._read_bio.write_eof() - self._write_bio.write_eof() - return self.transport_stream, self._read_bio.read() - - async def aclose(self) -> None: - if self.standard_compatible: - try: - await self.unwrap() - except BaseException: - await aclose_forcefully(self.transport_stream) - raise - - await self.transport_stream.aclose() - - async def receive(self, max_bytes: int = 65536) -> bytes: - data = await self._call_sslobject_method(self._ssl_object.read, max_bytes) - if not data: - raise EndOfStream - - return data - - async def send(self, item: bytes) -> None: - await self._call_sslobject_method(self._ssl_object.write, item) - - async def send_eof(self) -> None: - tls_version = self.extra(TLSAttribute.tls_version) - match = re.match(r"TLSv(\d+)(?:\.(\d+))?", tls_version) - if match: - major, minor = int(match.group(1)), int(match.group(2) or 0) - if (major, minor) < (1, 3): - raise NotImplementedError( - f"send_eof() requires at least TLSv1.3; current " - f"session uses {tls_version}" - ) - - raise NotImplementedError( - "send_eof() has not yet been implemented for TLS streams" - ) - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - **self.transport_stream.extra_attributes, - TLSAttribute.alpn_protocol: self._ssl_object.selected_alpn_protocol, - TLSAttribute.channel_binding_tls_unique: ( - self._ssl_object.get_channel_binding - ), - TLSAttribute.cipher: self._ssl_object.cipher, - TLSAttribute.peer_certificate: lambda: self._ssl_object.getpeercert(False), - TLSAttribute.peer_certificate_binary: lambda: self._ssl_object.getpeercert( - True - ), - TLSAttribute.server_side: lambda: self._ssl_object.server_side, - TLSAttribute.shared_ciphers: lambda: self._ssl_object.shared_ciphers() - if self._ssl_object.server_side - else None, - TLSAttribute.standard_compatible: lambda: self.standard_compatible, - TLSAttribute.ssl_object: lambda: self._ssl_object, - TLSAttribute.tls_version: self._ssl_object.version, - } - - -@dataclass(eq=False) -class TLSListener(Listener[TLSStream]): - """ - A convenience listener that wraps another listener and auto-negotiates a TLS session - on every accepted connection. - - If the TLS handshake times out or raises an exception, - :meth:`handle_handshake_error` is called to do whatever post-mortem processing is - deemed necessary. - - Supports only the :attr:`~TLSAttribute.standard_compatible` extra attribute. - - :param Listener listener: the listener to wrap - :param ssl_context: the SSL context object - :param standard_compatible: a flag passed through to :meth:`TLSStream.wrap` - :param handshake_timeout: time limit for the TLS handshake - (passed to :func:`~anyio.fail_after`) - """ - - listener: Listener[Any] - ssl_context: ssl.SSLContext - standard_compatible: bool = True - handshake_timeout: float = 30 - - @staticmethod - async def handle_handshake_error(exc: BaseException, stream: AnyByteStream) -> None: - """ - Handle an exception raised during the TLS handshake. - - This method does 3 things: - - #. Forcefully closes the original stream - #. Logs the exception (unless it was a cancellation exception) using the - ``anyio.streams.tls`` logger - #. Reraises the exception if it was a base exception or a cancellation exception - - :param exc: the exception - :param stream: the original stream - - """ - await aclose_forcefully(stream) - - # Log all except cancellation exceptions - if not isinstance(exc, get_cancelled_exc_class()): - # CPython (as of 3.11.5) returns incorrect `sys.exc_info()` here when using - # any asyncio implementation, so we explicitly pass the exception to log - # (https://github.com/python/cpython/issues/108668). Trio does not have this - # issue because it works around the CPython bug. - logging.getLogger(__name__).exception( - "Error during TLS handshake", exc_info=exc - ) - - # Only reraise base exceptions and cancellation exceptions - if not isinstance(exc, Exception) or isinstance(exc, get_cancelled_exc_class()): - raise - - async def serve( - self, - handler: Callable[[TLSStream], Any], - task_group: TaskGroup | None = None, - ) -> None: - @wraps(handler) - async def handler_wrapper(stream: AnyByteStream) -> None: - from .. import fail_after - - try: - with fail_after(self.handshake_timeout): - wrapped_stream = await TLSStream.wrap( - stream, - ssl_context=self.ssl_context, - standard_compatible=self.standard_compatible, - ) - except BaseException as exc: - await self.handle_handshake_error(exc, stream) - else: - await handler(wrapped_stream) - - await self.listener.serve(handler_wrapper, task_group) - - async def aclose(self) -> None: - await self.listener.aclose() - - @property - def extra_attributes(self) -> Mapping[Any, Callable[[], Any]]: - return { - TLSAttribute.standard_compatible: lambda: self.standard_compatible, - } diff --git a/venv/lib/python3.12/site-packages/anyio/to_interpreter.py b/venv/lib/python3.12/site-packages/anyio/to_interpreter.py deleted file mode 100644 index 8a2e993..0000000 --- a/venv/lib/python3.12/site-packages/anyio/to_interpreter.py +++ /dev/null @@ -1,218 +0,0 @@ -from __future__ import annotations - -import atexit -import os -import pickle -import sys -from collections import deque -from collections.abc import Callable -from textwrap import dedent -from typing import Any, Final, TypeVar - -from . import current_time, to_thread -from ._core._exceptions import BrokenWorkerIntepreter -from ._core._synchronization import CapacityLimiter -from .lowlevel import RunVar - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -UNBOUND: Final = 2 # I have no clue how this works, but it was used in the stdlib -FMT_UNPICKLED: Final = 0 -FMT_PICKLED: Final = 1 -DEFAULT_CPU_COUNT: Final = 8 # this is just an arbitrarily selected value -MAX_WORKER_IDLE_TIME = ( - 30 # seconds a subinterpreter can be idle before becoming eligible for pruning -) - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - -_idle_workers = RunVar[deque["Worker"]]("_available_workers") -_default_interpreter_limiter = RunVar[CapacityLimiter]("_default_interpreter_limiter") - - -class Worker: - _run_func = compile( - dedent(""" - import _interpqueues as queues - import _interpreters as interpreters - from pickle import loads, dumps, HIGHEST_PROTOCOL - - item = queues.get(queue_id)[0] - try: - func, args = loads(item) - retval = func(*args) - except BaseException as exc: - is_exception = True - retval = exc - else: - is_exception = False - - try: - queues.put(queue_id, (retval, is_exception), FMT_UNPICKLED, UNBOUND) - except interpreters.NotShareableError: - retval = dumps(retval, HIGHEST_PROTOCOL) - queues.put(queue_id, (retval, is_exception), FMT_PICKLED, UNBOUND) - """), - "", - "exec", - ) - - last_used: float = 0 - - _initialized: bool = False - _interpreter_id: int - _queue_id: int - - def initialize(self) -> None: - import _interpqueues as queues - import _interpreters as interpreters - - self._interpreter_id = interpreters.create() - self._queue_id = queues.create(2, FMT_UNPICKLED, UNBOUND) - self._initialized = True - interpreters.set___main___attrs( - self._interpreter_id, - { - "queue_id": self._queue_id, - "FMT_PICKLED": FMT_PICKLED, - "FMT_UNPICKLED": FMT_UNPICKLED, - "UNBOUND": UNBOUND, - }, - ) - - def destroy(self) -> None: - import _interpqueues as queues - import _interpreters as interpreters - - if self._initialized: - interpreters.destroy(self._interpreter_id) - queues.destroy(self._queue_id) - - def _call( - self, - func: Callable[..., T_Retval], - args: tuple[Any], - ) -> tuple[Any, bool]: - import _interpqueues as queues - import _interpreters as interpreters - - if not self._initialized: - self.initialize() - - payload = pickle.dumps((func, args), pickle.HIGHEST_PROTOCOL) - queues.put(self._queue_id, payload, FMT_PICKLED, UNBOUND) - - res: Any - is_exception: bool - if exc_info := interpreters.exec(self._interpreter_id, self._run_func): - raise BrokenWorkerIntepreter(exc_info) - - (res, is_exception), fmt = queues.get(self._queue_id)[:2] - if fmt == FMT_PICKLED: - res = pickle.loads(res) - - return res, is_exception - - async def call( - self, - func: Callable[..., T_Retval], - args: tuple[Any], - limiter: CapacityLimiter, - ) -> T_Retval: - result, is_exception = await to_thread.run_sync( - self._call, - func, - args, - limiter=limiter, - ) - if is_exception: - raise result - - return result - - -def _stop_workers(workers: deque[Worker]) -> None: - for worker in workers: - worker.destroy() - - workers.clear() - - -async def run_sync( - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - limiter: CapacityLimiter | None = None, -) -> T_Retval: - """ - Call the given function with the given arguments in a subinterpreter. - - If the ``cancellable`` option is enabled and the task waiting for its completion is - cancelled, the call will still run its course but its return value (or any raised - exception) will be ignored. - - .. warning:: This feature is **experimental**. The upstream interpreter API has not - yet been finalized or thoroughly tested, so don't rely on this for anything - mission critical. - - :param func: a callable - :param args: positional arguments for the callable - :param limiter: capacity limiter to use to limit the total amount of subinterpreters - running (if omitted, the default limiter is used) - :return: the result of the call - :raises BrokenWorkerIntepreter: if there's an internal error in a subinterpreter - - """ - if sys.version_info <= (3, 13): - raise RuntimeError("subinterpreters require at least Python 3.13") - - if limiter is None: - limiter = current_default_interpreter_limiter() - - try: - idle_workers = _idle_workers.get() - except LookupError: - idle_workers = deque() - _idle_workers.set(idle_workers) - atexit.register(_stop_workers, idle_workers) - - async with limiter: - try: - worker = idle_workers.pop() - except IndexError: - worker = Worker() - - try: - return await worker.call(func, args, limiter) - finally: - # Prune workers that have been idle for too long - now = current_time() - while idle_workers: - if now - idle_workers[0].last_used <= MAX_WORKER_IDLE_TIME: - break - - await to_thread.run_sync(idle_workers.popleft().destroy, limiter=limiter) - - worker.last_used = current_time() - idle_workers.append(worker) - - -def current_default_interpreter_limiter() -> CapacityLimiter: - """ - Return the capacity limiter that is used by default to limit the number of - concurrently running subinterpreters. - - Defaults to the number of CPU cores. - - :return: a capacity limiter object - - """ - try: - return _default_interpreter_limiter.get() - except LookupError: - limiter = CapacityLimiter(os.cpu_count() or DEFAULT_CPU_COUNT) - _default_interpreter_limiter.set(limiter) - return limiter diff --git a/venv/lib/python3.12/site-packages/anyio/to_process.py b/venv/lib/python3.12/site-packages/anyio/to_process.py deleted file mode 100644 index 495de2a..0000000 --- a/venv/lib/python3.12/site-packages/anyio/to_process.py +++ /dev/null @@ -1,258 +0,0 @@ -from __future__ import annotations - -import os -import pickle -import subprocess -import sys -from collections import deque -from collections.abc import Callable -from importlib.util import module_from_spec, spec_from_file_location -from typing import TypeVar, cast - -from ._core._eventloop import current_time, get_async_backend, get_cancelled_exc_class -from ._core._exceptions import BrokenWorkerProcess -from ._core._subprocesses import open_process -from ._core._synchronization import CapacityLimiter -from ._core._tasks import CancelScope, fail_after -from .abc import ByteReceiveStream, ByteSendStream, Process -from .lowlevel import RunVar, checkpoint_if_cancelled -from .streams.buffered import BufferedByteReceiveStream - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -WORKER_MAX_IDLE_TIME = 300 # 5 minutes - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - -_process_pool_workers: RunVar[set[Process]] = RunVar("_process_pool_workers") -_process_pool_idle_workers: RunVar[deque[tuple[Process, float]]] = RunVar( - "_process_pool_idle_workers" -) -_default_process_limiter: RunVar[CapacityLimiter] = RunVar("_default_process_limiter") - - -async def run_sync( # type: ignore[return] - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - cancellable: bool = False, - limiter: CapacityLimiter | None = None, -) -> T_Retval: - """ - Call the given function with the given arguments in a worker process. - - If the ``cancellable`` option is enabled and the task waiting for its completion is - cancelled, the worker process running it will be abruptly terminated using SIGKILL - (or ``terminateProcess()`` on Windows). - - :param func: a callable - :param args: positional arguments for the callable - :param cancellable: ``True`` to allow cancellation of the operation while it's - running - :param limiter: capacity limiter to use to limit the total amount of processes - running (if omitted, the default limiter is used) - :return: an awaitable that yields the return value of the function. - - """ - - async def send_raw_command(pickled_cmd: bytes) -> object: - try: - await stdin.send(pickled_cmd) - response = await buffered.receive_until(b"\n", 50) - status, length = response.split(b" ") - if status not in (b"RETURN", b"EXCEPTION"): - raise RuntimeError( - f"Worker process returned unexpected response: {response!r}" - ) - - pickled_response = await buffered.receive_exactly(int(length)) - except BaseException as exc: - workers.discard(process) - try: - process.kill() - with CancelScope(shield=True): - await process.aclose() - except ProcessLookupError: - pass - - if isinstance(exc, get_cancelled_exc_class()): - raise - else: - raise BrokenWorkerProcess from exc - - retval = pickle.loads(pickled_response) - if status == b"EXCEPTION": - assert isinstance(retval, BaseException) - raise retval - else: - return retval - - # First pickle the request before trying to reserve a worker process - await checkpoint_if_cancelled() - request = pickle.dumps(("run", func, args), protocol=pickle.HIGHEST_PROTOCOL) - - # If this is the first run in this event loop thread, set up the necessary variables - try: - workers = _process_pool_workers.get() - idle_workers = _process_pool_idle_workers.get() - except LookupError: - workers = set() - idle_workers = deque() - _process_pool_workers.set(workers) - _process_pool_idle_workers.set(idle_workers) - get_async_backend().setup_process_pool_exit_at_shutdown(workers) - - async with limiter or current_default_process_limiter(): - # Pop processes from the pool (starting from the most recently used) until we - # find one that hasn't exited yet - process: Process - while idle_workers: - process, idle_since = idle_workers.pop() - if process.returncode is None: - stdin = cast(ByteSendStream, process.stdin) - buffered = BufferedByteReceiveStream( - cast(ByteReceiveStream, process.stdout) - ) - - # Prune any other workers that have been idle for WORKER_MAX_IDLE_TIME - # seconds or longer - now = current_time() - killed_processes: list[Process] = [] - while idle_workers: - if now - idle_workers[0][1] < WORKER_MAX_IDLE_TIME: - break - - process_to_kill, idle_since = idle_workers.popleft() - process_to_kill.kill() - workers.remove(process_to_kill) - killed_processes.append(process_to_kill) - - with CancelScope(shield=True): - for killed_process in killed_processes: - await killed_process.aclose() - - break - - workers.remove(process) - else: - command = [sys.executable, "-u", "-m", __name__] - process = await open_process( - command, stdin=subprocess.PIPE, stdout=subprocess.PIPE - ) - try: - stdin = cast(ByteSendStream, process.stdin) - buffered = BufferedByteReceiveStream( - cast(ByteReceiveStream, process.stdout) - ) - with fail_after(20): - message = await buffered.receive(6) - - if message != b"READY\n": - raise BrokenWorkerProcess( - f"Worker process returned unexpected response: {message!r}" - ) - - main_module_path = getattr(sys.modules["__main__"], "__file__", None) - pickled = pickle.dumps( - ("init", sys.path, main_module_path), - protocol=pickle.HIGHEST_PROTOCOL, - ) - await send_raw_command(pickled) - except (BrokenWorkerProcess, get_cancelled_exc_class()): - raise - except BaseException as exc: - process.kill() - raise BrokenWorkerProcess( - "Error during worker process initialization" - ) from exc - - workers.add(process) - - with CancelScope(shield=not cancellable): - try: - return cast(T_Retval, await send_raw_command(request)) - finally: - if process in workers: - idle_workers.append((process, current_time())) - - -def current_default_process_limiter() -> CapacityLimiter: - """ - Return the capacity limiter that is used by default to limit the number of worker - processes. - - :return: a capacity limiter object - - """ - try: - return _default_process_limiter.get() - except LookupError: - limiter = CapacityLimiter(os.cpu_count() or 2) - _default_process_limiter.set(limiter) - return limiter - - -def process_worker() -> None: - # Redirect standard streams to os.devnull so that user code won't interfere with the - # parent-worker communication - stdin = sys.stdin - stdout = sys.stdout - sys.stdin = open(os.devnull) - sys.stdout = open(os.devnull, "w") - - stdout.buffer.write(b"READY\n") - while True: - retval = exception = None - try: - command, *args = pickle.load(stdin.buffer) - except EOFError: - return - except BaseException as exc: - exception = exc - else: - if command == "run": - func, args = args - try: - retval = func(*args) - except BaseException as exc: - exception = exc - elif command == "init": - main_module_path: str | None - sys.path, main_module_path = args - del sys.modules["__main__"] - if main_module_path and os.path.isfile(main_module_path): - # Load the parent's main module but as __mp_main__ instead of - # __main__ (like multiprocessing does) to avoid infinite recursion - try: - spec = spec_from_file_location("__mp_main__", main_module_path) - if spec and spec.loader: - main = module_from_spec(spec) - spec.loader.exec_module(main) - sys.modules["__main__"] = main - except BaseException as exc: - exception = exc - try: - if exception is not None: - status = b"EXCEPTION" - pickled = pickle.dumps(exception, pickle.HIGHEST_PROTOCOL) - else: - status = b"RETURN" - pickled = pickle.dumps(retval, pickle.HIGHEST_PROTOCOL) - except BaseException as exc: - exception = exc - status = b"EXCEPTION" - pickled = pickle.dumps(exc, pickle.HIGHEST_PROTOCOL) - - stdout.buffer.write(b"%s %d\n" % (status, len(pickled))) - stdout.buffer.write(pickled) - - # Respect SIGTERM - if isinstance(exception, SystemExit): - raise exception - - -if __name__ == "__main__": - process_worker() diff --git a/venv/lib/python3.12/site-packages/anyio/to_thread.py b/venv/lib/python3.12/site-packages/anyio/to_thread.py deleted file mode 100644 index 5070516..0000000 --- a/venv/lib/python3.12/site-packages/anyio/to_thread.py +++ /dev/null @@ -1,69 +0,0 @@ -from __future__ import annotations - -import sys -from collections.abc import Callable -from typing import TypeVar -from warnings import warn - -from ._core._eventloop import get_async_backend -from .abc import CapacityLimiter - -if sys.version_info >= (3, 11): - from typing import TypeVarTuple, Unpack -else: - from typing_extensions import TypeVarTuple, Unpack - -T_Retval = TypeVar("T_Retval") -PosArgsT = TypeVarTuple("PosArgsT") - - -async def run_sync( - func: Callable[[Unpack[PosArgsT]], T_Retval], - *args: Unpack[PosArgsT], - abandon_on_cancel: bool = False, - cancellable: bool | None = None, - limiter: CapacityLimiter | None = None, -) -> T_Retval: - """ - Call the given function with the given arguments in a worker thread. - - If the ``cancellable`` option is enabled and the task waiting for its completion is - cancelled, the thread will still run its course but its return value (or any raised - exception) will be ignored. - - :param func: a callable - :param args: positional arguments for the callable - :param abandon_on_cancel: ``True`` to abandon the thread (leaving it to run - unchecked on own) if the host task is cancelled, ``False`` to ignore - cancellations in the host task until the operation has completed in the worker - thread - :param cancellable: deprecated alias of ``abandon_on_cancel``; will override - ``abandon_on_cancel`` if both parameters are passed - :param limiter: capacity limiter to use to limit the total amount of threads running - (if omitted, the default limiter is used) - :return: an awaitable that yields the return value of the function. - - """ - if cancellable is not None: - abandon_on_cancel = cancellable - warn( - "The `cancellable=` keyword argument to `anyio.to_thread.run_sync` is " - "deprecated since AnyIO 4.1.0; use `abandon_on_cancel=` instead", - DeprecationWarning, - stacklevel=2, - ) - - return await get_async_backend().run_sync_in_worker_thread( - func, args, abandon_on_cancel=abandon_on_cancel, limiter=limiter - ) - - -def current_default_thread_limiter() -> CapacityLimiter: - """ - Return the capacity limiter that is used by default to limit the number of - concurrent threads. - - :return: a capacity limiter object - - """ - return get_async_backend().current_default_thread_limiter() diff --git a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/METADATA b/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/METADATA deleted file mode 100644 index 69be300..0000000 --- a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/METADATA +++ /dev/null @@ -1,123 +0,0 @@ -Metadata-Version: 2.4 -Name: beautifulsoup4 -Version: 4.13.3 -Summary: Screen-scraping library -Project-URL: Download, https://www.crummy.com/software/BeautifulSoup/bs4/download/ -Project-URL: Homepage, https://www.crummy.com/software/BeautifulSoup/bs4/ -Author-email: Leonard Richardson -License: MIT License -License-File: AUTHORS -License-File: LICENSE -Keywords: HTML,XML,parse,soup -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Text Processing :: Markup :: HTML -Classifier: Topic :: Text Processing :: Markup :: SGML -Classifier: Topic :: Text Processing :: Markup :: XML -Requires-Python: >=3.7.0 -Requires-Dist: soupsieve>1.2 -Requires-Dist: typing-extensions>=4.0.0 -Provides-Extra: cchardet -Requires-Dist: cchardet; extra == 'cchardet' -Provides-Extra: chardet -Requires-Dist: chardet; extra == 'chardet' -Provides-Extra: charset-normalizer -Requires-Dist: charset-normalizer; extra == 'charset-normalizer' -Provides-Extra: html5lib -Requires-Dist: html5lib; extra == 'html5lib' -Provides-Extra: lxml -Requires-Dist: lxml; extra == 'lxml' -Description-Content-Type: text/markdown - -Beautiful Soup is a library that makes it easy to scrape information -from web pages. It sits atop an HTML or XML parser, providing Pythonic -idioms for iterating, searching, and modifying the parse tree. - -# Quick start - -``` ->>> from bs4 import BeautifulSoup ->>> soup = BeautifulSoup("

SomebadHTML") ->>> print(soup.prettify()) - - -

- Some - - bad - - HTML - - -

- - ->>> soup.find(string="bad") -'bad' ->>> soup.i -HTML -# ->>> soup = BeautifulSoup("SomebadXML", "xml") -# ->>> print(soup.prettify()) - - - Some - - bad - - XML - - -``` - -To go beyond the basics, [comprehensive documentation is available](https://www.crummy.com/software/BeautifulSoup/bs4/doc/). - -# Links - -* [Homepage](https://www.crummy.com/software/BeautifulSoup/bs4/) -* [Documentation](https://www.crummy.com/software/BeautifulSoup/bs4/doc/) -* [Discussion group](https://groups.google.com/group/beautifulsoup/) -* [Development](https://code.launchpad.net/beautifulsoup/) -* [Bug tracker](https://bugs.launchpad.net/beautifulsoup/) -* [Complete changelog](https://git.launchpad.net/beautifulsoup/tree/CHANGELOG) - -# Note on Python 2 sunsetting - -Beautiful Soup's support for Python 2 was discontinued on December 31, -2020: one year after the sunset date for Python 2 itself. From this -point onward, new Beautiful Soup development will exclusively target -Python 3. The final release of Beautiful Soup 4 to support Python 2 -was 4.9.3. - -# Supporting the project - -If you use Beautiful Soup as part of your professional work, please consider a -[Tidelift subscription](https://tidelift.com/subscription/pkg/pypi-beautifulsoup4?utm_source=pypi-beautifulsoup4&utm_medium=referral&utm_campaign=readme). -This will support many of the free software projects your organization -depends on, not just Beautiful Soup. - -If you use Beautiful Soup for personal projects, the best way to say -thank you is to read -[Tool Safety](https://www.crummy.com/software/BeautifulSoup/zine/), a zine I -wrote about what Beautiful Soup has taught me about software -development. - -# Building the documentation - -The bs4/doc/ directory contains full documentation in Sphinx -format. Run `make html` in that directory to create HTML -documentation. - -# Running the unit tests - -Beautiful Soup supports unit test discovery using Pytest: - -``` -$ pytest -``` - diff --git a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/RECORD b/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/RECORD deleted file mode 100644 index a3efc0d..0000000 --- a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/RECORD +++ /dev/null @@ -1,89 +0,0 @@ -beautifulsoup4-4.13.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -beautifulsoup4-4.13.3.dist-info/METADATA,sha256=o692i819qmuScSS6UxoBFAi2xPSl8bk2V6TuQ3zBofs,3809 -beautifulsoup4-4.13.3.dist-info/RECORD,, -beautifulsoup4-4.13.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87 -beautifulsoup4-4.13.3.dist-info/licenses/AUTHORS,sha256=6-a5uw17L-xMAg7-R3iVPGKH_OwwacpjRkuOVPjAeyw,2198 -beautifulsoup4-4.13.3.dist-info/licenses/LICENSE,sha256=VbTY1LHlvIbRDvrJG3TIe8t3UmsPW57a-LnNKtxzl7I,1441 -bs4/__init__.py,sha256=-jvrE9GBtzsOF3wIrIOALQTqu99mf9_gEhNFJMCQLeg,44212 -bs4/__pycache__/__init__.cpython-312.pyc,, -bs4/__pycache__/_deprecation.cpython-312.pyc,, -bs4/__pycache__/_typing.cpython-312.pyc,, -bs4/__pycache__/_warnings.cpython-312.pyc,, -bs4/__pycache__/css.cpython-312.pyc,, -bs4/__pycache__/dammit.cpython-312.pyc,, -bs4/__pycache__/diagnose.cpython-312.pyc,, -bs4/__pycache__/element.cpython-312.pyc,, -bs4/__pycache__/exceptions.cpython-312.pyc,, -bs4/__pycache__/filter.cpython-312.pyc,, -bs4/__pycache__/formatter.cpython-312.pyc,, -bs4/_deprecation.py,sha256=ucZjfBAUF1B0f5ldNIIhlkHsYjHtvwELWlE3_pAR6Vs,2394 -bs4/_typing.py,sha256=3FgPPPrdsTa-kvn1R36o1k_2SfilcUWm4M9i7G4qFl8,7118 -bs4/_warnings.py,sha256=ZuOETgcnEbZgw2N0nnNXn6wvtrn2ut7AF0d98bvkMFc,4711 -bs4/builder/__init__.py,sha256=TYAKmGFuVfTsI53reHijcZKETnPuvse57KZ6LsZsJRo,31130 -bs4/builder/__pycache__/__init__.cpython-312.pyc,, -bs4/builder/__pycache__/_html5lib.cpython-312.pyc,, -bs4/builder/__pycache__/_htmlparser.cpython-312.pyc,, -bs4/builder/__pycache__/_lxml.cpython-312.pyc,, -bs4/builder/_html5lib.py,sha256=3MXq29SYg9XoS9gu2hgTDU02IQkv8kIBx3rW1QWY3fg,22846 -bs4/builder/_htmlparser.py,sha256=cu9PFkxkqVIIe9nU3fVy-JJhINEhY8cGbsuCwZCnQCA,17872 -bs4/builder/_lxml.py,sha256=XRzCA4WzvIUjJk9_U4kWzMBvGokr_UaIvoGUmtLtTYI,18538 -bs4/css.py,sha256=XGQq7HQUDyYEbDorFMGIGek7QGPiFuZYnvNEQ59GyxM,12685 -bs4/dammit.py,sha256=oHd1elJ44kMobBGSQRuG7Wln6M-BLz1unOuUscaL9h0,51472 -bs4/diagnose.py,sha256=zy7_GPQHsTtNf8s10WWIRcC5xH5_8LKs295Aa7iFUyI,7832 -bs4/element.py,sha256=8CXiRqz2DZJyga2igCVGaXdP7urNEDvDnsRid3SNNw4,109331 -bs4/exceptions.py,sha256=Q9FOadNe8QRvzDMaKSXe2Wtl8JK_oAZW7mbFZBVP_GE,951 -bs4/filter.py,sha256=2_ydSe978oLVmVyNLBi09Cc1VJEXYVjuO6K4ALq6XFk,28819 -bs4/formatter.py,sha256=5O4gBxTTi5TLU6TdqsgYI9Io0Gc_6-oCAWpfHI3Thn0,10464 -bs4/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -bs4/tests/__init__.py,sha256=Heh-lB8w8mzpaWcgs7MRwkBnDcf1YxAvqvePmsej1Pc,52268 -bs4/tests/__pycache__/__init__.cpython-312.pyc,, -bs4/tests/__pycache__/test_builder.cpython-312.pyc,, -bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc,, -bs4/tests/__pycache__/test_css.cpython-312.pyc,, -bs4/tests/__pycache__/test_dammit.cpython-312.pyc,, -bs4/tests/__pycache__/test_element.cpython-312.pyc,, -bs4/tests/__pycache__/test_filter.cpython-312.pyc,, -bs4/tests/__pycache__/test_formatter.cpython-312.pyc,, -bs4/tests/__pycache__/test_fuzz.cpython-312.pyc,, -bs4/tests/__pycache__/test_html5lib.cpython-312.pyc,, -bs4/tests/__pycache__/test_htmlparser.cpython-312.pyc,, -bs4/tests/__pycache__/test_lxml.cpython-312.pyc,, -bs4/tests/__pycache__/test_navigablestring.cpython-312.pyc,, -bs4/tests/__pycache__/test_pageelement.cpython-312.pyc,, -bs4/tests/__pycache__/test_soup.cpython-312.pyc,, -bs4/tests/__pycache__/test_tag.cpython-312.pyc,, -bs4/tests/__pycache__/test_tree.cpython-312.pyc,, -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4670634698080256.testcase,sha256=yUdXkbpNK7LVOQ0LBHMoqZ1rWaBfSXWytoO_xdSm7Ho,15 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4818336571064320.testcase,sha256=Uv_dx4a43TSfoNkjU-jHW2nSXkqHFg4XdAw7SWVObUk,23 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-4999465949331456.testcase,sha256=OEyVA0Ej4FxswOElrUNt0In4s4YhrmtaxE_NHGZvGtg,30 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase,sha256=G4vpNBOz-RwMpi6ewEgNEa13zX0sXhmL7VHOyIcdKVQ,15347 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase,sha256=3d8z65o4p7Rur-RmCHoOjzqaYQ8EAtjmiBYTHNyAdl4,19469 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase,sha256=NfGIlit1k40Ip3mlnBkYOkIDJX6gHtjlErwl7gsBjAQ,12 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase,sha256=xy4i1U0nhFHcnyc5pRKS6JRMvuoCNUur-Scor6UxIGw,4317 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase,sha256=Q-UTYpQBUsWoMgIUspUlzveSI-41s4ABC3jajRb-K0o,11502 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase,sha256=2bq3S8KxZgk8EajLReHD8m4_0Lj_nrkyJAxB_z_U0D0,5 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5843991618256896.testcase,sha256=MZDu31LPLfgu6jP9IZkrlwNes3f_sL8WFP5BChkUKdY,35 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5984173902397440.testcase,sha256=w58r-s6besG5JwPXpnz37W2YTj9-_qxFbk6hiEnKeIQ,51495 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6124268085182464.testcase,sha256=q8rkdMECEXKcqVhOf5zWHkSBTQeOPt0JiLg2TZiPCuk,10380 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6241471367348224.testcase,sha256=QfzoOxKwNuqG-4xIrea6MOQLXhfAAOQJ0r9u-J6kSNs,19 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6306874195312640.testcase,sha256=MJ2pHFuuCQUiQz1Kor2sof7LWeRERQ6QK43YNqQHg9o,47 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase,sha256=EItOpSdeD4ewK-qgJ9vtxennwn_huguzXgctrUT7fqE,3546 -bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6600557255327744.testcase,sha256=a2aJTG4FceGSJXsjtxoS8S4jk_8rZsS3aznLkeO2_dY,124 -bs4/tests/fuzz/crash-0d306a50c8ed8bcd0785b67000fcd5dea1d33f08.testcase,sha256=jRFRtCKlP3-3EDLc_iVRTcE6JNymv0rYcVM6qRaPrxI,2607 -bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase,sha256=7NsdCiXWAhNkmoW1pvF7rbZExyLAQIWtDtSHXIsH6YU,103 -bs4/tests/test_builder.py,sha256=BBMBirb4mb-fVdJj4dxQCxrdcjQeulKSKBFrPFVpVOk,1095 -bs4/tests/test_builder_registry.py,sha256=tpJ5Niva_cF49SdzIb1gMo0W4Tiodr8BYSOE3O6P_g8,5064 -bs4/tests/test_css.py,sha256=T_HCMzpe6hTr8d2YFXm0DScr8gT8d6h0MYlhZfo6A4U,18625 -bs4/tests/test_dammit.py,sha256=TQCVe6kKVYSuYjwTtIvIaOYYmWYPMnR_3PK45kimLg4,17840 -bs4/tests/test_element.py,sha256=u7FbTtKE6pYJetD1PgS3fCU1-QQXfB7GaLwfI3s4ROY,4373 -bs4/tests/test_filter.py,sha256=Sie2l-vepWTAqlXJJpG0Qp4HD8HHSi2TC1XymCxws70,27032 -bs4/tests/test_formatter.py,sha256=a6TaeNOVeg_ZYseiP7atmFyYJkQJqlk-jlVxMlyJC2o,6943 -bs4/tests/test_fuzz.py,sha256=zyaoWgCt8hnRkXecBYM9x91fI_Ao9eQUcsBi76ooJ08,7123 -bs4/tests/test_html5lib.py,sha256=ljMOAds__k9zhfT4jVnxxhZkLEggaT7wqDexzDNwus4,9206 -bs4/tests/test_htmlparser.py,sha256=iDHEI69GcisNP48BeHdLAWlqPGhrBwxftnUM8_3nsR4,6662 -bs4/tests/test_lxml.py,sha256=4fZIsNVbm2zdRQFNNwD-lqwf_QtUtiU4QbtLXISQZBw,7453 -bs4/tests/test_navigablestring.py,sha256=ntfnbp8-sRAOoCCVbm4cCXatS7kmCOaIRFDj-v5-l0s,5096 -bs4/tests/test_pageelement.py,sha256=lAw-sVP3zJX0VdHXXN1Ia3tci5dgK10Gac5o9G46IIk,16195 -bs4/tests/test_soup.py,sha256=I-mhNheo2-PTvfJToDI43EO4RmGlpKJsYOS19YoQ7-8,22669 -bs4/tests/test_tag.py,sha256=ue32hxQs_a1cMuzyu7MNjK42t0IOGMA6POPLIArMOts,9690 -bs4/tests/test_tree.py,sha256=vgUa6x8AJFEvHQ7RQu0973wrsLCRdRpdtq4oZAa_ANA,54839 diff --git a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/WHEEL b/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/WHEEL deleted file mode 100644 index 12228d4..0000000 --- a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/WHEEL +++ /dev/null @@ -1,4 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.27.0 -Root-Is-Purelib: true -Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/AUTHORS b/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/AUTHORS deleted file mode 100644 index 587a979..0000000 --- a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/AUTHORS +++ /dev/null @@ -1,49 +0,0 @@ -Behold, mortal, the origins of Beautiful Soup... -================================================ - -Leonard Richardson is the primary maintainer. - -Aaron DeVore, Isaac Muse and Chris Papademetrious have made -significant contributions to the code base. - -Mark Pilgrim provided the encoding detection code that forms the base -of UnicodeDammit. - -Thomas Kluyver and Ezio Melotti finished the work of getting Beautiful -Soup 4 working under Python 3. - -Simon Willison wrote soupselect, which was used to make Beautiful Soup -support CSS selectors. Isaac Muse wrote SoupSieve, which made it -possible to _remove_ the CSS selector code from Beautiful Soup. - -Sam Ruby helped with a lot of edge cases. - -Jonathan Ellis was awarded the prestigious Beau Potage D'Or for his -work in solving the nestable tags conundrum. - -An incomplete list of people have contributed patches to Beautiful -Soup: - - Istvan Albert, Andrew Lin, Anthony Baxter, Oliver Beattie, Andrew -Boyko, Tony Chang, Francisco Canas, "Delong", Zephyr Fang, Fuzzy, -Roman Gaufman, Yoni Gilad, Richie Hindle, Toshihiro Kamiya, Peteris -Krumins, Kent Johnson, Marek Kapolka, Andreas Kostyrka, Roel Kramer, -Ben Last, Robert Leftwich, Stefaan Lippens, "liquider", Staffan -Malmgren, Ksenia Marasanova, JP Moins, Adam Monsen, John Nagle, "Jon", -Ed Oskiewicz, Martijn Peters, Greg Phillips, Giles Radford, Stefano -Revera, Arthur Rudolph, Marko Samastur, James Salter, Jouni Seppänen, -Alexander Schmolck, Tim Shirley, Geoffrey Sneddon, Ville Skyttä, -"Vikas", Jens Svalgaard, Andy Theyers, Eric Weiser, Glyn Webster, John -Wiseman, Paul Wright, Danny Yoo - -An incomplete list of people who made suggestions or found bugs or -found ways to break Beautiful Soup: - - Hanno Böck, Matteo Bertini, Chris Curvey, Simon Cusack, Bruce Eckel, - Matt Ernst, Michael Foord, Tom Harris, Bill de hOra, Donald Howes, - Matt Patterson, Scott Roberts, Steve Strassmann, Mike Williams, - warchild at redho dot com, Sami Kuisma, Carlos Rocha, Bob Hutchison, - Joren Mc, Michal Migurski, John Kleven, Tim Heaney, Tripp Lilley, Ed - Summers, Dennis Sutch, Chris Smith, Aaron Swartz, Stuart - Turner, Greg Edwards, Kevin J Kalupson, Nikos Kouremenos, Artur de - Sousa Rocha, Yichun Wei, Per Vognsen diff --git a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/LICENSE b/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/LICENSE deleted file mode 100644 index 08e3a9c..0000000 --- a/venv/lib/python3.12/site-packages/beautifulsoup4-4.13.3.dist-info/licenses/LICENSE +++ /dev/null @@ -1,31 +0,0 @@ -Beautiful Soup is made available under the MIT license: - - Copyright (c) Leonard Richardson - - 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. - -Beautiful Soup incorporates code from the html5lib library, which is -also made available under the MIT license. Copyright (c) James Graham -and other contributors - -Beautiful Soup has an optional dependency on the soupsieve library, -which is also made available under the MIT license. Copyright (c) -Isaac Muse diff --git a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/INSTALLER b/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/INSTALLER deleted file mode 100644 index a1b589e..0000000 --- a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/METADATA b/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/METADATA deleted file mode 100644 index 0eaeb1d..0000000 --- a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/METADATA +++ /dev/null @@ -1,10 +0,0 @@ -Metadata-Version: 2.1 -Name: bs4 -Version: 0.0.2 -Summary: Dummy package for Beautiful Soup (beautifulsoup4) -Author-email: Leonard Richardson -License: MIT License -Requires-Dist: beautifulsoup4 -Description-Content-Type: text/x-rst - -This is a dummy package designed to prevent namesquatting on PyPI. You should install `beautifulsoup4 `_ instead. diff --git a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/RECORD b/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/RECORD deleted file mode 100644 index 3655e41..0000000 --- a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/RECORD +++ /dev/null @@ -1,6 +0,0 @@ -README.rst,sha256=KMs4D-t40JC-oge8vGS3O5gueksurGqAIFxPtHZAMXQ,159 -bs4-0.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -bs4-0.0.2.dist-info/METADATA,sha256=GEwOSFCOYLu11XQR3O2dMO7ZTpKFZpGoIUG0gkFVgA8,411 -bs4-0.0.2.dist-info/RECORD,, -bs4-0.0.2.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -bs4-0.0.2.dist-info/WHEEL,sha256=VYAwk8D_V6zmIA2XKK-k7Fem_KAtVk3hugaRru3yjGc,105 diff --git a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/REQUESTED b/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/REQUESTED deleted file mode 100644 index e69de29..0000000 diff --git a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/WHEEL b/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/WHEEL deleted file mode 100644 index a5543ba..0000000 --- a/venv/lib/python3.12/site-packages/bs4-0.0.2.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: hatchling 1.21.0 -Root-Is-Purelib: true -Tag: py2-none-any -Tag: py3-none-any diff --git a/venv/lib/python3.12/site-packages/bs4/__init__.py b/venv/lib/python3.12/site-packages/bs4/__init__.py deleted file mode 100644 index 68a992a..0000000 --- a/venv/lib/python3.12/site-packages/bs4/__init__.py +++ /dev/null @@ -1,1170 +0,0 @@ -"""Beautiful Soup Elixir and Tonic - "The Screen-Scraper's Friend". - -http://www.crummy.com/software/BeautifulSoup/ - -Beautiful Soup uses a pluggable XML or HTML parser to parse a -(possibly invalid) document into a tree representation. Beautiful Soup -provides methods and Pythonic idioms that make it easy to navigate, -search, and modify the parse tree. - -Beautiful Soup works with Python 3.7 and up. It works better if lxml -and/or html5lib is installed, but they are not required. - -For more than you ever wanted to know about Beautiful Soup, see the -documentation: http://www.crummy.com/software/BeautifulSoup/bs4/doc/ -""" - -__author__ = "Leonard Richardson (leonardr@segfault.org)" -__version__ = "4.13.3" -__copyright__ = "Copyright (c) 2004-2025 Leonard Richardson" -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -__all__ = [ - "AttributeResemblesVariableWarning", - "BeautifulSoup", - "Comment", - "Declaration", - "ProcessingInstruction", - "ResultSet", - "CSS", - "Script", - "Stylesheet", - "Tag", - "TemplateString", - "ElementFilter", - "UnicodeDammit", - "CData", - "Doctype", - - # Exceptions - "FeatureNotFound", - "ParserRejectedMarkup", - "StopParsing", - - # Warnings - "AttributeResemblesVariableWarning", - "GuessedAtParserWarning", - "MarkupResemblesLocatorWarning", - "UnusualUsageWarning", - "XMLParsedAsHTMLWarning", -] - -from collections import Counter -import sys -import warnings - -# The very first thing we do is give a useful error if someone is -# running this code under Python 2. -if sys.version_info.major < 3: - raise ImportError( - "You are trying to use a Python 3-specific version of Beautiful Soup under Python 2. This will not work. The final version of Beautiful Soup to support Python 2 was 4.9.3." - ) - -from .builder import ( - builder_registry, - TreeBuilder, -) -from .builder._htmlparser import HTMLParserTreeBuilder -from .dammit import UnicodeDammit -from .css import CSS -from ._deprecation import ( - _deprecated, -) -from .element import ( - CData, - Comment, - DEFAULT_OUTPUT_ENCODING, - Declaration, - Doctype, - NavigableString, - PageElement, - ProcessingInstruction, - PYTHON_SPECIFIC_ENCODINGS, - ResultSet, - Script, - Stylesheet, - Tag, - TemplateString, -) -from .formatter import Formatter -from .filter import ( - ElementFilter, - SoupStrainer, -) -from typing import ( - Any, - cast, - Counter as CounterType, - Dict, - Iterator, - List, - Sequence, - Optional, - Type, - Union, -) - -from bs4._typing import ( - _Encoding, - _Encodings, - _IncomingMarkup, - _InsertableElement, - _RawAttributeValue, - _RawAttributeValues, - _RawMarkup, -) - -# Import all warnings and exceptions into the main package. -from bs4.exceptions import ( - FeatureNotFound, - ParserRejectedMarkup, - StopParsing, -) -from bs4._warnings import ( - AttributeResemblesVariableWarning, - GuessedAtParserWarning, - MarkupResemblesLocatorWarning, - UnusualUsageWarning, - XMLParsedAsHTMLWarning, -) - - -class BeautifulSoup(Tag): - """A data structure representing a parsed HTML or XML document. - - Most of the methods you'll call on a BeautifulSoup object are inherited from - PageElement or Tag. - - Internally, this class defines the basic interface called by the - tree builders when converting an HTML/XML document into a data - structure. The interface abstracts away the differences between - parsers. To write a new tree builder, you'll need to understand - these methods as a whole. - - These methods will be called by the BeautifulSoup constructor: - * reset() - * feed(markup) - - The tree builder may call these methods from its feed() implementation: - * handle_starttag(name, attrs) # See note about return value - * handle_endtag(name) - * handle_data(data) # Appends to the current data node - * endData(containerClass) # Ends the current data node - - No matter how complicated the underlying parser is, you should be - able to build a tree using 'start tag' events, 'end tag' events, - 'data' events, and "done with data" events. - - If you encounter an empty-element tag (aka a self-closing tag, - like HTML's
tag), call handle_starttag and then - handle_endtag. - """ - - #: Since `BeautifulSoup` subclasses `Tag`, it's possible to treat it as - #: a `Tag` with a `Tag.name`. Hoever, this name makes it clear the - #: `BeautifulSoup` object isn't a real markup tag. - ROOT_TAG_NAME: str = "[document]" - - #: If the end-user gives no indication which tree builder they - #: want, look for one with these features. - DEFAULT_BUILDER_FEATURES: Sequence[str] = ["html", "fast"] - - #: A string containing all ASCII whitespace characters, used in - #: during parsing to detect data chunks that seem 'empty'. - ASCII_SPACES: str = "\x20\x0a\x09\x0c\x0d" - - # FUTURE PYTHON: - element_classes: Dict[Type[PageElement], Type[PageElement]] #: :meta private: - builder: TreeBuilder #: :meta private: - is_xml: bool - known_xml: Optional[bool] - parse_only: Optional[SoupStrainer] #: :meta private: - - # These members are only used while parsing markup. - markup: Optional[_RawMarkup] #: :meta private: - current_data: List[str] #: :meta private: - currentTag: Optional[Tag] #: :meta private: - tagStack: List[Tag] #: :meta private: - open_tag_counter: CounterType[str] #: :meta private: - preserve_whitespace_tag_stack: List[Tag] #: :meta private: - string_container_stack: List[Tag] #: :meta private: - _most_recent_element: Optional[PageElement] #: :meta private: - - #: Beautiful Soup's best guess as to the character encoding of the - #: original document. - original_encoding: Optional[_Encoding] - - #: The character encoding, if any, that was explicitly defined - #: in the original document. This may or may not match - #: `BeautifulSoup.original_encoding`. - declared_html_encoding: Optional[_Encoding] - - #: This is True if the markup that was parsed contains - #: U+FFFD REPLACEMENT_CHARACTER characters which were not present - #: in the original markup. These mark character sequences that - #: could not be represented in Unicode. - contains_replacement_characters: bool - - def __init__( - self, - markup: _IncomingMarkup = "", - features: Optional[Union[str, Sequence[str]]] = None, - builder: Optional[Union[TreeBuilder, Type[TreeBuilder]]] = None, - parse_only: Optional[SoupStrainer] = None, - from_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - element_classes: Optional[Dict[Type[PageElement], Type[PageElement]]] = None, - **kwargs: Any, - ): - """Constructor. - - :param markup: A string or a file-like object representing - markup to be parsed. - - :param features: Desirable features of the parser to be - used. This may be the name of a specific parser ("lxml", - "lxml-xml", "html.parser", or "html5lib") or it may be the - type of markup to be used ("html", "html5", "xml"). It's - recommended that you name a specific parser, so that - Beautiful Soup gives you the same results across platforms - and virtual environments. - - :param builder: A TreeBuilder subclass to instantiate (or - instance to use) instead of looking one up based on - `features`. You only need to use this if you've implemented a - custom TreeBuilder. - - :param parse_only: A SoupStrainer. Only parts of the document - matching the SoupStrainer will be considered. This is useful - when parsing part of a document that would otherwise be too - large to fit into memory. - - :param from_encoding: A string indicating the encoding of the - document to be parsed. Pass this in if Beautiful Soup is - guessing wrongly about the document's encoding. - - :param exclude_encodings: A list of strings indicating - encodings known to be wrong. Pass this in if you don't know - the document's encoding but you know Beautiful Soup's guess is - wrong. - - :param element_classes: A dictionary mapping BeautifulSoup - classes like Tag and NavigableString, to other classes you'd - like to be instantiated instead as the parse tree is - built. This is useful for subclassing Tag or NavigableString - to modify default behavior. - - :param kwargs: For backwards compatibility purposes, the - constructor accepts certain keyword arguments used in - Beautiful Soup 3. None of these arguments do anything in - Beautiful Soup 4; they will result in a warning and then be - ignored. - - Apart from this, any keyword arguments passed into the - BeautifulSoup constructor are propagated to the TreeBuilder - constructor. This makes it possible to configure a - TreeBuilder by passing in arguments, not just by saying which - one to use. - """ - if "convertEntities" in kwargs: - del kwargs["convertEntities"] - warnings.warn( - "BS4 does not respect the convertEntities argument to the " - "BeautifulSoup constructor. Entities are always converted " - "to Unicode characters." - ) - - if "markupMassage" in kwargs: - del kwargs["markupMassage"] - warnings.warn( - "BS4 does not respect the markupMassage argument to the " - "BeautifulSoup constructor. The tree builder is responsible " - "for any necessary markup massage." - ) - - if "smartQuotesTo" in kwargs: - del kwargs["smartQuotesTo"] - warnings.warn( - "BS4 does not respect the smartQuotesTo argument to the " - "BeautifulSoup constructor. Smart quotes are always converted " - "to Unicode characters." - ) - - if "selfClosingTags" in kwargs: - del kwargs["selfClosingTags"] - warnings.warn( - "Beautiful Soup 4 does not respect the selfClosingTags argument to the " - "BeautifulSoup constructor. The tree builder is responsible " - "for understanding self-closing tags." - ) - - if "isHTML" in kwargs: - del kwargs["isHTML"] - warnings.warn( - "Beautiful Soup 4 does not respect the isHTML argument to the " - "BeautifulSoup constructor. Suggest you use " - "features='lxml' for HTML and features='lxml-xml' for " - "XML." - ) - - def deprecated_argument(old_name: str, new_name: str) -> Optional[Any]: - if old_name in kwargs: - warnings.warn( - 'The "%s" argument to the BeautifulSoup constructor ' - 'was renamed to "%s" in Beautiful Soup 4.0.0' - % (old_name, new_name), - DeprecationWarning, - stacklevel=3, - ) - return kwargs.pop(old_name) - return None - - parse_only = parse_only or deprecated_argument("parseOnlyThese", "parse_only") - if parse_only is not None: - # Issue a warning if we can tell in advance that - # parse_only will exclude the entire tree. - if parse_only.excludes_everything: - warnings.warn( - f"The given value for parse_only will exclude everything: {parse_only}", - UserWarning, - stacklevel=3, - ) - - from_encoding = from_encoding or deprecated_argument( - "fromEncoding", "from_encoding" - ) - - if from_encoding and isinstance(markup, str): - warnings.warn( - "You provided Unicode markup but also provided a value for from_encoding. Your from_encoding will be ignored." - ) - from_encoding = None - - self.element_classes = element_classes or dict() - - # We need this information to track whether or not the builder - # was specified well enough that we can omit the 'you need to - # specify a parser' warning. - original_builder = builder - original_features = features - - builder_class: Type[TreeBuilder] - if isinstance(builder, type): - # A builder class was passed in; it needs to be instantiated. - builder_class = builder - builder = None - elif builder is None: - if isinstance(features, str): - features = [features] - if features is None or len(features) == 0: - features = self.DEFAULT_BUILDER_FEATURES - possible_builder_class = builder_registry.lookup(*features) - if possible_builder_class is None: - raise FeatureNotFound( - "Couldn't find a tree builder with the features you " - "requested: %s. Do you need to install a parser library?" - % ",".join(features) - ) - builder_class = possible_builder_class - - # At this point either we have a TreeBuilder instance in - # builder, or we have a builder_class that we can instantiate - # with the remaining **kwargs. - if builder is None: - builder = builder_class(**kwargs) - if ( - not original_builder - and not ( - original_features == builder.NAME - or ( - isinstance(original_features, str) - and original_features in builder.ALTERNATE_NAMES - ) - ) - and markup - ): - # The user did not tell us which TreeBuilder to use, - # and we had to guess. Issue a warning. - if builder.is_xml: - markup_type = "XML" - else: - markup_type = "HTML" - - # This code adapted from warnings.py so that we get the same line - # of code as our warnings.warn() call gets, even if the answer is wrong - # (as it may be in a multithreading situation). - caller = None - try: - caller = sys._getframe(1) - except ValueError: - pass - if caller: - globals = caller.f_globals - line_number = caller.f_lineno - else: - globals = sys.__dict__ - line_number = 1 - filename = globals.get("__file__") - if filename: - fnl = filename.lower() - if fnl.endswith((".pyc", ".pyo")): - filename = filename[:-1] - if filename: - # If there is no filename at all, the user is most likely in a REPL, - # and the warning is not necessary. - values = dict( - filename=filename, - line_number=line_number, - parser=builder.NAME, - markup_type=markup_type, - ) - warnings.warn( - GuessedAtParserWarning.MESSAGE % values, - GuessedAtParserWarning, - stacklevel=2, - ) - else: - if kwargs: - warnings.warn( - "Keyword arguments to the BeautifulSoup constructor will be ignored. These would normally be passed into the TreeBuilder constructor, but a TreeBuilder instance was passed in as `builder`." - ) - - self.builder = builder - self.is_xml = builder.is_xml - self.known_xml = self.is_xml - self._namespaces = dict() - self.parse_only = parse_only - - if hasattr(markup, "read"): # It's a file-type object. - markup = markup.read() - elif not isinstance(markup, (bytes, str)) and not hasattr(markup, "__len__"): - raise TypeError( - f"Incoming markup is of an invalid type: {markup!r}. Markup must be a string, a bytestring, or an open filehandle." - ) - elif len(markup) <= 256 and ( - (isinstance(markup, bytes) and b"<" not in markup and b"\n" not in markup) - or (isinstance(markup, str) and "<" not in markup and "\n" not in markup) - ): - # Issue warnings for a couple beginner problems - # involving passing non-markup to Beautiful Soup. - # Beautiful Soup will still parse the input as markup, - # since that is sometimes the intended behavior. - if not self._markup_is_url(markup): - self._markup_resembles_filename(markup) - - # At this point we know markup is a string or bytestring. If - # it was a file-type object, we've read from it. - markup = cast(_RawMarkup, markup) - - rejections = [] - success = False - for ( - self.markup, - self.original_encoding, - self.declared_html_encoding, - self.contains_replacement_characters, - ) in self.builder.prepare_markup( - markup, from_encoding, exclude_encodings=exclude_encodings - ): - self.reset() - self.builder.initialize_soup(self) - try: - self._feed() - success = True - break - except ParserRejectedMarkup as e: - rejections.append(e) - pass - - if not success: - other_exceptions = [str(e) for e in rejections] - raise ParserRejectedMarkup( - "The markup you provided was rejected by the parser. Trying a different parser or a different encoding may help.\n\nOriginal exception(s) from parser:\n " - + "\n ".join(other_exceptions) - ) - - # Clear out the markup and remove the builder's circular - # reference to this object. - self.markup = None - self.builder.soup = None - - def copy_self(self) -> "BeautifulSoup": - """Create a new BeautifulSoup object with the same TreeBuilder, - but not associated with any markup. - - This is the first step of the deepcopy process. - """ - clone = type(self)("", None, self.builder) - - # Keep track of the encoding of the original document, - # since we won't be parsing it again. - clone.original_encoding = self.original_encoding - return clone - - def __getstate__(self) -> Dict[str, Any]: - # Frequently a tree builder can't be pickled. - d = dict(self.__dict__) - if "builder" in d and d["builder"] is not None and not self.builder.picklable: - d["builder"] = type(self.builder) - # Store the contents as a Unicode string. - d["contents"] = [] - d["markup"] = self.decode() - - # If _most_recent_element is present, it's a Tag object left - # over from initial parse. It might not be picklable and we - # don't need it. - if "_most_recent_element" in d: - del d["_most_recent_element"] - return d - - def __setstate__(self, state: Dict[str, Any]) -> None: - # If necessary, restore the TreeBuilder by looking it up. - self.__dict__ = state - if isinstance(self.builder, type): - self.builder = self.builder() - elif not self.builder: - # We don't know which builder was used to build this - # parse tree, so use a default we know is always available. - self.builder = HTMLParserTreeBuilder() - self.builder.soup = self - self.reset() - self._feed() - - @classmethod - @_deprecated( - replaced_by="nothing (private method, will be removed)", version="4.13.0" - ) - def _decode_markup(cls, markup: _RawMarkup) -> str: - """Ensure `markup` is Unicode so it's safe to send into warnings.warn. - - warnings.warn had this problem back in 2010 but fortunately - not anymore. This has not been used for a long time; I just - noticed that fact while working on 4.13.0. - """ - if isinstance(markup, bytes): - decoded = markup.decode("utf-8", "replace") - else: - decoded = markup - return decoded - - @classmethod - def _markup_is_url(cls, markup: _RawMarkup) -> bool: - """Error-handling method to raise a warning if incoming markup looks - like a URL. - - :param markup: A string of markup. - :return: Whether or not the markup resembled a URL - closely enough to justify issuing a warning. - """ - problem: bool = False - if isinstance(markup, bytes): - problem = ( - any(markup.startswith(prefix) for prefix in (b"http:", b"https:")) - and b" " not in markup - ) - elif isinstance(markup, str): - problem = ( - any(markup.startswith(prefix) for prefix in ("http:", "https:")) - and " " not in markup - ) - else: - return False - - if not problem: - return False - warnings.warn( - MarkupResemblesLocatorWarning.URL_MESSAGE % dict(what="URL"), - MarkupResemblesLocatorWarning, - stacklevel=3, - ) - return True - - @classmethod - def _markup_resembles_filename(cls, markup: _RawMarkup) -> bool: - """Error-handling method to issue a warning if incoming markup - resembles a filename. - - :param markup: A string of markup. - :return: Whether or not the markup resembled a filename - closely enough to justify issuing a warning. - """ - markup_b: bytes - - # We're only checking ASCII characters, so rather than write - # the same tests twice, convert Unicode to a bytestring and - # operate on the bytestring. - if isinstance(markup, str): - markup_b = markup.encode("utf8") - else: - markup_b = markup - - # Step 1: does it end with a common textual file extension? - filelike = False - lower = markup_b.lower() - extensions = [b".html", b".htm", b".xml", b".xhtml", b".txt"] - if any(lower.endswith(ext) for ext in extensions): - filelike = True - if not filelike: - return False - - # Step 2: it _might_ be a file, but there are a few things - # we can look for that aren't very common in filenames. - - # Characters that have special meaning to Unix shells. (< was - # excluded before this method was called.) - # - # Many of these are also reserved characters that cannot - # appear in Windows filenames. - for byte in markup_b: - if byte in b"?*#&;>$|": - return False - - # Two consecutive forward slashes (as seen in a URL) or two - # consecutive spaces (as seen in fixed-width data). - # - # (Paths to Windows network shares contain consecutive - # backslashes, so checking that doesn't seem as helpful.) - if b"//" in markup_b: - return False - if b" " in markup_b: - return False - - # A colon in any position other than position 1 (e.g. after a - # Windows drive letter). - if markup_b.startswith(b":"): - return False - colon_i = markup_b.rfind(b":") - if colon_i not in (-1, 1): - return False - - # Step 3: If it survived all of those checks, it's similar - # enough to a file to justify issuing a warning. - warnings.warn( - MarkupResemblesLocatorWarning.FILENAME_MESSAGE % dict(what="filename"), - MarkupResemblesLocatorWarning, - stacklevel=3, - ) - return True - - def _feed(self) -> None: - """Internal method that parses previously set markup, creating a large - number of Tag and NavigableString objects. - """ - # Convert the document to Unicode. - self.builder.reset() - - if self.markup is not None: - self.builder.feed(self.markup) - # Close out any unfinished strings and close all the open tags. - self.endData() - while ( - self.currentTag is not None and self.currentTag.name != self.ROOT_TAG_NAME - ): - self.popTag() - - def reset(self) -> None: - """Reset this object to a state as though it had never parsed any - markup. - """ - Tag.__init__(self, self, self.builder, self.ROOT_TAG_NAME) - self.hidden = True - self.builder.reset() - self.current_data = [] - self.currentTag = None - self.tagStack = [] - self.open_tag_counter = Counter() - self.preserve_whitespace_tag_stack = [] - self.string_container_stack = [] - self._most_recent_element = None - self.pushTag(self) - - def new_tag( - self, - name: str, - namespace: Optional[str] = None, - nsprefix: Optional[str] = None, - attrs: Optional[_RawAttributeValues] = None, - sourceline: Optional[int] = None, - sourcepos: Optional[int] = None, - string: Optional[str] = None, - **kwattrs: _RawAttributeValue, - ) -> Tag: - """Create a new Tag associated with this BeautifulSoup object. - - :param name: The name of the new Tag. - :param namespace: The URI of the new Tag's XML namespace, if any. - :param prefix: The prefix for the new Tag's XML namespace, if any. - :param attrs: A dictionary of this Tag's attribute values; can - be used instead of ``kwattrs`` for attributes like 'class' - that are reserved words in Python. - :param sourceline: The line number where this tag was - (purportedly) found in its source document. - :param sourcepos: The character position within ``sourceline`` where this - tag was (purportedly) found. - :param string: String content for the new Tag, if any. - :param kwattrs: Keyword arguments for the new Tag's attribute values. - - """ - attr_container = self.builder.attribute_dict_class(**kwattrs) - if attrs is not None: - attr_container.update(attrs) - tag_class = self.element_classes.get(Tag, Tag) - - # Assume that this is either Tag or a subclass of Tag. If not, - # the user brought type-unsafety upon themselves. - tag_class = cast(Type[Tag], tag_class) - tag = tag_class( - None, - self.builder, - name, - namespace, - nsprefix, - attr_container, - sourceline=sourceline, - sourcepos=sourcepos, - ) - - if string is not None: - tag.string = string - return tag - - def string_container( - self, base_class: Optional[Type[NavigableString]] = None - ) -> Type[NavigableString]: - """Find the class that should be instantiated to hold a given kind of - string. - - This may be a built-in Beautiful Soup class or a custom class passed - in to the BeautifulSoup constructor. - """ - container = base_class or NavigableString - - # The user may want us to use some other class (hopefully a - # custom subclass) instead of the one we'd use normally. - container = cast( - Type[NavigableString], self.element_classes.get(container, container) - ) - - # On top of that, we may be inside a tag that needs a special - # container class. - if self.string_container_stack and container is NavigableString: - container = self.builder.string_containers.get( - self.string_container_stack[-1].name, container - ) - return container - - def new_string( - self, s: str, subclass: Optional[Type[NavigableString]] = None - ) -> NavigableString: - """Create a new `NavigableString` associated with this `BeautifulSoup` - object. - - :param s: The string content of the `NavigableString` - :param subclass: The subclass of `NavigableString`, if any, to - use. If a document is being processed, an appropriate - subclass for the current location in the document will - be determined automatically. - """ - container = self.string_container(subclass) - return container(s) - - def insert_before(self, *args: _InsertableElement) -> List[PageElement]: - """This method is part of the PageElement API, but `BeautifulSoup` doesn't implement - it because there is nothing before or after it in the parse tree. - """ - raise NotImplementedError( - "BeautifulSoup objects don't support insert_before()." - ) - - def insert_after(self, *args: _InsertableElement) -> List[PageElement]: - """This method is part of the PageElement API, but `BeautifulSoup` doesn't implement - it because there is nothing before or after it in the parse tree. - """ - raise NotImplementedError("BeautifulSoup objects don't support insert_after().") - - def popTag(self) -> Optional[Tag]: - """Internal method called by _popToTag when a tag is closed. - - :meta private: - """ - if not self.tagStack: - # Nothing to pop. This shouldn't happen. - return None - tag = self.tagStack.pop() - if tag.name in self.open_tag_counter: - self.open_tag_counter[tag.name] -= 1 - if ( - self.preserve_whitespace_tag_stack - and tag == self.preserve_whitespace_tag_stack[-1] - ): - self.preserve_whitespace_tag_stack.pop() - if self.string_container_stack and tag == self.string_container_stack[-1]: - self.string_container_stack.pop() - # print("Pop", tag.name) - if self.tagStack: - self.currentTag = self.tagStack[-1] - return self.currentTag - - def pushTag(self, tag: Tag) -> None: - """Internal method called by handle_starttag when a tag is opened. - - :meta private: - """ - # print("Push", tag.name) - if self.currentTag is not None: - self.currentTag.contents.append(tag) - self.tagStack.append(tag) - self.currentTag = self.tagStack[-1] - if tag.name != self.ROOT_TAG_NAME: - self.open_tag_counter[tag.name] += 1 - if tag.name in self.builder.preserve_whitespace_tags: - self.preserve_whitespace_tag_stack.append(tag) - if tag.name in self.builder.string_containers: - self.string_container_stack.append(tag) - - def endData(self, containerClass: Optional[Type[NavigableString]] = None) -> None: - """Method called by the TreeBuilder when the end of a data segment - occurs. - - :param containerClass: The class to use when incorporating the - data segment into the parse tree. - - :meta private: - """ - if self.current_data: - current_data = "".join(self.current_data) - # If whitespace is not preserved, and this string contains - # nothing but ASCII spaces, replace it with a single space - # or newline. - if not self.preserve_whitespace_tag_stack: - strippable = True - for i in current_data: - if i not in self.ASCII_SPACES: - strippable = False - break - if strippable: - if "\n" in current_data: - current_data = "\n" - else: - current_data = " " - - # Reset the data collector. - self.current_data = [] - - # Should we add this string to the tree at all? - if ( - self.parse_only - and len(self.tagStack) <= 1 - and (not self.parse_only.allow_string_creation(current_data)) - ): - return - - containerClass = self.string_container(containerClass) - o = containerClass(current_data) - self.object_was_parsed(o) - - def object_was_parsed( - self, - o: PageElement, - parent: Optional[Tag] = None, - most_recent_element: Optional[PageElement] = None, - ) -> None: - """Method called by the TreeBuilder to integrate an object into the - parse tree. - - :meta private: - """ - if parent is None: - parent = self.currentTag - assert parent is not None - previous_element: Optional[PageElement] - if most_recent_element is not None: - previous_element = most_recent_element - else: - previous_element = self._most_recent_element - - next_element = previous_sibling = next_sibling = None - if isinstance(o, Tag): - next_element = o.next_element - next_sibling = o.next_sibling - previous_sibling = o.previous_sibling - if previous_element is None: - previous_element = o.previous_element - - fix = parent.next_element is not None - - o.setup(parent, previous_element, next_element, previous_sibling, next_sibling) - - self._most_recent_element = o - parent.contents.append(o) - - # Check if we are inserting into an already parsed node. - if fix: - self._linkage_fixer(parent) - - def _linkage_fixer(self, el: Tag) -> None: - """Make sure linkage of this fragment is sound.""" - - first = el.contents[0] - child = el.contents[-1] - descendant: PageElement = child - - if child is first and el.parent is not None: - # Parent should be linked to first child - el.next_element = child - # We are no longer linked to whatever this element is - prev_el = child.previous_element - if prev_el is not None and prev_el is not el: - prev_el.next_element = None - # First child should be linked to the parent, and no previous siblings. - child.previous_element = el - child.previous_sibling = None - - # We have no sibling as we've been appended as the last. - child.next_sibling = None - - # This index is a tag, dig deeper for a "last descendant" - if isinstance(child, Tag) and child.contents: - # _last_decendant is typed as returning Optional[PageElement], - # but the value can't be None here, because el is a Tag - # which we know has contents. - descendant = cast(PageElement, child._last_descendant(False)) - - # As the final step, link last descendant. It should be linked - # to the parent's next sibling (if found), else walk up the chain - # and find a parent with a sibling. It should have no next sibling. - descendant.next_element = None - descendant.next_sibling = None - - target: Optional[Tag] = el - while True: - if target is None: - break - elif target.next_sibling is not None: - descendant.next_element = target.next_sibling - target.next_sibling.previous_element = child - break - target = target.parent - - def _popToTag( - self, name: str, nsprefix: Optional[str] = None, inclusivePop: bool = True - ) -> Optional[Tag]: - """Pops the tag stack up to and including the most recent - instance of the given tag. - - If there are no open tags with the given name, nothing will be - popped. - - :param name: Pop up to the most recent tag with this name. - :param nsprefix: The namespace prefix that goes with `name`. - :param inclusivePop: It this is false, pops the tag stack up - to but *not* including the most recent instqance of the - given tag. - - :meta private: - """ - # print("Popping to %s" % name) - if name == self.ROOT_TAG_NAME: - # The BeautifulSoup object itself can never be popped. - return None - - most_recently_popped = None - - stack_size = len(self.tagStack) - for i in range(stack_size - 1, 0, -1): - if not self.open_tag_counter.get(name): - break - t = self.tagStack[i] - if name == t.name and nsprefix == t.prefix: - if inclusivePop: - most_recently_popped = self.popTag() - break - most_recently_popped = self.popTag() - - return most_recently_popped - - def handle_starttag( - self, - name: str, - namespace: Optional[str], - nsprefix: Optional[str], - attrs: _RawAttributeValues, - sourceline: Optional[int] = None, - sourcepos: Optional[int] = None, - namespaces: Optional[Dict[str, str]] = None, - ) -> Optional[Tag]: - """Called by the tree builder when a new tag is encountered. - - :param name: Name of the tag. - :param nsprefix: Namespace prefix for the tag. - :param attrs: A dictionary of attribute values. Note that - attribute values are expected to be simple strings; processing - of multi-valued attributes such as "class" comes later. - :param sourceline: The line number where this tag was found in its - source document. - :param sourcepos: The character position within `sourceline` where this - tag was found. - :param namespaces: A dictionary of all namespace prefix mappings - currently in scope in the document. - - If this method returns None, the tag was rejected by an active - `ElementFilter`. You should proceed as if the tag had not occurred - in the document. For instance, if this was a self-closing tag, - don't call handle_endtag. - - :meta private: - """ - # print("Start tag %s: %s" % (name, attrs)) - self.endData() - - if ( - self.parse_only - and len(self.tagStack) <= 1 - and not self.parse_only.allow_tag_creation(nsprefix, name, attrs) - ): - return None - - tag_class = self.element_classes.get(Tag, Tag) - # Assume that this is either Tag or a subclass of Tag. If not, - # the user brought type-unsafety upon themselves. - tag_class = cast(Type[Tag], tag_class) - tag = tag_class( - self, - self.builder, - name, - namespace, - nsprefix, - attrs, - self.currentTag, - self._most_recent_element, - sourceline=sourceline, - sourcepos=sourcepos, - namespaces=namespaces, - ) - if tag is None: - return tag - if self._most_recent_element is not None: - self._most_recent_element.next_element = tag - self._most_recent_element = tag - self.pushTag(tag) - return tag - - def handle_endtag(self, name: str, nsprefix: Optional[str] = None) -> None: - """Called by the tree builder when an ending tag is encountered. - - :param name: Name of the tag. - :param nsprefix: Namespace prefix for the tag. - - :meta private: - """ - # print("End tag: " + name) - self.endData() - self._popToTag(name, nsprefix) - - def handle_data(self, data: str) -> None: - """Called by the tree builder when a chunk of textual data is - encountered. - - :meta private: - """ - self.current_data.append(data) - - def decode( - self, - indent_level: Optional[int] = None, - eventual_encoding: _Encoding = DEFAULT_OUTPUT_ENCODING, - formatter: Union[Formatter, str] = "minimal", - iterator: Optional[Iterator[PageElement]] = None, - **kwargs: Any, - ) -> str: - """Returns a string representation of the parse tree - as a full HTML or XML document. - - :param indent_level: Each line of the rendering will be - indented this many levels. (The ``formatter`` decides what a - 'level' means, in terms of spaces or other characters - output.) This is used internally in recursive calls while - pretty-printing. - :param eventual_encoding: The encoding of the final document. - If this is None, the document will be a Unicode string. - :param formatter: Either a `Formatter` object, or a string naming one of - the standard formatters. - :param iterator: The iterator to use when navigating over the - parse tree. This is only used by `Tag.decode_contents` and - you probably won't need to use it. - """ - if self.is_xml: - # Print the XML declaration - encoding_part = "" - declared_encoding: Optional[str] = eventual_encoding - if eventual_encoding in PYTHON_SPECIFIC_ENCODINGS: - # This is a special Python encoding; it can't actually - # go into an XML document because it means nothing - # outside of Python. - declared_encoding = None - if declared_encoding is not None: - encoding_part = ' encoding="%s"' % declared_encoding - prefix = '\n' % encoding_part - else: - prefix = "" - - # Prior to 4.13.0, the first argument to this method was a - # bool called pretty_print, which gave the method a different - # signature from its superclass implementation, Tag.decode. - # - # The signatures of the two methods now match, but just in - # case someone is still passing a boolean in as the first - # argument to this method (or a keyword argument with the old - # name), we can handle it and put out a DeprecationWarning. - warning: Optional[str] = None - if isinstance(indent_level, bool): - if indent_level is True: - indent_level = 0 - elif indent_level is False: - indent_level = None - warning = f"As of 4.13.0, the first argument to BeautifulSoup.decode has been changed from bool to int, to match Tag.decode. Pass in a value of {indent_level} instead." - else: - pretty_print = kwargs.pop("pretty_print", None) - assert not kwargs - if pretty_print is not None: - if pretty_print is True: - indent_level = 0 - elif pretty_print is False: - indent_level = None - warning = f"As of 4.13.0, the pretty_print argument to BeautifulSoup.decode has been removed, to match Tag.decode. Pass in a value of indent_level={indent_level} instead." - - if warning: - warnings.warn(warning, DeprecationWarning, stacklevel=2) - elif indent_level is False or pretty_print is False: - indent_level = None - return prefix + super(BeautifulSoup, self).decode( - indent_level, eventual_encoding, formatter, iterator - ) - - -# Aliases to make it easier to get started quickly, e.g. 'from bs4 import _soup' -_s = BeautifulSoup -_soup = BeautifulSoup - - -class BeautifulStoneSoup(BeautifulSoup): - """Deprecated interface to an XML parser.""" - - def __init__(self, *args: Any, **kwargs: Any): - kwargs["features"] = "xml" - warnings.warn( - "The BeautifulStoneSoup class was deprecated in version 4.0.0. Instead of using " - 'it, pass features="xml" into the BeautifulSoup constructor.', - DeprecationWarning, - stacklevel=2, - ) - super(BeautifulStoneSoup, self).__init__(*args, **kwargs) - - -# If this file is run as a script, act as an HTML pretty-printer. -if __name__ == "__main__": - import sys - - soup = BeautifulSoup(sys.stdin) - print((soup.prettify())) diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index ea695a8b6c580b990c1058b915e8c8d6cd6c3b2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 39625 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
=Qo6UoAyE5)?d}7d}Rc5Za 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 diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/_deprecation.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/_deprecation.cpython-312.pyc deleted file mode 100644 index 5f5931d36074763c95199adc6ca14ca27fad1d0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3741 zcmb7`O>7&-6@X{|_$TVua;(UXJWX0#geB6kjml6AH%@#=^P>cn0UJUBYQ-IrD=&B1 z*`*Y!N~!_|ECNNHLxUJd3i#jy1skXiIpnBgfLzw_McDXIphbZk3NVnHv^w>@S^he< zn=G*J&Cbrxn|a@RGhg-hCkQvk6?MD7=&I=zor*_Sb#9w>Ax$qj3ES~##bwkhGLW6=s!oOD zU{jQ>Fq`Tw)#gNZujOn1RPI_FTgQZ73jCNwRJ zE-_j#VJxux*ETKd+%t0(OXpLx#VP8V(5I{FRKj3+(?-MT;>%vOj62cVSY}M7;6E%( z_Z*(4=Zc1?!u~&7=!tD=Y zj%8$Ry#ytjt%jxO3TzzsFQ;Iq=A(he@4fdyTqoD1>+&ZA0Sq5Q^5j-IFKuQj|6Oh`x7`||uqJ;>47nzORB8%H^)FGcy=X(b8@bcmREc=eR?l@( zlkPOfgGEO72YL-$o4An6G1tWY(b0}bO|aZQgnKnUTnr9 zRECH(9ZUD6^fx%)mJ}o)4s%y6h#+fA4Pwo>a|0Di!ANTez~OQjl0mcpn+IE;QUevk zkE8oI^1*RME-sgDY;5emlPNkSmdO{m?oQ|QjAfOkA)u}@?{o%&Y$aovOPLT@h=WrZ z*YwzQ8LZI@%*`yhXENE=YB8IXtAVDY^Vev*o*7wDl|E-VIo)#4r^V+HwBr>J|Jfi9 zBP2e2qrcX_J1|whQh$Bh*(vTU_-~hdyW*Et{FPNd`Tm3C#O|T7e@E4L;$eae9s0<- zdFB4#F+X-}4@Mz@wxU}VHka#mdK->qXz`=qKp;}!lhE=s zcEJ?`k&Q@HI~&q=_U;P^-PzAy_#Ra^YC#`wo&njVYEP=dnFVqup@7K2t?>!K!SPEr zrMzq?fS9~417a#5hWqzJv@poT`DjDoWBEGVMxTB{*2tYEnlL|FB_062Q&u`<03NOp zn+jYc0QmMrLRtr?0DO+S6Y?N}tT~!cKOK7cahH>>KxidwWKBH1r@2gO@;U+Nr4V|4 z92#{e+aQ(|*Q;z+q}`O(W&R0h%Tp-C3EG=&gCt%tv(1xv?MxRponxPi~R%NCdla6%~Air4M8$=#E%_rg(TXLQaT&XPvPJgAnjwKuge;ap@_E$cLD^=-;n#XBcH_@1k~*- z-=S)ZljK2P9Sx^Q1kr5PaB|>lj5u-P29fY0A0`Aefm0NC`iOuR(`*qjg4mt?*twEp zR4jI$&p;y#9QSu18j2)I-^vL|-5Vp)@YiJUdsUI-Msi#lz6Co0st!8=>Wle3RE^oB zG`u@7+)z+IM?-xgE%e{C{!Mq2eKfzhd{29JPlG0ni2>>0&G`laRfjVU)b`njsDyF< E1NwQC!vFvP diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/_typing.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/_typing.cpython-312.pyc deleted file mode 100644 index 0a9012e818745285515ceab78e4f882ae102e957..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3543 zcmaJ@O>Eo96&^{{zyIW4$v+ZhDY2Evl4Co68)rARaLi6!ClcR*BGo0hRJY((J%YzYId_p$ zy@FTu2|m>?_|i{5u~Y35y3~jeQM-k1 zwMXbtdxc)LPv`?1mmA$i3ilQ%UhMwCW5@A>6OPc2JMaLG;s73q0S9B0jvE|BA%;D8 zQ1Q)D4YS*DGk%Eie#Q?7!%PY=DTs%e#R%hqjzyeFAxBCuDa<54j^l*0D$n>fhfmTl{&4&oO?);U{nqPq6c|&neHeaYvg2ZSI72l4%o6J1JaX63-+*#5U>dFva+! zy@oQ%PIsDdDaM8IG~;F%m!_O@M!3kNvs9{%Wyb#rBg%NJ2&rgBLB*oHh2tC9g~&1!%2WOY$oxU;x$@9xTN%llXZgN)DWo-+(mSg#oP*HW>9mkPRJ z^{hxL*2|KNm6q1(T#;TDHt9YO!2vc2uS%PEv4~Zy8CGx&>y@JM5F3`~k+dn(^qLQA z0w5gS0eFuv5?l%r+=@%^1d$R{+?Z25*sE~x^I{+Nvm*&8zPDZ>fP=ts8*at_mTO(o zP&EJ*85Gy>W~C^R#n)wmbsZ9FmhR1ub9~t;BVSto9?J&*YO5e`@v@}xk}Tu0!Q+Cl zg$ch}HMUCHn9i?P3Poe0poMsNo)esNYWLh(LC^9f!h;X57t{jm%Rhe(5#ZO)TNb>6 zHwqe7`1L9^WGfk41)@xpC1O;;fjACO-4{^595by| z`eBo2^qkpv7nHRlNrX!*nt5dwI$t4xeWmzIG zDrLxMO?u_bgW@766?#=et*LHxiLKkcO5kmMZM7dWkJpy0$g$Y$Co$OPB_xZLmTyzl zO?PZ{3D!g2%sR@atjRou5@z|9<8e!QmgRrx{LJe4C8?7xC?TYKdLzi?G@)B@>U^I- zACRFVoakRHGM)6$b-E!P9nzuAtl7X~;)!;)EE)3Ft%@eoE=u~SPeg>ac8a%pMY|K8 zW;?}sNvAzhDrl@L_kTe&cZ`0)w^D)lj@_HqY%^!cW6Q`1OFI~=?*!E{)H5EII?IK0 z(}cp}eXW&!1PZxa(v4&4O@FJSKRsdj4BnOp6-=tOR$s|nvLbeC5bAX`EB~2?C5E>gHe;W7o< zP{>sPi(4<1isUOQU!y=j>Et?vuPJ;(;Rb~{3iA{eDBPs5NZ}TR(;egIz^vVhz9!3{ zrCm?|J^V9ncw8>mXP$Gp|BV1Xhr$4;37-ZL7y0b=dwrh~K%*DAd;a4NyGHk-M_@Dx zEyLZ@phRO7#Z!CJHE)gVr#`&;=>B-|4?#0ES09<*?%atTpn2#uvG}gMcX9XodNi{g zdUy8#WuRR}hqi<7t{$Mlh7ZM(d$D@-ysbPB%EYLNx^^-LC<)r(#CH3;>H&(woKKtS znSIqvFVqt^O%&OI6>b7Qo~jIg{YQcwXtmNzIpwDnSD?{yJn*3Zsq{3v1kvu!QDINnQQgoS(BTE&qmVC z!nVuOhEn5)-0<#}IrdFGe#7K$fJF){AfBcLKjVZw4aHB7*F5ILoH;&MPtBXCZwC%* q9_lriFcY`xvD@3>cTWz`?Zd=aEnH7DJ!cMwrs=`{6-~1*+rAIhPy**s=Y8X zyQ1l*JfuLM3O_aZ3qk%s(f)*@Kwit&0(}dhRO(Bf`kgboq^K%(T899a%h|b{IrDwr zIcNWR;X>2H=byDthr<^l)jqD~b1ZTDGTNIbde~V+K1?z8+{Sp<|I^VLyp&YBE1fOqb`8pO!pt zdts1zGzzt^Q_MOW-+_n3owW$-!ZkcqU)fa11F1t8pu}n`l4d^}_0q{mwQXU=ATj8z zVamj&DiW=g)t1{y+pe^`;sHI&Y$ii2r)|83IeAy1iaMg7r9uzHB*}!yXb0%*CxH@4 zEM%NuM<$=RBd`!QDMg?M17%d4iUVy@Oe|E4yCja#))6`tk({vqPWH{cE8_sJ+>-}t zK2JF5Hk)*6ymCrs!M+ZhJvm%pJXsYInpRu%(~GmHuS^^51NPWJv!CcEmJytU?c<15 zDvSCiR83=LTX)557w>svQ> zb~bO_-2SLOZS;C%O0PF<_IgngWFg(3@Ack=yjXqj*6(+Yy-KZWE)@NI z+{``zHh+#T<7duT;_IZ`u1v2yj2Uf)6w9}vM{CNmLk$NmHTSOPISURo`%5Y2oUMvUJ6vASBj%| zKmgQeGQgInqI=Nabj6(kL0mgqK!}0#@pnG5!))>;p6DgbS7WC7;!U5h_|7}PG-PkuQ-P&;4fHbDI>SAn$a+6z_J8QXW7I<&p07>Dmt|) zga<*_McW{O{Q1anx3}V8Mi${y7gHRizd<3u# zBZR}o+-ZnvnbApR`5`d@+;U`40ZVd3oLm?+#NNje^DTy z*P86NfkBD^r4u?DB_Qup&znc&9rF!XH%;-c>kKdcwpR2ohDj?O7?rAFVkS49xoUi13lh0YRC{sWY3wgq%25eXKdeu_PHN4jGlgS01ZwMOPf}ahm4W~-YCLJkp6>dl9a;`-l zNbArV`QS5L47Vfml$>DAv)969-Rb3@-nn~odvoh%aSGe*cSEo|^q+R4SxI1C%64B~-w|B8x=?CYInL(~*NmvFoI7n+PM7FUGLqt{%Z}XXrV*duHOGvaSi2HlW-)9dk>}=)a04`aKuvuL8UG=siNPX(>YIOn;m_prGq$zd-XMoaE&( z&X>7W1nU_em;iW+bWOAn4F?iwBfvnp5zqsAx5eAEVos1hgCKWMGR$*O94_K9rguzp z2}HhZu^e%T*oShIt6<=D6K_x=8p7bqVM}CM?Ae)B9kd7+9iSQ2RpZ1UveAnMSWqMl z`*AYHj3D*Q9$GgyhbaSX;KT=&28$*qj@-eSQrJjtz}ODnIv}aEDA^ZNh*OElTKFgm z*EnW@fhur}oxKX!R}&bFjHq}I@Xq`_00yqS=lmQ36LUCqB5~@( zi+r!x&b(Cn!X#PrCwV$e=b}^gOhE4?Bn0RyPoU3+^jAXdv!{M4pTACgrpwMrKJzP! z|K>CG+io|wAVnfLe@p1zd~i)lfqr^nXA-CKQBGIZ3tr@unta}P-Mzzk!(7KOgm2IO z441=7sZ{#Aw{pDHC{;iF<*|pKPpdIavAnK|b_xBvgn_y6bUAG^Dg3a)>T{`c&U9#xcor3ded%7nW1Ur1b5 zUQ~3Ypy;X|veZhb5K<`}w!)Q2AtKTdD_V&aVwJ8!S0!GER}zIpC0R&TQiYWG9<|bi zG|I%R?n+OgM^%gzAHZ{$m8oP4S&=7h^;Y@{eIlK(`YQv4fy!WE5YI_tNKZY5mL#a& zsFf*XLdvs>-u=3w_ZT~`hGlCDyPDDcim~H>!grullyVvA^N+}{!CyUnRh7@G^0M;7 zL-Wd|@XN})n#*XTAw`+2I>s#59J5wsrJ8QAa*ea&XU{U*u#A#Z<2Gy9W_6ZLpRG0O z?5t^AG}u#fj#IbC$HvN93E6DBVH-R@YdUj{nY>vWvys)NoMT6)i)^IctefL(dfIEjyladc9=YtY%his@-6y zklLl!N)4(!M?ytwo;I|GW0o5hjfL0Xr0GCP867%@vK5G7ntl7tvjf}F-evi)e=nvGTJDhIn))DuO4z()i88w_65VJv$|%BIT4Kt4AC^@m@(X5 zp@7?~QHJa#Lv|uK)~Kg$@QPMNH?1bKOSQVJhH6g+M}Hdq`%luNoZ3oh)oRTVI%DH8 zd8(#2EaP0WZscOE@Ud#M6)9=9(~3_z2G?dR!%ab(TJh6$>Y`?~y3f6QW}G|Mvd{5tI~iOynFF=hB#3fh)yjOyCMFtN*u zp%herM@Ux-VZBGs=;7C+g@~TjBdS{E_$!`dtcjkeL(Mm zjQEz{2lY6J8&0i+6`On=j&)X|5q=)4vYKlK3ep zP)Y!|0E8f>u!^wFQPCBu3>axtbr?C}JhcW=8dVd(XV{LN7x|`2u3`&ar!@Z5wLeDU zva%RjiaEX!ycWW9%JK8->Q#5O`EzwKw5SxZ#K>z=#gm_}spLXa3(p^y#${YGN(AY_ zX|!Q-B~6akE!k}@!h2CwtADEIOhP}zs2KVL=YX9shOiaJWaYxG2+cI#fxLVOKQ=WA zBXjfFvAJ5s7%O8rv=5iGG0UnPcFfWR!+Ct{qEWp#1{EBuH=Vg!_3`|pkB!-;V;pv2 z#2%ZmkBni3%GaB%c(G_=NQ=dVGflQDPuIes z{+?AO)ZMchQwDY{M}8Pz=^t8-{3yPLLQ2UWN<75yCnn`05|@?sglsh#j!SbC#i6p| zT2#)*y>$D2KGjZpsYQQUuez-`iwRu#j|sb^)oBH%nKN}-ILjuefHXhSw{v3Mvynv@ zt-mclN%$_r1aEJIAhP9{D8x2;YsO9R?r4i=b|~2CcyKp)o-%L`J&KQ;Bt#rziIC zqPjGMa=zBJGj67Ruc?bFbW2@0I7RbdnG2*|x+#be@SnI-)nf^EJ{N5zO^_Qx^^zfm zkf%|DFz;5X*v^^@%MlG#?N&_EKF{*SxVFN@s=d%947O^YfeiaG{9sVyN_N+kZ@hcp zuSb49^69=K*Y+LxW#(HS?)&iJ)wt3(bb0uv!=LsZyw-bg`RSER?{Y#8XmFVP0c8+) zS^5@AMSTsvMF@kchhbiAvx;cn!-xlaZU<|VL9NTqdS9<-g-AQDg2_#%9^%ZP# z6FR(DoMv-@PllUPy)j{p=LQdePx;Bl(Wtv{)JW}hg&8&zP$n!o* zw@bk4eDzoim&2yA82N?zV__v)7Yy|bHx6SU>L!K;Fbj%Iew&ymZa58I6|?K+fb${T ztbnSxOvWn+rqQtwZ_L>?D#{zM&5C60Z36|lGs@;AqfK@&L0Hpuq8+4jgrr`@qz1ld z_TmeZcAh=mWV%t-Fx_nm0}-972^IFKmEl(jatKeZgjEJ!2x^?4!vOgT0wEx9z8B@K z4;wpMwzOG$oSmQ>wGfT~xnH6ScqG%1Uh$!hP6ih?cj)h8WpgEvH%)d|(>J#B!o0?* zq0br3`5K4o$7hB2dOM8{EXMb^%~CN*eV`$}YWkYs>8NMUaTKwpx+cG<0{nAcWJ4x3GOCn}R`>^JeakfOD~6*h+#_85Ma zl-0+SEL(Qoy!6JUPcwV3W%j-sdoS`g@%Q5&?E3Jf>m$#6WL(R<^bZ&D^GW=rjR--E zOCW?~ZnupPL9~G=x_}#mJL|4>xDn~VjgJX83{G4Jn9;UE3Iibq;0A>7Kt@_>a84@) z-0XFz;tzh=`7OmP0=%`?UuzLz?7y+B{yt+I)K`X;L0*0`K(Y9DY*jz6V zi;-usK}LswkxvHmQkjais&N;F*B0`-Y|qo%uc1>Kth=IY19Y~>|DI3cHUsEAY`KSu z@OTB{x$!xR-!I;%w`#&0GsXls0iEAUUzFI37D;a4}Mj0tll-psu>@AXirVr#k_} zU~DKzz8@Ui-L;kcUclUTP{d6+A~83QdV19KD|zBA5=G0bm=0EeGUz5Nn^oNp`&S#4 z8N6$Ia9G%!TAf+7+680^tdrXfocB~6?g?OSYl}Ugl-^*J=YR(?MnHV9jg{}m+ANVD z#-~qENzj1mcJ9H)TPWN#qz_kI6DgG@TcDKOaQLgXd2Y7sRox{ErtNrL(lGi@}!g^jC#7iH0AE*QWx8SQM zKr)0w-GQjAWYyqli$e}#ixX}Eav{2kZH>~L>x0jl*wXStZvjMk5Zu*m@iw5aD`^uH zZimJ2qhPWSqWBsO!W{=|mKBw^dN`6G5tw%)M1Z~dS?(UptIa}bf4TFsI{&8TR^ zSD@jOz>S3j#WO|j1VG9@fp^%o2k9I5ES+6R?{YowsW+y!^1Ow=y)t=P+}EN}^1Gv+ z-yH-vKc@K>DnU&1fyOceu-J}ds@fD9e8RLS3bhdkY2yTETXD>`gzZor+d6DUqs>fr zt4GqpJH|$My4ZZY5O8+qwI&>1-dYHo3C`pyUh*{`tx=dQaByR zz0INK$EZw(j`$K17mKZAu_(`2Bb_c5f6&k@_e)o?h-IT#mcy!0wKr;I1>Tn|3 zx6*fbHB9&KjEnmhi34jTDM3(<%!r6O$rIPy8S?i|M)2b{@ZAk5R z1>o)qpp+CqsU$UpazOxE(oLxzCCSz@lsXd>^@pw~++9(WlAp zCB~CFCntnb!Qr6kpm!+EZqRT@{UEK#?dB7>kusJWIPwR@2 zl4t03rdSkb`{n-i&OI_WU-~rG|d1;AbtXsM*hz+^@pf&m;RkkL>=J$irWx_Fh-^ zu7+Z2?4Kh8H?rl3nq2FHim1sg?NY{|Sep fvDGL(-L(5q@5iyou_5K-p`FJb3xE8mir@bOi+7Oe diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/dammit.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/dammit.cpython-312.pyc deleted file mode 100644 index e7bad4bacb83bcfec568419835d16d3b1b13662d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 46475 zcmeIb3w#_`bw57)l2+Q4cJ+Q(wpR~ZT3HW26Tf0xmSx8;If-PFC~@SqW+bmIX`R_s zY$*~L2p~h+$ONzqfhZv%3JJvF6^CblhC=B>YdL7MnASjOyKQOLb|~Od_I zlJ-in)FH{H4wGz_ExqPGONYfI0k`&A`)nOH#%;Z69cc(lLwtHix)x^dup=zJH={4J zBeT!Z;oxw4ud^?!Ba88j-t0bChpW%s;qJ@n$mz@N$nDGP$m`4R$nPuYDCjHfDC{fh zDC#TjDCYE;y(N969i@yrdgt|(b(HnZ@0icDt#?7k0@>EFP{~!YO7IYhM|Q5qHG^tv z>n-mnSIRpU%2~=HIU8vfQ<`q8?0U%BQ7yYWYLvyukwZD;+zu~Oc|@5drS>^o>DRGD zaVdrPTdd@Do4Evr$eFLDwI8}mq)mp3_s~7bw7}(p=S%`q?1%2XHvT!Y2ty50ms<0G zQ>t9}m|0n(EV^;M|Ja({IG=X!#p2%EB)RAzNiJ3zpF^LcU&m5q>7g!xCqw-`nDADR zs|2}9^;YUw&SCQqR%V2)7_?PNN=22V)|&L5P}xzbRCX-vU!cVl8ZlKJRZ10N99j%| z`rT5$^{8~ra<_EUG#ei?JzTBFc<1}xiC4K<@ePFh-2=Uzw!pv<&w)VyK+x0cKcM>5 z!L^>f{r;|itkik7`1<<%q0G$ogMK60(-r7{Kv6?MkI!>pFr)-Ss^aVOgaUdtPw1c; z80b0Z@%0aS`V?P(FtcCjQi4I0-Qd|C@}R7Pithn`@1W;^FQ~|#KtBqV6;HPs==1FM zsfRtc`Fnd*e_wUbvmceg?Sj7E%&iL2-sV$-it1T^FcdlxT-(@qWblZ;A)xj&9#I2_ zl&(-?H&PwpM2#Evch-6O14li5K7W4*e~O%WV9>L3Kn;0zckNUZu8tf~f=CtesLD~* zA5u_%1uY^EdIH^e2G3o)cXn?u~^qwOjf1uyj8%@8>7eZWr)Y7JeqPF&dBfU!0N|~cJv~-|9YVGm` zLnt?W7urJg_2Rx6oh{naMKcXFh?*btsj?F4?Bg0lO~GiIs)PpA{w|GM@QAPi(rCFN z1DujV97y2Z?hu9ZZ&(UZI{xWnLNyJV5~)W_!=^*&dYZ&_Skifu%p9&w@>+&AwyT34 zANm<8NY^8QV9zF>Wqud%ncuRi4OI;@0NG(Mp8 zKhTKLhRz#080cTouxxo_5UpK*#MgD$*P{d*4+K{>$~^cQjtoX!oq9`)Ftr@_*oMDg zJ-~74jr4-4^!ZPfPBuLsJYT*d;>x>_HShS=h$H8bTTa|Eo-^&3H@+k6sGhP`UqJ?G zsOr9ZgSG4L-Plm8Kjkg=R9Eb)X{g=kC8VMD-i;fg&SQPOoqB?yrR$NWPYL<%xo^Y1 zB~+oH5<<`|_`9c~df&zxil72Kjq9o_HtdULP`~Y@EK#RkOsA>@qc&f#%kM|WvQmnu z1^4Nqdg(vAhFtjw8uOH-NRa7LhZz#y)L~JqicPTznWjLN6K9?iX5p}O#m3S#O}5UV zZA{zcO4u${LBcr>(fgkBlidg}of8OB@5>$8 z*Ug!u_umeelBjd;4eyp`gB{w6o4=%)tA>qEAVF zX~cv-bI4%w`l}eRBp7;vaqC@m#2T{coib!F@M!NC8FKQYww4_nU`pBk9BG!{!G}s%B?Osd*t+ia6V0)Pu^B(@>`A;nwSvu!T#=(MyoiACiXCwp{aUC?Rm25~vPE zxR3qt&A@VpEr;^-(h}E1txeLy9~rhHeFnWk`g_at&s(JwZ_z$%L5sJewKGs2mo}0) zoEgj=wx=vHLvJ_KpiIs@RFJ5hjtysSksfh$nR}!z^FF-$5y!AYwo)BWnjg-vB6P%| zmonnK-hDn{k{!cNK<6i|dTQMB9e4^7(fk{>9-?CB{8IENFzb=5;Ve8UT6HA*I`_;@ zx=(=>&u5iLJfwU^yPkFkQ_~Sw>Jnum6()mkuOxTk=|c1L2YZ|22JeE$P0mPqXuh6z z*bq4wO~y!gxX3DDR7jnPUT+5F)^mj_b?i`;jwPcl?N&$LTFlbSn*W+>@$-UsJ>AVuG=72R8QjT@97K5 zK3_$H=gxylzsKi+LfQkJc6N!-d4onVeV9i0(GKESwespbN6|n~kkMRS2LpkiXs*6M zFobznUtgfVcd(vX*C>YCE2))|h=AB+xH&SHj%yn(i|A zcB*uZP^B7T5<7@D*5^kxjasCrHeSjNp0&<%U?Ai&?v;$8>D`Zr=?NRuLQe% zN6@`}eMe~CjE8CPaKFYdNsJlAQ%%ZuwNVO`5tI=^M$`b4=?DCnksrW>%nNFD?Ci1P) zpy_j#qbAJQs0^A~TLP+#d5F1TY1DK~o4TnUL|)BU-=p+XZ`v@lvE>?7uc7lu;0QWg zNaMDw|;4J{ia@2YVHioFRm+S#)5BPcql%PuYjas@6s%jlD zbqSGXRf(q4+xGV=D$Os|1^{m^()9+Tt^r{i>I?-si7P~11c}ljqS-<4+z{rCg1JUL zy@CE7gX}yo*xBt@gCU;Mvcen9<07cyok67!rYGcxW*7=_)XF!?fKdk%XmI|hjc*an z;*!ZYgy9}kp(LSQ{5|~vJb{QaD&a^}VlbMeDxEN~_(`bXPGz&mPOgX1Ur`U;JQGAW zlXO9mxN>)imRz?(4AuQty3cXkBe)fv_P7*ZD$Sce>WY+>jk?|_Df>jhX!eCAH+?BM zy=2{#z2=REm0#NX(mgNU^TmDB4b7LOTQXWrVQ1}>bKyiuJYRBG&bXF@T}vjL&%2gJ zifSiUOm3bkYCLJZSX4V^jb}>k{PB%pS8b$b*_dm>8g?&2SZ%}Tp7HHr=i)crk~?o~ z&4=DOk#o*f@lymlFOJFJkxxx`sRpx!Hl~i?5>zt^P0QC?lC#TREDO6g%(yp)-J4%Q z@b377CVHATH=Ct`;zwIXGa?0*mnD0~hS8Qt+4{44!)48*yI;@qMBF8(vQB1=E3dh$ zE|$!Dyy$e%nXDg`Z8f+(8>UM(j-|!Zq?}Sp`B~))@0eP!{x$b4@f;NQ zX1=tbVya^EOvUza#rElnozwGoU6#xlOGbA`7S>&sOj%3D9QsWTzviyJWI<5ef)sed zl7$m_&lEpVJn5Y-Ul}f5Ihu9Rp7Ti7iL9}%^Y+q6b^RI3OZFG-XG^A+HixU5r|eZ| zRZrDZtus}t!&R%NtJY30Tt~NSII(AR`&j5g@x1ZvpU58F9`V-GYdGgz9Je7Bx2m~$ z)N(}_|yPN8_?prc^@6jdRbwi75?peQK-|%9vE=sg+ zPO5d3Y@OE|E!o_3M@!PIbI%=}n=!%N+0s6gPDL!<=Z)qkCZ&n!sGY@J;J~3S3=!i; zER+7Or~r@%rbEWm)JOx{(Q{hp2-Mm`$@#TJhm7fIBG<6l$YmL}9LL0R*i7nunR0Bt#)57pfLR8n($Tk2C4}uhmZ^AmDsf`UR zCa&5S<2|lh6kK=Jx){)FiQ0N#dq2YLJZgcN7}m?}cp9|_AnFRJ{vJQfz=9nQM$?!< z4zm0qjwX0nQD>sAoovGs$%blEakA8D7ox3$n{iX{F}pOc^6`e#4U;+3rAxrja`I<# z>cctpGdat`Im^y8PUmbMO@py=bVDR>{)8)>*Er>DjJOKM(@wl=%DzCYKryr4H;FBN z-?suG4d4*2bARXslxEH^(F~v4Q8UUZP5she{&jq8=vP zl6YlmKLUdE9LC!zOny7ULJLVdIOKhcmy<~9rFT<}GWp%)7R=<-g>&jA?|R|BXYV`P zG+n19(m1Y0ZhJO;*67d7VO$)%q%H z8$*jzJ><3NmeLaz@)KTkm5kr|cL#u+oa;!Rja-@0wY#HjMv{wUNA%@jcT@rCET1* z8|##*$Ej#l*@W?iu7Wn2hc=>XfovJET&MGxhAq1Fe8kj`kqW+zTtlcOS``p0Jyzd) z!N_;}FopKPGytX6gN3vJ2oiH($ut--t5N-!Heo?iYuZ5%_ZgZT`a?-GI?ryJ1M4&M zqyFAr&jCd*YJjHOSOFZMbtEo6n4HzKIdA~Wew#4~t>56OFsO=ziNLcR3yNCtw2VrI z-{9;L>rf%ck!x>k2n>DJpP~kLD!owLF`Ex~D*9+~Rjr`9RHq29eyds?2tbx;1_sO_ z=hiY=gw2jKYOl>h>oD!coDy?H(XK|kcteTjdaL$Leu_lv(gP;NET&S|iD*2(AQR8J z7Ly1pR&!5Ti&?QS%o`m<>q2NhuAEV~wPIOQlL|{lGb4`d zu|+4=N1(VXCx+wDM{CBMk>dG}XPwTP=$c$VUA+3F4f1+H`B)|m@RqQvd}2q~)i7mm z5Tm@H4`Z!!?)|!mcj`YwIv+#G^`vtu*$g>OdFT8vo7Z$TtN@$U9HcT94-!cebADPU z24^t&9zeD`#0xO=C}Ic3#4;!pHkw@uM!`}W3o}W>nz{(4oWXh+h+q)J>{9Q)Jkl2T zhSt?_=k9?Q1Xgbn>5Q(Sjb@R)htku4Am<2UmPs|?AukeEm47D^YZcEGawFT6*$!bpVwE*B~p?T-IUKMPtoq(IB3y z+fPm@FpTQ_UX0P?n(E`2&2elcB=?N{JhJxh7yaQHojVAPp2u;*Ae!8B61|30X!>Ei zccW{bxqm8THnvy+fzEVvd0VSF!^pjEqT z!tRJ80mwf>f7kLcugJ&V=fpjWaONHN9}y$pTptw#Io0h~O_lZu%;dVQ+G zjz_77E-yh4Uq~uJuLyI9YsA|Bqv0evId^k~`trL77~Nbw4sv$au9)3#Q}LIfRd3nd zQ)L@Y8Uh|30`*~c{fv8A*uCsb<;?P3;pMx&uS~n!-(m=`3r}j@wH1%^-zmjdHoYrJ zHt8M!`iewq`IN8?%oR{D>&yP`ZkR!Z1Ks}pvM=OoV2>N6Mt8ia^HhVYP}%TX)A(7n zcYiWp7b1n&ZBGC;2b2pIPJN15Fjhvem;`e^IxS?KOp9=y8l=D~Krms?U>itNTl4nq zs8tYbb1>-jz!&Wxoc36TA_q-eV7BGz8l78F)c~9yXf&z{6lvdqV4xRDJG=zpoW~0} zM^%`T1?%;B_O@@WU#-a+qYzDU^+3(u)zrSd)zh}SY1b~#u9kLqPk359v@+vqYTn!4 zA{J6aLy%ri3qXltbY~24vx>!vuM1UKS0RQuw+Zz0*=>Ob3qt!g3OS+#u<~{-M+yox zQqzW!3lbT=WBzWx0uiYXu30Llp*fRIP8xoSzM{)0uCh@Kiks7O^c!H#NrrtfdIP|o z)n?+fQV}GTOScEPl7=stgN7<@JXR^qhiPEKfq`UG1q{J6u3N&cTV`BMVOLYc>6&p? zhn>}vIj~o{GvhFVW(rB9X?n;fNroQzDG>jiBM=&*bchV2bAH#+N$qozft;n23T^XN zRQC=|+x#O&wDH2kEQpuWJSzM;laS(Kg7?V(Nv1pjII9|~NwM;KAp~X_YF_M=oUAp`xk74jlXy~4r#a^Rjc!?Gn#9};D zcC7tFg(cry9*BbJ_hB8H8HtTjkV)Ke#b!@i%kJ&Xdv@(@jZKaBT|nKZP~hqFGI? zck3R2aLQv9D+tabR%D4?tM3Dt#i!kK`^!+}TQlla&k(2HhO)q^Z<4ayGtT*8=lmIG zdDvM#Q8`nwCS0-R?6PU+Eu$tZq*45muye_bvoY*!JY$(zx--0V=l5@)cJ3K9U39re z?f-vg=76_v{odTF3stAN?*e) z4AbIk%DG+vWC&p8ZT6`4{?AolZ0abD10EX>5XRmLsmDhC+;*TQAF6&EE5Jqs#fe!?tvMJQTPANh+P&+8GOn^qYN^53O({|Bz zJbz5%E5UJdHJeOl`!_7*@i>UQLAkeG6n@V^uf%g+QLEu9G&q_S(dHqnOMIiXzqduW!TTgF=i<%lFIngNz@7#PI8IDMK7Zc z)`dUgN1dL2SMJ3?ox5Qq1Ka7uKe8&^D70#-8LH#-8Lzok?XOCX+nNu`we<7F$gcF%FKgB1UXdNyP9LP;C0t zLa_DIADG2n=ewKHPYpL{JHcxbYm+?(l&~ML9@3w>Tc2Yf^Fe_RPe98iWw3+7z!s` z$T2t|vUvb{aS!~=c;O7&vcYhm z$fPxEQ;TH{9=$d}GL{QFzcxeiz;@7U#Ot*s*-E~z?1ZN4e>J3|?%#hHdj@5$4Exj`-uTDakr-MvCglTN*kh+l$mI|LL?i4B3f9ZS zE<#v2=wa*Ogop_?v6M41mxLTLEsXL50)-50I}R{bOJO3h5^>SgxfWSuiA$h zJexV@cxF@At>D@k_tqA>68EcsN~|0~x5BW)?eP5jwVAeO*@}kc4cK)_6{e#273)@u z#MWZ6V>Qq^L&H%_QjhlVHe=yYk1Ym`u-X%2YoKJ68c|Puzus5Rb*nc_2laX*U`O)o zCZ9e0*fMy7HuH6(QD#kxZ^*O``d|V&pwJo`H#x04(%@HQUV}8+P82Iv&Xm3**c*%a z2Qe&e9lh?8_$ zON=J+_hDU}{1VA@qj$WdtVtvHhIbSkQ)5m3AX^w`t?`0A>P!l+3W61HkmLwn=z)X* zhz2PPlW02is2^j*Pn+z8{Y$qUK@iLyUCObp-T^sDl3!PW2cY;;|D8X~b_hO~Pu; zc29PhlkQ^E>wtUPjC))4Q0xIk4y{I3>Cfe9<_ArQM0uUb+v=xRA2k%suPOiQH;{Wz$JOKvSHcMhNY0}=*`vF>pRuV`N-iS zMsFQnMVXLPU59(I1E+VZ*QIVjsCpV8YR66;63%e)CM=q}MdK4N4csZB)W;|_%|W6z z?9KtV`~=}{O%*X1jrws4&Jj8p`xgpTI9fnUQAeUUyRGSI4;&mKjN@z4oY; zls=B;I&!&uPf?RkA|G$u2-1txm!^apGAtsrMWeHGsHA1il%qk9D#JSpzKpELr8jdW zZ~at#%enfU-_M<{*)?iCZ(sDfWBvta{v*3j?2fnxF1RZq^U8jeZq3SuEg~yt#_2uh z^iI`p3_CZz=JZAu)SX+f{EV40&Wn`QpDSB&CU?qSa-qCxYR!%xE!ugeX~OqR&l5dQ z`_C=fIbF_oSP=14QHJ>uPxXZBd&2fwL_5aX zUn{8n?d2?K@h%g4=zqJSX!9+0^=WF2&k&d-Kzlu-HfBm}De9sQp#KPGHV^`W)iKj? zoR*Q=lTsf*b!vlKvYM5X2o zQqv=Y=&9+Q13{Ya4i#V9QANxq>ZdePVPwyiocU9Zd6B&0NZ!0t8%}PR&Z``?M;v)$ zp_!ukF#bF0DbkTQzA6mA9cRuX+fQsCJ9yr?Fp^gUw;f?&H#j>=B~Dw3zbjX9AF(Yi zAs3Qff6AAS9nj!|yeY!q*eFZ;k;|>_fEP49TsUmjw$shSZsC;6sPC>tc&d_8rcRWu zW~VMs+z)XEuh;7)N&i=MH{?R1yyHu7AA{p3!Vzll{#l{M?&w6Q-dd0yMk^qHio4yQ zrBbAx(^4r?7%fFR)#m(;mxhde`Kg~KNvbB~sB|brSvRP6iqv!Jog#&(w`~67-=?;) z(=s%5w_gEAN;Wp>JVoOfeg2+ml6t`raKZJSUX6?khUFE?jJx2%%FrD z1{OhEd{}FT+6s2Zi@tNXm%&O<60dL8@=a^SUBMo;HCa?M*}_4N>)HZsf*ZAZ%~x#$ zq3-(CSDn~_Zp`?-4i@7=s(ubHTgVKS?<7K^g_!rsFlGs(OhU4gs1{=QX~N0@boNG^ zB5G1*Gq((*{f0`fVQ)s&3z<4rm0&g8#T_F`ECAz~eJ)teUc@=TPL zS2UAb9nP&j=d8v`3zc0J&Z&BPWtWE?uCWRZ7f(WdaCO%ZqgDaT32c>Ck`p1v0= z0E@Fnx14uY;4V}Xk-Gj&)k}3R)^SZL!p@3`7Sv>gUXz+|Zp}Go4Qi68d(DNa6=$}* zwDZNC(^Z?O!19R0^W9krq# znF87(n?c+7&=QB72EjsMCLG5?`p4TZFET+1*|I$+QNmxRHD*PRic!Z368QZe_<|i0 zcH(EtZaScFz#o3E2VlebE}E(-d?@AZOKEbmpo!O9TG zYoh8VUL(0j``%w8H?U{q_mMi5KkJ>Ld3dZEe zn$J5t7xRk7i^n!hIm_S3a*ySI=s!SN|j5t3_$_Y zIhM}XMr?`0r@;3NrBaVa4Gh&P5lfbWk+lA-q&O#n_$T6U@Dd+r1T#jO%qP!{*uniW zQX4hE39Zkk>-Xg2l?t%CB@c%Nr7(dYwQY9lcjpaf9?H>ckhto~zHH}OWejJi%afir zBk@G~y>YNqMyg|-=rlY%4W1(7kfA#N>%v^At8HiiW^T02VcC9<(-%TTaUlYVwU0dM3r3(eZE zmo~c?%`;3e1Y+PuIpD0xt4MX8gMlLoj!uPHv>!d3ZerB>?cD78i!=$X?~k>X@=`{U zmDH#hDYe(Lm{J`5w40_LwpdN_lNy{fNvBo{4jjQ^Zjw=+3W6SMw4UBX*MARnaNoqP z%cMh^xD32Hb~5Bzv;UxRiY(ng)Dmx|8;7qR_V)%@M9wXRJ>fkboOO!VL<)O=cNWnV z7IQp~Q2&J!ZKBlVS4x!;EX?TBN$*J)qwT1!@yvR6#OhWzyQt#M-GPDrB=>H=1UBd= z{@3&I)AW0GqgsQ3rB(yb$u!uSFQa97pTD}8Vg>=A^>4x@YU%SGi(0T)$zm^RWB@ zVK_!r*i02I(jVEFUcej(H=>{eB~rs_Kj9bjA_B?fYL3uNJx?Ll6Z{!+9G5OFmz)(B zs%s~2`t*ZS&gG*!PS3koGJkZ(h0^)s@>9*vTPC+Y=QtyWYt~Lzt(z`gKf3b`2!0a=qW{c0UfDU(KfU<2DQ9KGQ8DFch%&#+&))fpf4b_nDR+4!uWBZ* zHk?;GomV&Itb^2KaS1E(*49?c_O@>I7OD^9!PP$@@TUYGA@B_XWSdZFXS@0l0-q%? zMu51pN}@xh$zaq@r%K>x$w8G~h5AJTCkc?jg4G|DCgMV2q8Fonlt2Xm4}nuU_yr_$ zkoMWUPr77YX|u;wleBh2q@p^q{H93bipYwaFS$x=x0x=w3*t6HFn_9CGPyQfaZ@~< zY0T3~$E!{*h-WaFDV0@WQ|Y|MxPxh@R8l@s8ZNGjXEB{E&0jRp5iVPLh0BFg>O$|d zwI-6kVA{F>8p^b_JW{w|d@x*yU@u(1-n% zz~c${+2&U=UT$Ud`=Kio0v#+ZJ8oWPD;{4xu{}HwQ&r$s;B6*C-R{F9~mIn_ANrUeSJ;LMaE_mw?50a1I<2vmjDkcPXRMmXGEcQ^woI4u#$2 zaT@~AOu2>ebi(XX`Jy-_f>}BHEh;X`v#hMrP*N@c-^$*DMm-;tKm%{g5tLp$1DaUY`YIOiwB zV+n`Y=EEB*S1y1@SJ7kUjyxqF-cnBOP~c3tn99PFmpp0eD1e7nrd&!P8Pb?Z{ttPc z;*`r22TIcFh1S7=vK@t5`~tMpLL-d>UQiyy7AeJ?gP#n(SLI0_RV8u-(kIHZ%9W^J z={2EM2%YDbr*Vd@d|ZAv zLf<357w{qZeSq(mKL9u?p8)(I*ZD*8!@&PU{!_q5wpY56I@r}>#aBU5WWBToW8%lG)K{2cJ- z<<9|rUVZ`ajQk?t7xhQDF>TY^uU4qyvoK}_W@9W3SUO{NU>S^M0&_6t z1eV2EHZT`sZeTf#e?gh4wvHO5^GPWO>kFf*5x{TV& zpcD@82G+yaL12Ey4govNSTC?X#`=K;7&`*&e#TT_;9!6u{0%Vn05EVez+?CuWNZl7 zgNzLW8)597z~05!abWLe>^;EV%h*G}-e=VI{h&U;;iJG#F!n)UA7bobV1L5cp8|V? zu`ysL8T&A>M;ZGFu#YnKF<_?{8wYlpv5y1$1Y?f@`y^wZ0`@p#6TqHe>`7psX6z|o zPc!xzV9yw}odoqPhkq8>bBsL?>~oBL9@qYRmQ#s?CXqu1K2ki`xdZQ82dJ`?=bdVVBnO1uj21}jQu&V?;Caf0jR&=@E-#E zOUC{R*k3dDH^8PC3j;gH*fg;7jJ*czM~uw?i!k;&uqb0c26ln5p8)$?#{Lf2MaF&# z>}QPq9M~I-{Q?+xCg4Bd?;jb90sAMaEw2BJzkk8sFY))Uk6FOu7J|olpj&BDAL0Kd zv?yS4=uzbgX>A_**KHx4P3Uciy+rAha$uJ!Ouu$iAZ;e7D@OdATKuo*ijUif_fhn-*NPSJH;NPRx2#!NyY0ZQCV8VT8Z_7ZC#EIQEN#t9e5}S-i8*zXc1|-n zl#|~bHdyi&Z`@F~V3WT=vRNHVa&#OMJ2&>T*@P`ZD1e=lHRC1wP0~c4zx6_*v{R>qp&xhhYhR_&Dv6a!KTa}%u|nT8yjD0*h~>?-!p~JpEW*eQ2{-;+*hioQoj* zbQ2EW*gycsUd`V^_!MjGS~rawzTxoefSp*A6v9@#e?Nbzh);$>*}B^XSTCQt#U~Ev z2yNn6pF zQ=GQyp-F~o-LVrJI6Tw_e5#qg(S}OYZ(yvV%yr40oh4a#&c5|Ep3pb;%|_d6e&NPD zXP-k@*jeW4`>RN%l2yO|FuUjA3v}%7!$-DYK|W}>ZEsC@rAA$I`X5%0+2n3mr zc0tiFeuP`_cV)uN?wI6vY((~uA2C!F@xu|AQYTW0AHJ|6by80Lg$&QD#6sh9T27=( zGtwE0gyd3zGU(ej>Cb8LNNLn9l&9yxVrRaN>kE598=M`??B=i#B_(-BCwYq*P9KOj z7CqUQnyk_M8zf&qGA+;f9U@cpoL}-?WNE~Hot$NJvVnwuSUr|uGp>^(#l85bmxb4s zG;Dmc2KTogH$7Z$lKM^XXtW3Kx=!h->$8#TgWa6kH+rN)Deop*^%mFeHy?K~+A>kU zL*)rv$7Gw{1MtO|G_;=4cl0_Rcg=nqOc|x)-Jp#VZ*EZXrnhbt7G+~$X{e1iizS#L zm>s$HYC9vu@{!m!1b1Hu2Te`Y4!ypk<+fc-%`Lm}&8o!LD;nCpIqF~FF`_PZ-!&GA zg3*PVx*f!t5+AKcXLTe#2@n+HjXE(eh2Vn*fgWCxh}wldk1uu53lZxV?0ud+pnaJ@ zXtvQD{Y((!w!8`w&7yO}uumw|NuQgHrfW{~-b~@*%d29isc5Qss&OAR4G51C*xV(3 zg-de<<^`Fd!dWvC!&yBY!#sEwMl&2q@+D6rxrmoV7M6=^BfE^l1!DnukYC6vd+e_1 zyv4xn7m8~l&fJKzD&owGIOj*4IO%=Cm8|rVOvGm46nkeOR=c{+J1Qo+&sd)9i-S_LdBwq?oTfv7qo@&d1K!;l!MiVqIswKPWH_d)`kn&AN``!J!*;+m(ekxGsTVJ z;zsN&&nSf7NI}V|eJA(L6nMi0-qEdanA1-0Up?)vBVRuEiILZ_?vsJkmzgFNqhRDC{A3W{s{fo~B~)=$6-< z3olkw@>TTdDSB^zMIcPzFA4lLK-9)-lfsqW7(<94hZN@BKf=2qSNcEh_;`(vE(1SK zd5|fb>=&kv8Rj|nq2ygYs1p5jcMcqqY-z)>$NClJ7#v=tB#1kFAa#tm1Dt1QHIRS9 z#uv0g2B#R1)E4AVZW}E%_*)H{ah_})w#p`&z2B&|bU3qYBPi+%u4NT#P5+f#iLbAP z49S98Yqc9eO>R`0-csV~wGaKS8RtUb+nOGqXLnojd^({l(qta9VbWPJOHS5y*aIMh zL$?r)6ym5UgIOkdlC2Y94ugSL zAe{;)RKVSB{2{iuOT36B~Hx8v_!Lv zV_4|8k|6oVGY920XPkC|=+3?%3xc82Ib1X;u9rBeLvT{JR8)5A@X5my<&XA{S}&5X z?ZU8Q;l$179JS<{qd;lkxJg=@lvYo-g=jak4}+LMAoE?W#qA}3vl4e0(X9X5k6KBDVjG^v?N@#WOCqK z(aOkzs)>;^w}-25o~hmtuHG{(3$~40=)){@qZ~TY37paB0JI>C&-g@J24k z!ZpTu&ZFW0y`hXgUspZkny-H-BY4o?9jZU%57H-m5l$zg2M-RV9jgx_FzTXje6+Q+ zcQ)*Nny;b_G>+BALKY|vl6{$=CEH999BxjVH56tG-luJ#@;vt*m zRm%M*?0lTirBJe=PosX?4}2vhZ+&+Y>Bp&daiA_Ma5%j!v9mGdUJ*l!!#DTRQn~J- z^b~s|k~v-mY1t{<@Sy+W+4TLI{JqO0O`i37gU6$U6nb(Swhx6$^)|pq$Sw3i@j;XE z*>H;whqFjc_&%7nKV0WyH2KnOiQt|@k>?5Z1jE*v#2&S2r=CQdgh{6xk*l9Ci4*IF z(*z6CvWngXpJ;3rqmG7s;{9?jnQh^`i_OYCVA9NM`3N{VDv{#$BNAWU*0r@+hiht2 zf(nc0U?#u66(?!!C;zSFM=}aPL3#}vuTu>ie=7G^i=8HkJGTZ&%Gca;y#DchUT=0Z zlf9par*^TX5>3MgVc>WrCa0`|{u~(+M>mP%t}Y@h>PY(RmdaWWDLm1PmSbHCfA8CC z7hL!aD&ZFthtFaKa6TTiZaU0WY}=eY`Gt>H!K~RZPClkjfywH56mab}P4ygthvv=U z)yXRMlf$GdqK3%+QG%MmLo^p7=3AavFtvef<+1M7w|Ef0H=a%Qe zrZ~HE#$Fb-m(AEK!}iLFyCxr)s=DdC{bo2-pPF}a-e?*WPTI)n2|GRHOyw>f-!fCS zK8*kF^%oc5dsY{!7C*D&i5-*gny%UiH|qL#nT1bN4LhU z8Q6n@4@DKsxIJOFXQFVj_{>ey?zPZzNxNhnx}J4t>{Njs?5YU6DyHlezj@Okxl1lf zmW<*{Y48q@rvtkhq>=oc1?9~S>AQ}M<|4~?3r&Ctcl23a&<1;?DGk1mPEwhFG_3Iz z3}T)5(aFI>f2BLvvdbUlRp{Ncvw+TB)Vm~|X+T|yEg7%G|5(Gnk?`vG+`Qb4d3m_J{(a=dur zrfFC0l)aWG23LcKKodrs&c=s81Gvzs$@s%dK31t<&ym_8i$$nXb;c_(V#BO@n9W?T)) zABadNtr*tIS(}eY&T?zx{4vqm$?pP@^t(<=)8Lr%!>};+r0Vh#wb%7ss@&|Ax*a3l~S4-tYcP965aKxsa{=+$BvphTfMeu8muv>sroYnsl5aS2|NXWeoft2y+nXM zn!vLb+>|E^>OUZ4sCah&O$gHq)Mx2*0rc5yh=@map4d5Vohhz^pXp5T(s1$8Geu{s zr;9gFJDXwb$SR7si_W>5#pr#atn#S(~4&Opkh&rfq4IF79T`QXT4*CQQI)Y7?2L;>P>=6^Nny+3!cZ z>|fHm*@5We((A6mNM7k^D=bUcENZr9ewrcKHz zd#q#1RfEG3GjgyalfPgQw}H4CB>i@@s9bu&wbJrM(@G1^X^&&#V^s#!K-9W?X;U+Y zz5A-k!^nFOX$u~}vJJ&9YvRE7QjYHaKzG!#Y|U~GdWg~;ko9ye9QZy2rX9rja{eQf zd-+Wq`hE(Pas0NTa_CYH{Q!k-NrW!r&{2e1yZmZb)Uv!;WIsU(;k1oU1XK1EBKrp^ zw58Yms2Fp{tg}_a@h(Z`wVg= zks*IC><56fB;lg`TAaan`#B z`g)nMcwPKZCmDX2;iC*c!tkREKgRGB!*PbE8GfAMCm24)@RJNb#qe?U$LMBJOUvFn zuA1tirtTqgUEPqSp`qcbX~~dz$&#z4`>vW6MNMt$0ZM4z(-Jjxs5Em@_ai`UCX6=V ziqA#05VjQ{YN}PY5pji5-3n~TTwkwl2XfW)P8Htd^g-bE-ClJkr7EUWy9nzdY&Wo| zIiRQ{UDZ8AnTFKc_2e1hQQFD_R`hOlZ2~P6;s7ZwU zfK&Vh!yhvIOZCHg!~GQp{58YBVK@~viP0C1nnXLFi<IBfn($uMGc_dr&mtzkb5g(4xwjIv> z>NjF16N$!S)Gm3%Bl zi&i4yp(kTBBM|q0BK8R*;`mo%j~Nk<#^}QuBGETvj~n>e*o2OMXCn55fj<#@(!igL zecHf39ec{apNc(g;7`YBGQ#D5=QFWq4E&kcq=8SyNW~Lro{fFhz&{%!eOQD)7kl2o zpO4Y*CK3L**yj!W^RX8U{Dl~qF-4j)u@?>e#Ta#G5&nhP7Y+Q2u`e0;mttQw@Gr-{ zV&Gqiy=34o#m*Y|+1Sel{&MWA2L9F9*9`n?v9BBW*JHGcOVr^Tv2PmqH)G#2@NdOl z(edvdkA2&~-yQpofxjpAT?2n_?9UARq1dYi{=V4v4E+7EKR56X#J+Ffqp=?t_=y;q zo49V@{b1~e2L7SgUmEzsFgU6 z;E%@GvP47eyB~?YW`ut<_9FxTSZv0?PsJhzJ{}`3AntWK7B%pX$4F9(@K3}p82Dqc zpBVTjV}EPlpNjpRfj=I*Xy6mEp8}8l%m{cg_HzUObnFcSe=7D11AjX9_Xhr%7|l~e zMV^WMqk&JxVg~+f?4Jz$v$20R@aJOxV&Komere#Ji~XyCe?Ina2L3`UZs2EPmkj*H z*kuF%LhOoxe=+u^fqyAR`nss+mt+5K;9rUT+Q46m{l>u0#(rzyFUPJL_*Y~9Vc=gA z#eH2|z9BB(^jc!SLz38k68JqpH2==+ty}io+15!X+0yD3KJB#HYrzbo0G&czPJo6V z0#*=?@4`!bPy_;+3ExJ525WTQ?!CL(w{O0?y`>YY6FXb(XzOfh-O|~%y`!a#x6(!n zw{E|qt-W(@I&~Sc^D0@iU{_O$1W~)cpO3u@Mzi|hC~SBY;7msxYc0!3=ia3@?)9UV zn9*5MStgQg5UD;xMBI>mvgHAj>PQ@W0KXEbdGvb^OocbhX`7QXEs?WF8o~PPhz);O zn@Bn?!0`MzOfCF8>@K`}P^>VdT7l+6VQwByhy5i})GHYtE=4Idh;t@~3LL&Y#gcTd z1#8CkkqjJ&kUngu(s1Tj7Vr$p3p@{gPMLJ-|#jYA?Zb55Nu_4!}Ce^PHpALOFqjzBP2ItR< ziF5q)_@wol<^dR#`sqAgvNiF-cF>QLuK8Pqd=`L8$6#a8JNa~KPYu>-V4%*_Ek?8o zj4k=w+xBP+jX1A6xf1+sx1`%@W+{CHraBRaPk$ev)0#stdx=jg8~3C88YVBT1;jzl zIQK?>O!$Ac;+xTUGCny1&rsVp5DeAMDh2EE$=e3>ue4Uvx3;u%2ovi`)JD3&c2+3~ zOMD$2TVD--s!$-{>Bah0!cwL^^ekp0EOJLwKkUniV|;1xZ2x|}b@nGObcqcBdfOUI zOO&HOxp-tcpj7u#;0#GkHmmmNCG=!eG2`))s;wW1FzeK!q%Yef*Obox#>blcT?doy zuz&wG^@Xcz()&xCYn{~AiEne!p=-1^f?QdX7&Xe6wL?Phj4DY%o_XVoETlR{^@G+} zAPwC%t1Hu5OQPTEpQ#cVo?a|KR7TFvJh4XqR(GDLSXhE%F@xV7~c z)*z0BSV0wE4$!Jr0K$cBkU~fukLIB-Z-)bkLY{Ss%r-l96GgWZFW*a`jldlQNHI~H z0rbNm-a(;v61WQ>>Y&voxMg6Y2u_FKYbTDORYOq=ofl!HXjs!k2$nB#?km1apYj-p zXa+p^uotEW=VcbnHV+yR>ug~54??oRdfOo3YgCS^u%l|CZL)IO(JqW*iH`js?>=Q?6!B*sr}<6>das3Vf?8nr~Sb3W2MZhv(5xojNNFmJs1l`J9;C}Eo^dV+I~R-}n{-S%rxva{@4N|KB##_BactZ%?W&rxSBWl#gGlI5 ztgaBo#y!*>Xn=SZznudr@~KaKgaFO!#3>c?2`eB#Du6hQBAu{p1Rf=Dk-*OgkOrat zoB&N6c>PbMX^cv0F5CZAQd-$4Cr-1V$$;q4H02WgJJH=wQkYB+@lnDm2zUt49Eic+ zA~GmLPoT3d7UQgoci^mx^^unC_(pnU`AY4$i=3?{TNNL7K?qvYIPQXJyHr{+Q9V_= zDO}MMF4-K<;LuDu?ZLsQ(>MSli|K6R01Ow?ZsPz9zEd1yF)R1IyRr6GFn_%5vGIPJoVzESMakG?=naPCFd$$it-3Pco^jxUsCcI4iJG_sbaLPdUE+6`q{8w@?)*zOOMTk$J!9?TmE(isSS$Blku0{f%Wf-u zB5C17=@oo-h(3?BeC=h+B3osoxIE6+B@KMNn2|G9d1C$*8{*=yLT=n}N{CHR~?p15W($A`u#QyKMOrUOKrW|BU@? z-iujudPjb|BEwcN?vG2jOx}8??b+Q|2#uGOuT6{CT~j%z9ngz**H~WM1`N%V;hxH= zh^G@_2QjuVoHEa1r6wh#VqvK_Gt~;rUub0TG2vRK$yjDAr<1 zh$v;EJU)+zG7zZPe8LxK5etd%h=_8+D+FFic$Jh}8Of>8|Ce8bAQpl74Ch~NG9lCP zTSw)wRp<_uiM^96&R8Z_KhZhmSs5-}HI=t2oPE<3sT^N#Ljm)c(3_13YBwZX$b{Z*Oo)cNRLMk@NVbTH#e%42qDBy2CTaz-go!#q z)HBf_h(;!s5|JNY#>8?Fvx140L=?tXF>#ZKxtWR8f>^`ES|ak}>zG(CVs2q#gCI6C zvB@N;CVo5gjVylHWxfym1(g2ZA1$8HlORuVuK#J39)>j)gXQ;=9L;MhHa#8Bnf z+XV@Bz+{^s+nLOd?-e8%BVu#ocM1|-?H~)|cMGyZOMH(Y@l`G^YM&tQ)5uOi?q{+f z?i1tzEw)RLvPLR`#2P<}%8&O55+}}5$(Q|t#MGK^bXbtR8rdhvevJ$W@`y&>FGw6~ z#Cd~)gcA;v1A=@&BaaI57?XwZK|u~NnIC^pkT@*~c?;qrf_$e&zDtle3!Gz{%=~^~ z&EOj~3v!D_wg_^oMs5@2ts1#qkUIoJm$QLAiFiP zN00|K(l1CXdvoH$g6tLK@3! z`Jf<&HF89d@6^b5338J~RHKP`XneCqHVbl#Mz#oYt43}U((i>j|ko9R1`@31~-YJk{tjt1fuLVs#^o(RNkgu`}}jCLs2RsAd9Uj|eXl z5PNi=B}_oZ#KJj~ zy9G&7kYe`;lB6J!w+oV_Adzi?Bq>PbUO|!+B=Sx{k`yHJZb6b1B=R0Xk`yFzpCCyJ z64@z8l7d9~1W8hm$Sy&W6eLm+BuPP#mwN zAd&YAlB6J!K|zufByvEIBn62)DoB!oL=Fm)q#%(G3X-HCkt2d6DM;kI1W8hm$R@LR zzZ%&rNRomS+agGkf<$f;BuPP#m$wU&q#(ua6eLMOB6katq#%)d1W8hm$lC=;Qjo|t zL6Q_Ca<3ps3KDszAV~@mdAA@*3KDsbAV~@mxlfQJ1&QnwBuPOceS#z@NMx5FNeU9F z2$G~Akv)PWDM+MWkR$~`UOp^Hl7bZ5CrFZlLK_UkQNm4Ltv?uPb zHbIgUByzhTNeU9VQ;;MDL0;Z1NRomSyGM{D1&O>}kR%0(Y!f6&K_d4GlB6J!cM6iE zAdzN_pCCyJg1i(EB&49L^!4l#{J%25LG+>Gs`21N%lJ^ZwDwKuL6a@*%CN<{ zk!SDu6Ut=snY=Syle@!<*M`g2y{XOSD>uCC3s-FVc22mWdCFQk-hAHLj9FjBEic~@ zE~nsf1ec7jKrns&*e+GoMygj`$=G7DExMRnbjd~tG8C6zN@vtAmElxNMscjA>xzTW zD|ANYB{QMI07JGH?@B)56dM{k@wq?Rq>oQuXVDP{4SXB|&W~2DNC(SfptqM!^TFmZ z6*fXirPWC_jR0AYqUqQtjN_hrR5mKvDab|})PiaT;c37rmMu#T%Ee|VEGJ3);cRh$ zs+&k!ED}bgJYdlrk+YM&&IxyHxsU>FUqZ0OXAWy4k>Wqg7_5rHvEW!Jy;8Fj!W z8&E^SosxZ}Vf2jVY7V!Z{Q@OuxH~BL6ahAG%{F;mwXesQkOq2{4JufGL~Dq_uK~s_CX?y1)o!xFe&NbL z?)ZgN^AoA^$5Pf$q=i40GX73l^b@J<*Jg*w{A)=EzbckYi+^pln9Nt~lF1GGNKM`G z>@oXzY1mygEiH+g^G!KFx8_|en18%AzSw4}85@X8xJ(pJRz5NR3Zbx_6l^jbcaC;V zOB*j*VHuK4nWHQ4C2o`XQl_+Y<#P`pQXX45o>=+xIDXNBMH<>_$0PDJtODm&P5mJH=bzyO~h47p9RVJsnbp0Ov(9O zJPT?5GwwnOSA+Dzzg?NuQX#!sVcVKxd9^03rP2IqgNg7)+ty6mtE~g)XCi#P jZL2l?dnPmR?^#TQTP=jAo00x|8I+hs1S{h1pgZmfdg9)oH(nX6}`vfsh-00t)eyS}R9!w-Z&aNh*xUk}x(TB?K`UO$-W(6d4lakyI*4m4IqI+TDK(0rvVi)pB@Tk>u`U@M!Pq zKiYFVOl67s4XW#~6dqBc10%7%jLHff_nTE? zOJZC#bRSds9;i~S$5Mz`IHsEVM^Z6Kb@iV<-X3c0YHvN#-P;L3+@bD7BpC+`kA~@4 z7=#zYN|?FMz z5R@(Ymkbd-`e@XXA;S&&mqMx2$^@(~>;+KRgt=%$Z^m2-U96n2*oe}oL&%Vf`JF0# zlnJZoo3Laow6O@rnsOM0Z!cMgn{`NqQpZVOp_28lDb!wgjwj=;Ekpsnt);DmR+O}M z6k4Aq7k)TK&KXaWG42!lxJ&w6De42fC_hd^$vD*y%yFmQc6gWmR4DZsas;rN)kpBJ zP5+>XL&+miMPghjDko!M1sM`heLR^EQZ#ucCdK7|-7Y}dp9<4(TtFtUU+7E5C17dD z7X)P}tOyB75@kV23TGriI+uz8x0A$x)=^^?`-R?QLV8jV^XyR;!c>A`q6tM3v9GLz z6JnT(LUKe&jVN08bYl^^bR>~L6al?F2LxmQiv~IEJwC1s!IvB>get%BzGFy<#{z&m zFizEqFMDIrGb$fD7muZ%>=qJ9VAMD~&Z0pUqB2$q(F7n9i@_X(ZtW3=jVdtdabZY` zr2@1XmO5=kI8E@U$ot;nRFkAoNlI6DBu5gWfM1L7xz7dC0ajN&i~w>Wk{pSNiADw2 zFd9d30K-!s!0k=1)8Og&7r{(FmaqKOKvkYfVKKd>pN`|SVCmTc3FFBTs&DI9R2hN= z=>Sn+9gxDn?lvTDg41B#+SwdO>kOp$Y<0E;I_CDj~GrKE(&_L3sURrz5M%BnFQ zP5~H&s?MJ0j`oC}X+PQ5eXLh?bhCYFr!+~~&Zw55upCwtN|85H6kV#V{ai$1;#IXN zG#ru6gd=BF8$&Q8or|c}6p#c+?{UA4da#GnRX!1pOR6P@GQ&$7%$z&N z7I`ERkz{Bo!`YWn^dgC}bib#02&l7pV33C8rbxIs7K=B*89ys2yPHR)#Aq{||K=1U zmED0yA8VF@12m-o#qgjcH=mLBH0MZE3Z%wWtNucF<0$Z#-viM;N$xp`$v*Gc^P?BD zj>C(5+YR0}@2GpT>ig@zyFTmKwa5p4?R$Lk=(1oFmVuJb=D{<9ccM4gjFy~uzZoA?1E_-|DPn^nnPyNHFbxZ$0;; z$d9*N8@YbyME1~$g?%R%n)uZh@<7uRq$JgcWGtVqqHUQ2S$EU|%eQ}EasB+UC;xg4vnQvHK^X@%YN3-sy7OjVtD{H1K z2(bP}6-?o(d9mv8skY@cwNst9t;AUc6PmAj;@ZA!Rm-BY72am{Tz=}(Q?DIbbZ)(A zbxoaHvaY+m9svLT-bUhCe}`}|BkWXp_?OPs6(hd>;hrb=sZ0CR@k?hXe(HixYl&yw z9b$m-airZ>2eMTM7M%xgIIFKaH)Wlhe(Bu2VuH{2<$bW5Kk+@;zMcHkx1qy8-m7qngi-h3TLiDb^Q|+#K+~ z`ve@5%V5cfh8T%+6Go0?48tb)QkF!c$meA{uOJ1plpzJJPXA85pkW~NvLu>xc{)K# zAmp_@9fIso^7>sSuZvEY3hZC}i16dZhW4xch%)em-$3_3HGLeiv|*Q!HXPj3>vt9jA7d(+QteThX&;G* zM7JUsvjm11m~&{^P&AWN8?bDu$pTdVRihFfRCz@@r}(W*qG$u{#SSRd*pMjn!T<(T z6g)$!MFQ;(4--xO5^&eIEE)Gu*&#s$m zTd43)cHXdfXSTj!%rVFpr(c}ix8SY^mhY&Z5#Knx=-70_yLQ(1+QupKa;<;1;XBRW zYQC~6>P&6ibj6fuY7BVl_e^tR-+%GV7q52yL(kv$%)48b ztgW|=*yJu?LL!*yDepvChMLPnBH%tD;5y-gM$sVg$YQ_^U;R*=ea zDmJnj_$7@H zRZga8PxqEc8za=<|1PR^#a@RD_ckz4OyHRzeh%Cz6ln#VCp>Zy3Vs73qu|mHy&;rJ zSCy}CAe0)zhIqgx37pEQ@LyVKE4)z<0z@^T?kB6hA+TIxQb>xYl<`oGup&sSdP2>R zA&LZcnSdC}p{F;%GQ+(N0yATP-0*F_WCF(C`<#$A3w`}9C;Q*xXg4(X^Rx>Jh6#Nd zpN>E#C(3#A>u6S9yUu*_u>1Ou|GJ4V2;aHC!3*lcF!gEl2y=l z7gd3hllEuL!vgbYYw2%c6M4&^O$3K1If0Jc6wt;_Z+O@Q@atEg>s{153h3Kr+p->E z$-0^0|Jk8#2h>};T27v9?cKfUXO*mH%aV2L zXFLZdJ4XH8{ipR=P$trf$={PdKT1>?#|dnH*aSdmYE53nH7MPNiaB4_)39XS_8Cus zZNssnN85Y***4Jrhps=kZvewjSbwd-*8uMLoP*PpK!?G z>m|euoQ0n?f^Iksr+Sa{9(%U8sqNv2I!6*`6UnheNJLCGK5!U{KYs(Tlu_@`)8o8n z^BfT5_9d(TGhSa4pntskA**Z4o#Iq9UHbsW`EQpI-BRvnncaG+V#&IRA^R5B@2^s= zp%6MELLt>23dNJ+2ne{4>I{Wm7zxL6Uo4>z2>4KlX{t;pQ8dq}3o|snRQ^md8KcMW z{Um0mFguOe7cl!GW?#bW3}zx^Z)qFO#20PHTFjF0m;Vp4^W?U{WU{VQa3=3e>k251 z-r2UhSgcf#Z98t;%qIUw72XvSlq+W9@y)c)ZkauI#rUm>`PyAsUsKi{Sh3(oE7`PV z1)HzfiM`^k1D0(>?q7euu7N{?_t4qhb>1*>;(lOld=2Z zp;!xg8{RQttYjEll%;|N3|bQBH>7`3YH}8WPC4E2Pc%G>;4sy0HS?2ci)CKja`W?( zUD2AN*b8mP~Mkz(rwmz~un=Pk;kLWC179$U>HuLSSvem@pSY zXb|e+3T}{LH1Nt&#;9wTX&}`J?!u!O`sxFfGJT*^N=P&eVS%tfL9I>3g|Q?Rn_|(k z61eEm*`S-?aY+GVfJR55^?tU0D!GM1l^MZ)lWGD0gA%1!m4XaxPzF&oM~0H%cLxnt z#&4*Mt6Ws&lrrtrL~(4If$w;h6+})SaY!^p4Zdc zU?kj;)%0}HaGof6aw^^@o#6DGFueg{FWPJa2VzMu^5lbo{MUcQ zjsj%AA-|s_zo_cG+VYL|H@1Bz@U6fV@0FH?+Q4;RbGEAUf7!wKvVSLVDOwNhDcWUV z)ZzJ&aR+nujx9eLJrA}2gr9T9jGZ{$7oV7Z0>J&a`r7C}Z(OYETyS*G^PL)1I};;u z-FTBrmK*2K==2>J=`w);G=~A`K@2_TPfzhVc>Zr;D~x|+1K^T{z5x?FxEKwLs&^Fi z!qZrm3Wn{32^^}3Sy>YKjH%R^y3hsCO$>VT>U|W44y0)G)eemb0@z65kn}^NmvC@0 zFpdSsfq?p#iy-}J^RPZJk9Q!vj=^zMFUnFOM2}}tbYKqD=S;VqWGn|RU*L(<7+V5- zilgBe1gDt8FYlws$(INDn%|;w5D^liqu@SBg%j++tK1pYEJtWGrKlz)4AD}?_io`y zN%IF9v|Wj6$toXsmWfW^vM;`Ggkm!p@WbJm45{;b1)r911`JJ0WZkbfg% zWR&`AIHkp^&?j6&K`G2qfr5+KsAwq2(gO9BQW*FP!S^=^*Rw?P01xu|1j=jCGGT;^ z40#$|O%m%8V}dWxAOsu?I+ei{fKS)oBw9i48-el;6?l?p&lp}Zy~L-%c|1^lS)~uC z3H+Gs0t#Fx`;_DG8S`qFQwl5dsUa0#J8@-98HQ!qy27Qhm=mvi46oOBsZi$E&ibiw zw+^E)C`*4P?(WrbAFqHbAo&0kTpKC9&S5LRJX8owtrm#V=gO{g+{<6*@T3FJNOW9a z5oEZT5Eh%1WD}M`N}_PxEFK0m1EL*?$Pk7<0_jIvlW|bO;jYJME(AggpI5(Gv0GPQ zL?JB1Amj%zq1E`Ou)RSP&fuLjzji-Di$kDcOsgR4=%=`g>H5Qcdv<~u%WMI>d!b(- zz)(*^;IRQYPza->x1J0ahptv{-<#f!&5)Pk1&>bx?RPUzFuNCeT(DR?MWz9_4$un^VSHrES}fneswiX6^bu^th3P9g1g$SK zMv$r*Yc8;7Z+@Hfy8sjo5)5j{hd`7}lA9Q1KlmO**n1ZF-Wv}0jB~-UaZ-!Ef9}2A z?xSYwPCLTv;|31pteAO*yFowyJUOKG1YRzxo&pr zoMX|stEiF%t?%T6){kF%^5@*oTmHi|zrQzI)w|?8j_mma_uEnHH*74*b|J28P)km)C>nszGJJ-6htu!L z!o9q_qBC5fw<(mO0T_=7Ou3w*28p?RvOLoA_TGMx8Ys2MviMpgL#TKcF(Ei6ogB_W;gY*!Y;#QtdLga(C+cD z7f{+5;Uhh(b{tf5vB8Zgct#hQ#uNBaU=yl|^^x%~An=pF8Fw9blG_ANRdLl)rt+Oe09&HMIVRj&2F z`@|yObJJOQv1htxcI|?*ezN@|-gce$WqIGs7Z&+?pwjDnb(XK5NzTzFeuriPfzJfkRfU*UZb6@2kU_-BBYdlx}CK`nTZzjjU z&QHkTI;4M%HHK(X3t|`F%wyb?ZHC5xag9_5o(BCA6#6h!vof9n_X9=B(Zb;ld_ozk zc^r{Qw0@ynQ-=TFU;{K;=^SR?#LSNw>H-w)XgZA9Va(bw+lm=FgfzE>I}{2-EENs| z-sXm>Q23-8!T!}u;`7)N)oRACDQ+Ykz$UQgU?ppp!_H!DD`t3B?^_ROKGlO1ZB!&X z`EkhM8V|>*q!nD3Zr`NiW8(ghtoe}Ce?aX2MRt5hw*Ssx;S9eckln5%y!S(X=f}kL z0sh<{5XT3^11;~G_j0wjQ=E@$;B5LKk;GV>HbZlaIFW~2dne;u_M`7hT z&c>~o-MvDfnA>v~3(&tkHItU9ss*xUxoXFxW2$d~?6_@qa;_QhltM8Zxr@c^IuqB$ z&49-e%egIgS$W%2#qFDsR|phy&=88-y9DkqH`lsCu)GR*V0pWPb8~~u^y!OVoc?;8lzy$ya6u3$hNl^l^P~5-;pk#rj3kAFfu*h2AR|S$N zfet0hF=#6h87Co>IAgk7nNX3FFz)%%a!=CnWa(BXnFJ-kLAk=|VbY$Sc6ySA1bI5< zH`AH_ocp#a6evoT?MXV1#H;)6zMOOJx#ymH?jIKy7h3TAN9W&6RJ>`m{0I8bo_yi3 zuAFyREVnFYERsdChAd(0u+?gjY{NEu+e7wYJO4U{9r$&GoZ-CTJcL^$XDC1H8g_*X zh6}=l!-edZ7b*(7huz`g;o@+~a0&b6hdklZ;Zk*Mw__Yr}QJb>aHq`f$T=LwMcrx^UxgW4LL!DZGAoeb_tf4L1)rhg*hQIIn`x zhVaJWjp0qho2(YOQF#n?DhzE7w+^>*cu}Y=+&9^Ny&C;Y_l6XCtX zdr@Aqyk7Fup$p||%|&11HhK^5lS<|NQrUhAua}#pa`NSnCpn~oLTncKfK>UlDhv!i z!%xA-e&L$a1BkbD- z-*&lHK14mBhaKgxEeP8xSIXsbx#&AR{1}IKAiPsPru!aeUmtwCOuhr`yA8hEO{Je; z-yQJXDWBAHIK{rZ;OmhO$*0}~^wTqZn*Ddf|1tTr9(#~|ABXQAc~JKqV&5m=yVvA< zhJE+JcfWi_kNYh9J_+9grnt|s?^E!7+T{BQ_U(r6L6h(E?Art1UQ^A6*|!hA{U+bD z?0X2l&zO8a$-al-d&J~>j(v~9_n67|Q|x;jz60nTZPfjMO|Nu9KJ~SeZ`#xz8{wFz z5c4!fcZ5b)t`fg`uLdNGGzjb)9Uiq>rtR%#zDtSQt?8mbBod7W;=yPnmbM>1JT&lz zHEr)19Bj9zi~N#2smNo2xGbg1OdtM0C>V&P>&;%{Q;{*sMT8-BL4Q;U2jX#ANf$pe zbo`j{>HdW23w3Djj>nbY=u})jEyv{WXh@Dd8&HA)IGzhAkziz^y)13-j!dUrJ%Lb& z{L_x!;8;AJe@KqVN^mUgI*f8SK)B*jCG9vCj3LVLz~m&dNV`rp6OO;85B*G&M>24^23n*lE@|hP2-2n|56Xe5cyN3wG#H(lq@Ep8WclD!FeJ$eh4+QzupEi^2ScbT@@Vk)MdHEu z^x)KJ48KSljr6OXm@f6}-E~442!!Q!H%6d4emokBpNPn6UTF`!)UJCr5So&aF4H5H zE+{sN3 z{gbh+58NtPosGqnbLl!Wa%99#+Yw<*oo!HcizN?#z;Nrzzk%bHWyTUGUw$rGls@BY zhG(y<*0@R!ES3u@-PGdK?~L_=%2j0eTE3>wE^(I@BH6xX*Qkrt5--yH-&7rvW5)7} zmS5uebkGtn*1{!cyhL;VqD{&}EZZ+RwAt$=YkNKs5(jnvcZpEpqc9c^j9m=Lm*h~| zZSI{!emE*kg=BA{+wJ&8J|^O1EdFd@gN#$NA(qh05tVYzF3LJ7n= z#{ylUP`EQ59J?sTcXnNpBbT~D!O^bCX@Fd0r*Hd?t{7mV6EJa+^5`0k?dp;R()%W- zK~4P=GAM0a@%xoyC}0SGF+X0{EUEmWMUOX`@4Z*P;dXDbynQzRo~!iL;_JmXCT>M; zM(%995m~72THM|m&DR}XC_FOnII@BwEDxMh@$t?*>6+fY{_Zo!hWsba44phPBj`;=zE7o%br3J;I})Rh&%E)r$#wJb1<1MoC-Sy@80NM}Q~i zEV7B855&EfWkvQ*ftGvYQSX={V`>ML^Km&3inSS1P_R6awLpymy~KerGs$tHZ^FcD?%Rt~y;fs4lAq;MJrtM>) zSe7r)W%NRfdWeS6s~n{?qj)76asZ1@&HAShAvS^6HOsqhOKIhDo~5#Ow)ZbR75B=k zZf(7}b#CnTV+-Y5uJ?SqtmZqq*RF-~w(C8{_hWZ@zPkVJ#^eUXeSEejRn;(Sf2A;0 zQG*{>sgWJL|IP>@|45mSLpW( z;_df?sQW)X6$lZe;0s+PMaSUq`28j(6MaWr@P>uU6@BtacqsJxEdF8xczw?DuFdXr zEf-pf>lYk#slu8CM@`DJZo#n*e(N`+Hnc7mR5>f|mo_dt@rzFKtXs|}m&;Pw%wdRF zSn_@m{6tYyz!?7YM;&$R%0_rSgdF5a4lMAT)6Vw%^d@}{VTS9uVElZ~`G69W<7PfC z@D8T;?ua)4)=mkG#l2&pKrH6P1Q;Psj8GjDmN(!XLt2E(idR;-G;eHD9t(~KWr>k8 z7>NZX8EEY#9@;xHvOkPT=Pu%=ybPuY3hOFXt@>Kr|*pphw==6r4HB z3I`|7$GxL6XEPoJ$=>Ug(InJIEtqK3$Ou&vO+=|WC&fwHM%2cG?+Rr0%t*TzEzHa% z8i|7g&XtP@$(4&};?VhE%nRN>dO7CR8Er3d+C<0{Su~VM++;wBd!yq_1-Z}0gCWtt z%V-(;K?;tKgA7LEMxS3kFGsw{Y$_h7;R$%-;N87oMFJQznui316f~eDssty%^@jYH zi02;DNeQ5c+;-yRsu`r>I+v&MQ{arOiO=^&LDfNf!F#rX-;s&G4k*(E7jbH7FpM<_ ztrmD;)~SNT8234mlF6t-%LN@QfM`<`ojN0?ttUX)5krHgF}<~-EtCzIvWkId{IFJ< zEHPvB1{OFmTHutSf{{2-+OI*U${8`*rYnr1^azP3GQnUC1o7oa`djF-7%`aFEbqH4 zo|c7@4fC!IjJpHv4kd;V9sotwTq+S##>s<7rgENML3+{bpj@CA(KkV7Lgb>?FXJy( zi5JnCLeQCYma1A%nD-qH=SGo$qK)BCe=w}{SXWx`HmC)&4o=Ai3gM9Qq$k@v0IVgiV-LQ{Y(r&^O~Tdu?25a!e+dH9hmIOU%hz!;@pP0&n%SqX6>oQ zt+Vz;SG_TzXEaf#O0`Ij^`+HlB-WSKY3q!Y7@fpFW7yH=8uM_C%0w4=fYjmgP6R<5 z^v*WGh6sxeIuD0m6?6=i7DJ`eI2uk3A`Ft1hR{kGMl+O8Q-@H?w2q`kB|6vc$Q&f+ z&nOQf)z>WG7Tk@C-Y1epPoyfUQXcQT%PVNl8xApa!~hD~Lk!RxR)rW91TtaTss~cE zH3$=f1XVMeFkK=)di@UmVr6)}48r7cx>hQk&Wi7q{Tw2$L0cA_kA}n=f=4mNWJr^r#KdZZ2kCs^637W8 zML|qfV#s6OHo<%xae=K(y1N32_ z1iutST&!m%iFbmVX2&Sk*CblwJjNisj4M-P5c~10tyNdd(0(ey&shRYqmVJ6;w;k9 zO5#k2Tm(Q$NZd(`3(*b%cmo(^;&!tqnyl&N8bzVkxAC_^BAAyg@7bJAml!(=`A}n5 ztdAWDI}@~^$8;8^F9yJ7IiTqqa%Yc(ec66 zLjx`eY%6n2ktlZ$Ga-SHHx!)+j;Z~kyofes1M|z|N3XxaUrg%;aPy)YC?umB?C`)N z*znJ10kLGCwTxRay}E}Tvz9B?VJ9e+BV7s+a%S&LcXO51&Y=DwI2PR85cP$@x}w!$ zO+BefHbp-L!GVVTIGmfLo!jhkpj2KW7E8wOzAG zwyQRS6`ZlfiEQzs%_WL8(wq^)p~Z-kaFCyIef6sp#S1jw8QYsG4L}*Z%}62F?K762 z!cG9qP+A!f{9D`YiNAsDgcwI1EJS-dz*NR!!O_sP7Yn-J_%!tdkPi5QZkdEP0Ruw< zQF!VHi~)0(>MT#*%%?Mwhvh&dM*RmKmziqh62>eI2~(%wskMHN3;3esA|SSxv(_sZ z1Jg1su(l--nFh5YVSh-C%?Pj8i^tB_qJIx4FQ7ZHa4QVP1cHx2xIY?=hSK(6B%XGT zhoXVFVCxIJ2`Vm)CDa;G#VvT`74URM`ruJ<0`(MpL8|M_1v!dmaCN!>Ww_*Rpcm`jvM4Ep%*d9X~zJ#GDOHl zyr{P6Vzn(}awvq>T9updjS)aSE!y;xa4PirE(Mh1^>;Ki*_^Kb>Z*0Ny=%cs;59}1 zf$_SGa4Q3`13!)0{1|XsqY<&dv>*?ydbKpb4M3I_@P>m|AQch3uY5(!SYz6~UITE&9)U?3J8!-9627$@+xN$h; zE;ne?`<0f``ne5@>vt@AcBX0@zT$e#b<=sjw&A8Ti(=*J6zg6NilxxpsQfIwexB-X zA~$p7Nv{H`o=$GS3IEs1Mj|(O335Y`GRTbzGEk&Jh`|X9;Xby_9T)W35fRjfg#H)Y z+L!UGf!#3H^Ri3b3~)(Ktnv#W_Aiw3u*xr-&TlWmDt|5ERp8gqh>yO?*Q8|(9r|SW zVOIHj1z>4w{qynoWT*V;so(7HkkG}^(Xr9t+Sa~nk8lf~||aVCD%)qT#ZRr z<6LCX)p@U^?88VS^uBrv`F$QN^7Tx4#AfuK&LAU-`dlE^I_r@z$K;w7H1r*W?%b?Z ztRJu`^~m|oP~04|jgfD=Bk@}wyR<~bCl&G_Cuad}rp!x70CkiTI3^}@;-D!D+JI3- zaXBO?%n*+e&D9coLH>18gVuy21T3O*@zz^A4kB1o)3?wGey6}7ka-P||# z=`S6a-?%$jv3uUVn`ei1hw{%6B~h%%zT;FM-qAD(jvYdV#JFOI6o4f>klYcoF9bTT zQv;}Hyd$chPL(gMi7GkdOUJ0PCy)tEvStBO&8??yKDAV_Ia#s!wsL3J($)jXtp^q= zo|<<*^*x8R;4$oHl~%s`6W4!Y$3nv@!lt^#F$T3Tl+yHaYDN)Xp>#3h%cNKJ@e zC07ksql`k?P-v}@V$yn)T?_v@$tyLRYFIDDr51!WNK?`!X#;XtCtZeGsbjbid0sKf zkfxT-4sxt1?TTaZf&*JP{IVajELNF~{% z&T*$vZnjIBk$lKuBj?a1Z8PPt>7nIrN2<-7YKOGbl&bZS%iV<>+Bk>Z(qpC^+S%`M z`0df5Var47@&t0)%Bl8B`%I}i9=R_2kwYiv@T7FWR2LunJq16bE?p0;%hSkd8>i}) z4w`b>{>XLdK@K}OhhC}Al*3N;>xZ9FmtB;r8O|9hu1bfH$8L`QjC9zP$75#N^ zkRZOL&qzm*_Hj;oR61r#yNCUb!_O%H3EE}3SO+JUD&q<#|E1y9~NIGWUBYeUXegZolKbbB%3GF*oy;bb9Lavdi zhXH*71)9c?_48&w1cMXU!BBPec$)!S6z`d`B7nN&8p%>k#a8JEB+K}b<6}NAOM|c- zs_iLYzg6AM8Zp&q#OLkjO&7>~pnesDL=-y_t(1;54j^4;Tsyp22I*GL5Yx6WBw(hmoEp1oKKgo2E7fAIffMBf6=)f?7qAxy6J`Jc_hMUv=>gngT?OP-6Pfltv@}_uDN<{tBS+G{42Hw9 zL_3YxR~ePD(s!IFuQxFv?XoA`z zy)UWWsuo6!7ND%?tt~^j*}7KM+Re*d32L-f9&JdC3e5nuCO=pWsM_=leE0A1VB`Kb z0F26S((5k0zD}=yfmhn43c6y5#OuVYm=uYl#|Zy8Q?YVPJ0VD#noN|L<^dmjU7_{W zpCC4thdV4ajkAtditc;2%{mrcjj1BfQjs@Vj$PP&^H-M;(l+9*aH z$5@vvS~p+Rrp9PYLW$u~Vqk$;+&J&vm@2KjRdlmxzO+?!EtPJ3r*z}}^&7tO!fP)q zt>2kkzw_?FVP!FD$?u8D2^zL^qa(V+aYF2wM0l~s7OOyN~nJY6p8dUMd2Vt0)D(+h%#o;YYGXk z)8%>$KU{oz0mmwIg+Iil9!^_v>_?B8&WldPq1mWy5vVX(EF$$+Ati z0}Ewsvw0~`)oihV3Yu}XM~8|(g3m28G+1+NkVE1*NOLWv%6gO=+_8-lFOa^f+<;PG!?ym6)i_Usn%QTpbn=dbVu3$K#ADIuMVgsNi9qPt z2TXv09yS3TGlnTj2uRA!o{c8#D~p7a}9)cj|RqB zacOJHh>W^1AE{!9s5R((2nA=9i2g)tv-0}r_TzEj#r-y4@|I+Hb>K zSCaI!&a1ix8De8y)rFJ}*4p!U(Vd%5WL!2=1LQ%^wc@xg=byp39Lc7MRMtw7OHL0g zvFHh3Ra zm35PMqQVSyDts>xs2xHmW&4c}> zpQz1fyD8*vr~?SAuUYPuG@EqPGjM~rAFkgd6e01?88n@6U!X% znu=#wh(>s&fDo!AM+6|?Y&Kw1A8U?8jK!+dV`EduIiM=-iqjIjxnwZr2FO6eb^&!& z{unP4P|$fvwRb8_1z?L%_%2h=R3QyO18M}7OE}T!@!l?9@NArS39b4E>kor&5hXlJ z8_#F64?Ei6@oqdHlz|Vx1x=5Px^j#TJfo?sHz`9~MptvA*@lmX z)5I4x(R&T;^-~zYE&b34h5@+=;Rh+Fu9ki1!@6Z0Pk`&Vg&X3O(?jx8AZ^Ew8v7 z(AfDk`(;uX`~#z3p?ie2AC9YoffbWA6m!+}wFx9TIMC=@y+_7_N(`qB_3uH*yhK-G zLPSntS|pwW|AmgGRt$;PumGdeP*{EHIhbq204=zCUaDPD4>l4RB)bO6U!X&9)|ZJv zo|-XH5>n|0mwxE49=#ELFEAt6T3l7OFenvser2 zX8Tj+wO>5;t{v|0^UVIzx+bgGf^{IJ_7Kl%r!fn`L6WFk^a4}_ak3w9qIPhi)DAqo zmRB8Pwh7Ca?HuwanafSvD|rrlU)4`%58}(pK9`AGokP+?q!S9n89NVq1^UneeR%dX zbwURX0$GHJu$r{Ke9{L*U0ul_ECHxvn+985D#f&*z1~5g!KP`8D2y^G9?SZi%dXGU7So&0TBo+q%8OW?CO;z$S}8Ob^eU5w5Y=Z9x`I|NEXd9$$NcX z*r>?JTZJ(}(lx;_RAA|d9_ig_xWoGQYLzoG2u?)69Z1MIq^k1~djWOid77$FMPg$>5pc9Y{R4uDr8QBn_>*)=|1Ny-p@J3ip z3#~<**C*v(@FqlFg-&&LFO%*qDd>}2P6*5mDzH}ww{tD8F%_i&)nszxLNpi=80-`n zT%d!6LJIdBQTc7SvX0!QU0`Z#sGV)GvJcou-ouo>TL#Q{RV+5&EkI+g%y-m-ts`y<1mcYQ;kO z?ALQjTdx%vRvZjU{F2qg|LQAF$#xM^aHU|zD%ok3dEGK)QEb<-+KiKaJwL1`?|2z{ zm%SE^3wl$f`cN3xDTn0Ld|$HWuGv-OoJ&4@L03B0%A}fTxm~p*6){Fx52#a~76&>` zhUTReA^8T~ItQf=7{~$5y6S{n$CH%}J|RDLYVk2g)j3c)I44))_fP8wKmpmA8yBo@ z$-)*zaN0uVn-R%ab*tyrI=mObWzj50h($9Vp)k35#Xt^{ahl162E)ueWadr=Eke=A z1l9$hiWylMOjqJlSjZD)&Qlao9#qi3mJDDeu-Hk!N=l_aXVut+bLD~^xNge@2vZi7O{fH$U?DbvnQhFlBockY zp0ZgVpDnEMU#|TC1kr*HJ$I(qZyqGx@w#3v@#&(=0r6PvO+GT_B_5}#h6V}vvWpj1AbeJz4werVhe zvoZ1&QendJA0>`c@YINO;j?tOR~QPhhh!KF!qJ1YlOw0|K}_h}cDg{0;NUH0IvMLM zHm;)zhtrOLG7(D`;tYykl$dsfr$t#fc_3X$yUlH8k?{ykN9qFX`=~=ED`<`mEd)!9 zt6Y~Wt+9^Y3qvJUQx1au@{$M1?Kk5#=rQ)ob?L_=A_%(Uz@m7`C9Zo z3;`UyS5$)IgLf(yOMHt(J|v!R>|H4Dn|Jr6s_Jf?y?J()3aHG zT}>%Z{k*IGAtK$kkk^_bpvRQaWs`SFgD_Q2Ou_M6R6F!J{a8i$%6Ob_^#>$NhW6&Bp z;KdO(UPj}*k(ua3u~Y~L6I=mvT{XUCHA(DvB)(;!y-;kKz68LWje}amdVK z*fy4Mq*iI7uwSLuU3&5Es=i&S3dNQGi_#WyQeK8~+$?GMdx(=MmsDqB=pI>OPh;3X zyvi+_{IP`ym8T`u)bf>!uU%Yf>Pj|s-E}N9?Y>cDYd)-*5G_>wigS@(VO&a9_m$+I!(*?8wz(z7SEyZeS? zsdQ7abkkz#j#N?2e9?wG?zeiE_Mb}Pf7_{4$F`-8?qo;z?6F06d&;{}Z1uKmo-JH- zt-oJg&pW{GQnA-N@9so3MSgdNmO2k4@xS!I{q4J#wjWGxKWN?)rZhC)&Ldk&)0`}A zzEio>ejtheYMTD!_I^sE?h>bV?U{G&;Tqg_EP6>ct4_}uEF#G%cryM2IM$ksHKJ+- z(YmhNt5urz7Pp*pVZo9tDFOfT0?i=JiNakiM2@rXE`ks@_!A zf(Il)H@(Jnhklu!kGf|dl*Pc8@HRBljff~--CZylK?Jvg!!YvL#VvX+#x94x2BEWs zqoiwN)T={3&`$+n!J?-(_pi@LFharukgvFD`(j`S3^`#vQv(t~)4_CDm2!^Z#G=AG zaA`Xjd?r20uOX(!1X-c?&gwE#lbQTafnH>y%FG1m-Y*a_c^+ATm{eN|iiz8Or6jd} z!>l#63AXuCC7#)Es=9_u^UWSgxr<*ta{b7XdtK7KZqeOD8{^Gi9$fS^ryAGau>Nde zYMpns`<3IV(wf=sB zPl3>5k@l26+5^gO0l9E)?(6swoXIS?U|n6XGy0x=W; zY|%|3GcgnfOMe?J?)o`Na47Rl`%-m{OLbe4bz7F|_9g4~T|aWau5tDVR_JrXU#nOw z@4UNZX-D5XJNit=L*zN*Fbvu1#H@72kxL9|Vo+=sbRncDf!-!TrW1rKm-x|kq0ES{xn`U* z4y|mh#t=?E>wroS))J1uvuMU~7!ejkO|_aNth=?v+8O_KZBR^rGG-xc5CZG8RRYl7 zgmm55r6KC5t{v2!4mN2+-mH3Q#w4GRJ^@7x>cr@VY@re)D28UtNmNVClLQpllv`U< zRm;XyI}J}E``YV0K^DPOsjG?RW$4)o!pRD@ya|Fvo1>zs5TLNtQV>wE21Mxzk?Be7 z=o1yzNSkOXHi4qvR%I)YrumnJpPS(@2|uwkB!2O_O&4?)W(Yck#hd>V ziB!honlP5}*YHVnnCkBnmG+CuBlt6E+w`c1(}emaE%Z;7>saeQy+qwb3z@oC* z11xqtwNQR~-hG+{lC8HlE|#<|7PWFn-$Hr+yt_ZOsTF)z!}|9uc?Ab%kG_xdk@a(1 zUw?rt5tKG8m2OCuZdfecl&Y-1b?oM`+m#EIn`iq{?uu6jt`E#T_LV1Jd-6`z-J*pC z$ReLyE=C^EUI9N=A{a51(x8G&=>)ZV=Ep?sB*#@dD4v5U9?m0Nb($!iGbhD!{(uxO z4>a@9DIU&NCeTqcc7E$yG6waVu_Fd(>{a_K0nkAQ=wM#p#D}4Sup;(QDme7fC?Lp5 z&>({!fdU4`Nv$_KmmeDe-2M;($W{F@(7%j*9hC}jU2>4WzW`lOa3_sLDZ`6*ZgNsN z(d{ac<4r8FomGxhP{ULJjfz3R@}lG8;5ijCagr|3K}pasVrE8o`cS3eZgU+ow_MC2 ze?lbe4iXaytIa{ePA-(6ns=YdLBiBMmHTDoAbCv3>Kfm(@6m5XiQ>7 zW#)dy$PNIsZHfEPCv)1sz)DUv3<{wpaWlFJO0WT|)r?GNM_dt%%}f3*&`D5_&e6pU z0oF{wrVQYLwJ?+kHk1ofc%*woWnl3I?Ml5KT9HChOQI18s**T6j}tFfut^EM7t&!c zm96qTWOad57+`LgXavfPW80B@4UR=)k6@pWP7_EH?-*gNDiUE)igk=;yiheWwJNnx zDlru$v1lK*3Q)u-@N-9lc&3Zl1?e-4qF;%>A@nkY zy?7@zBc}X&fKfV6l$NcQQNXDwWu_QL_x{g>a>SYe<2G7Kn`YyrnnA0iZONu>cQ?M} zeCtxubMozKyyjge#gfKF$p?_B(gNUA=-@)enLomRMuGu29)bi6?sQ@;7cz`Hv7G{= zzcc{`tuuKlLf8XWQRRL@2y{xuB3M(&Cp;j<8A1vMKUH6CZIt*xj4*TiFmS6w@;~83 zwoK#UI3adzLf9q2iNC>kbdt{>kRV7*KLl9%u1lB<5vrWB39m#RP#@H8I@#+zBb3KM z6JRnNqGm`XpjfIvMvTj7_;w?ZEOG6KDWi{yprq8G7tWKUfwCw*UCa_uZSnYqI(M>x zF)!f@Bdn7X=-5W+NNilj zj6_Dwv(Cw_!sLCxL1haf3hXM)!mgM?nWW3cVb9~d3F~4HoIB}A(hqsYc^`%IsnJm| z4`227({6%jLsSP|*iO4Uf0^6X{u{vpp=@1fAsLi>TyYOSTxTDbV=izSE$Lokt$ zJt_VZ=KcVf`-9F|)ihn`^VP$bOjSAKCYo0*n{>2OS-!8(MCKFH1Vau8X~L4bHR*1> zQ+a3V?)bZQTWMkH>3;rQw%9beL4|oj)0R=BDEcFu*FKGTO~Vlo1x<_qSs-bstSLvx z;O5qpB6$A^FL)uK%GN&)>G(hT`RoJMQcux**7AXP8T$sUr}iPT;2kS-pju3!%+ggn zD`_*8iiWX_L;iGZk_GeqaNL6FkE@O~cc>toC;PIJU2;JDZYS|O4h=dL{7KF_q^E<= zyz5N%sr%KHkuJu=_~Hndu3%$oC{Rw5&YKrVI!CE(UH$hu=|IV3ulG6C$O%bC&3z~K zXU%p=R-e}gszN;wn@809q*dK21|!z`F$lj0#I7*Ot-lM<6vrKLvX2)v>M=asdYd8h zZYBtY4HVihUS+$D<<4r_M2)GrLc}L(f1hTkK9mS~cN;G7fu3;rh8r7~$~Pp-H(;W= zv1zUh6H`TDs;zyQe>->b_iX;VFwau~)!;en&BEF4l&5r7+>@0qWNczcRgR!$W4c`& zl%wxroyNyn2d%E=F#=)o$$n@v7du$?nLO-d;R0ldRXKo4PIV{C5qN+i8F6UBQpZTg zn6;QW<^VHis{c+gHvncJN-F>qCuv$n*Dpi>( z76jxPX8t$AqNf0>z@p7$PiX(m{WxvvX%rj30*@-^rf#1X%-;S(Z#RGA1n>!r--$EX zj2|QJNyeX;LIr~ikYG>s%1{JEs5s(6XN=cEC(?LGJT(NOmjV8`oRsWI@kLIgs|fOj z?xIaUaoM4+F+@}k$BxAjs6R$QX4^Ur+Ly~blSw`}<8F!388>tZT?w$nHg&YCDL-Nx zp8l|HP?ZdsRaG1Do2b)j13?<+o@r=7^KC+7_?}9=F?4WBvkjC%-}L>wT|6MTQl4m; zx+gDL#~m;eZ`bJ6)%=-!O#S(igQxzynLG@Y(>xiVU@;l6<|a;*kj79tPpFEByUz99 zPu}rV4iilCgaBnw3p1E_2{ljJD9Th>&{ZNf(Rl4f3N*3Sg5zD*Z#Tmn%pLjevu~YB zHh<#n?)m0V%%6G=&e{BL7nSEA{9{DhwMVD(_dvw~nD%Qh%RZBjd$l@e@^jgUfxR>W zW;{6cL31EKxemxmrjsBud0%sAcGj#G34MtY_B=ejp@^8vKCofuLBcf-hMk85M%GA~ zRjx}a2<3-eS6w*mRiV`#qwdlatZ|!|^=d(+Bu*-`{HSV4cBm!gGaFcdKKi#aj@TdK zjLGlM}r_GkJoB(v~cC; zak8yJ^EG}Yx7PboF#h+-`-ws}!>)g5twXRL&G%@T%UXpBXFFAl9-*sGCEruk4&Dda)F7T1-h*=S-0rr*Ee4 z!loSI#ae5j@cx{`vQ}Tt6kKS{k=mp<4}2|2>|xtraq!*Hji8gPd_6WzB)TF7$>l+X z$iR=msQU)e4z})cg6LW+Ia^^MM<{yH5}W3jwsyYiO4km@MOve=5?T?;cXR5 z$5!pAj!&VvD4i#6drarC1u;L=DO}nG@Hhi96_1WZ7332aYKa?>WGI6!6Whj0<_F=> z?P~z+u3F3f%vR>Y1-8br8R&kt)_mZ!>eP zf>eR2%b|`5WnE!rLs;3Ud+zqcZ(n%3X7TiyZyk8{%dN?}=e{2!a`;l!dh1;NdaDw^ zhfp%9Oxq`6LbHcFdg(>0IEBtxr1OvW4Gwl6>PtK5=w7;zt%kD9N+F;UNBG=>xISnQ zMm3;|r=$x`vkv+olsNZN7EU%h4GSHUxcgHa&0+TAQ=9&>u zpU0_Brx4CFg1db7z})zqykwIvRn>57_~!8KyoIXP+5UU(%2$tH#~H!Ez0#Ic!{+bh zJBmxl-frcMOUa@}HTYiX_NCG%lBG}FE3Zy9Zc2IE-gnw7%HOp+%F5p_w3O|jlpa@c z$@eNP1)bl)t)kN0@x`Josp|UchrUzYa(frF;PaBz-EVEiYxWS?21Sj&y6HEa-x$a7 z-y8AkGjs8|nZK-i?rz;;-E%kc?$vm2*WB5>P_rE;r0ZqD3}zf-d{RlEKx?$_LR3Kwd3q#8HOed^BT z-}uZMpZR9>Lf4`DwM}0sey#ZS#J6gF&~z>9dcV|C+iX-X<*8nRF&NMK+XXN;>DfN- z+RlQB40I&y*g#6KI7_6X;{~|0A3iZm^gBBM-*kdmn849b7FW^9Vz!uPOKk7Pn#qK8 zDz)NcEGlm(RLXRYYCt&+5YY@(T7ybGfg8==05bt&WRoCsw~rV^eQV+cg0me+z_^Qn zEiMxWy|EVM4Ky%pjfRo2w3X!_%Xq-S$O5>_>a5ZQE2jIU8QfmxwOtZ*X&nKaiv2Vht2 z>u9a==~ZC1JvW$X62t46U`DqUKPs3hwBGrlfY;WCfR`#}(&`U5QivKW)XoorAT80u zAV`bzv*;M*GG%%k9h=e29|g%dpBqq2uz>ToV4wK-GYjBMf|&Gw{%*1_q5uMy5lsOhWyXRfv>cby72qImw{i7v^*BI*5t~4=fD#WQ3|4`G%hwDXcil$Cm1*xS5g%m@ZX=5Qf^pB{2 zNyY=l&aG3;uY_I;EqJ!hyS55or5Rd#^x66#e6;m?u0=o$hlA8b0NEyhV2dmum<(uZ z%YpFmD9nem`E}U#VbM5Q6X8i$KTwj{--bOPeV*aykSeQoNQ5m=eL-u2K~Tc~302q3 z;CMKuUyrFM=+?}o1u;Zf%U7)*-=Y3%Lv~`y=85NpFT9W{ul~Z3RGF7dK2~Des=VTh zhselvrE285aed}Of`lNvkk|-^*p%Ty{vV-`Re)2doA;3t)uyaW28jNG8cV`HSXhU&z2-)I?%bWe1<#Im zJp1m-^R9giExh>1m}b#^kFtI6hBZ;L7cytqXj6ihz>)7oU30EvSmXJS1}v*reR|M+ z)HqY5-kkI_&%2sMO^M0gn4v)xnleusH*Y`@)cDh zHt7ecT23}g*Vr@am2oOVW4`p@zh2dUo06VQ^R7*zk~CNTAeE%_s{pZ9tHr85+-L^N zwPO7j>c^XUKN6ArL8_RO$a(~k*SjgvkWn)xyn5jKs1QrWw6*ih^_h8B1NR`dVd!ah z3%eA*PKe1{M?_M@P8hqGbz>JVOW7q;lrP~08x_AzZW0A5zk}CR5R+0meOe->i(Pes^9xtdKO(!YTVw5j0hoL;g`g3|w&JT)(;5(|Eg#`MX zmg*NVu-K{kD~iS~&rF{%uF@FFd6h;+NAThJU)4%fxJC};|0NGLbi^%W*A@7|7c|fnfr`LPzN1;}F71OJlUJdl(1q}S8*>ZTXz#VNh?>Z2E__$Wu|MY;+KSxZq)(rb`j&(e$bommA# zFb$XJlV|7zxp+dnN-mytUL+S2_m|1VGOt;3(U!9EMRNT#y>8I!OZ56VdR?GUTEGdR zGm{K@5lqI`qu)PgdDoWjbS>9gnm1iLJo}ji$3_VM%c~b0RrlR>3ywNyJ}o#lq^esN z9Ia+IVpY~%gZTf^vn|zhdfATO`vv7IPW&$KvE-G!XRCB>Sh2&k zOs;o3EEOAXAHRFxn~yJ)AH8<;+tsb}ZBNYaJO1|Nh3e<7op|42b#7eAb2vA>>$Ys$ z{pRIshvthr793Qw#+J7aE!*>*8(|_{{BAkSzxNBOSDf&N`3)-2<*ZW+gbTU=_3KjA z4XN#WmJ4c}r>*xZs+XPQK#rxA%lYgCbKNC^(b~e|l_K`tVe!;lJM?W_&i2egQRB7V z6-Sk`@?D>$qVvwVw+7xmv`{{D?dXcb~vYmIz%ukjg6op_H|nd8&-zPc0?Z_fjvdlYX9I@ z&4^r}C5_7kaT9c`Nev#6rch*N)wH7Qbh+ zIh$2N1{d-r;%0Mh()~6qyGv1Dx1|iINiJA#Xj=A=3ntb!Etiq2oTx+vxhkm=RphFs z7S@n!hh<&kvgc{5a|d?`In<`GQ;an`1u0;s+fv!ST+GfAY9gmck;onwU?7KbYGegF zpRsYZ^PKf+wc$ck(Ucu}Q+BA$bLsKmLXFpoSD?p(3+jV*DJpNU5rcFjrF%%7o1yYcv>iE>oU1MC}_THfe3>JW_J9nFLCQr)oJU6Xj~>8P9}`o-$o{U;19T5b5L&0W?yS&@N55-$_2Ffq zJcW&8QKc3&mlh#9^;MgYP)hb9`B}I0dA2JB>;LeUB&29W@KmzmhBwVxwh+pr~ z?q!b1m%UkLMoi*u9+;`fWN_>vEQP@uP^&=GeiEqfu0k+hX)S%U z4Z!w|aRD7{rn7Py>^S?O`*7LsC%da$q8{eG93=~)bc2MR)p=YhgG^vsO@h_rNHo&f zJ=k;jFib?_0*f(d44CdA@5ds479A>N5u@ZfK`(u^26^)sdECG&ZJmnI_@Lcl9YOIE zHQ9ZvR<;O06(fByh+T1~Z1oKp*3*lc@0C{2)%0^cx2qOPTd#M2$M{}sdupNdX~>-` zYGVtAI-@ZuEYsU{)7=X4DOkB zeyb-MxgAbwN4I*4^|=69ph>$pfLw0bFCD+M{R4 zTRjudgkdrVjS*ETR@8jCMdnt8KK?>P@W*Hg>GN1r1ShFfqB^_3M77(fpGek%p)AL8 zSG#0HpBoV5z#k7EDPFFvX=a`;a_gPVuu(pQQI1(p0^i*Ae|vgL7?@NkGVUOYPE81d zd}Nvp7kt5>iY8g^z(`yqavY2sy&wmqX})m>_XtelDgklqLrm@waho`3FfRYrO>dc| z6cwHI5=ixCM3-c1wgPd(7;Ss0b%Z5Jssqkn=#{|0iH&WVT0nVVGsdX3iFQM;kVR>~ zf&o+R;HB;jvM^ow*XWfD>`c2woBWs`rRmjZY7X5=V@tA9jBN?TKucvCl4Toi_ugq= zDBA^dr{cQrIoKH4a9jG7i(kE%TthFDhKd1z#_g76+KNfqgQ^Y&2|ZTLxkT`Yd`(r0urE>60)EL+5656(g>@ zp>1pMDg>u6xM~LY+^tEpcW38Dx1H0#;#zxgkT4)@sJ>xUo7}q(zIQ&Do`%QMJ})jj+^8j zdcVO{X9P8d&G2HqZ2iJl$#$_9eTP%hLQ6qcS+)oM7DYe*ao(Q}l8KWXm}%rdOc2T} zu%Q`F$3^X2h7RY9jM@#oZS6!}!6|9eCDd|wp+kTcpnw>*lK`4}aykUkNy2`xvDnu0 zcAq?q3qq7=3>;dPZnhap!F%E2HX^v@JEbXwAi^K!UTIZdV|Dh#5|QcMN4rw`u(*R; zZyC{$?4ArVwNejNW7&y?rFPjg-FOccE+e_FDPj+jYv2^gw4WJXUIWnqRGc2UMEA&MA1mk0sns(p9bnP!om_6>G;i80 z?lN3>i^~m?MP6v9RMjq3ZckQjpY40U+)@Eml`n0<1qnr^^F{0E0;)}~S1x*ROr!qx zresAc%!#MUYHvG}Wt;AoR^JB;=KOY1X{vtxSGK;k^%py@AH84S#Mi;jzOYc#Fc)~I zXnm@@alzfVY`3_*-{;!D)V;lXXQoyUkt>i->q-k8YcXxw(wi4mv|T00OvV6>(p`#l z2|13^f@IJvjrA0c;>3aBCJf@q9HBasjD;2WT{R5}IOtL|*f<>x;-Jtpn+nwj+{8%7 zMuh!u@*3f(I2aMk7!eEnzkEIj`^*~BL*GHq#Z)nxy>Ut{2&zOhh-i+ft~s<cRcHPsK0CbNX_!AHl2lhXKbXC~R>{)PB(iVi~UU8H- z%ij08oZgj6t8*R1*d*+AVP8%Nh2eU?(go?XkSZ7G0dSE7x$yI6Up)Js&FMUXJDefY zU1ld%z>O{6+`4q|O!DBFW&1W~6YoCK@0O?dn|B}ay)0R|!~%7{^IaQUg3&?c^#@o> zk9M%!U*%~n3FC*)S(GFBDB7O z>3gxvqN!Y&3dx#feGS#=X0K5|CSAM6f)&0_nQ@kl+am|8%^)QMBd!8ICay8Twlmj& z3yerI(>Br*W#J`{5~?Ld!)=$8`k+*%TQ>C25_wa@kKCDu5kgK z+C2a|86!3V8fN3cE40XrO^w54CSHOQ(uP*~;Ve)g#L|VL8ZV-YH-$JXqr#>ovJj*3 zoIw$l;KT&!h*F#B8gF@g9FPVsi^Nw#7?P0_Ps%2tnYrmAy124eKvajYIi0gdwO#~B znM)8oN@Ia#CW%$3!|73e6XU3@Vu(s+tYU~rCDyM-DxZ1H{R>3cNjnOJz1HHcnlJLQ zF*Gu#J{Q0J{Gz){TXzpZ8}xSXuN?jA(WIwq-qj^Yo2ui*H2UXJqCumf@pKp&E93N< zpx1eNWzkqBrCF5n_b4BF-JseLL!ePgY&&YyF;!lv(#-FHPHq#mp+sYduRl6*BDul` zY!*4y&7wToESk=5ccq=od?rqT3ib37ipKy6G_CJHACFJQ_I7ni@+IHpoxZ3t(RDr^ z4(;wD?C3n!(-oTr_jtueo*Tv_(1T7jZS25^-5)B)NS;7le(=Ajrg49+m5sM%Ns>UHKxjI$hGLG5xqrmKgQmwI;lj*aQy%% z#$nu0sj}UPrf%=xA;_*E3{ykRT)FRoZU0k7A3U(CJ)ry>YE4!P-zGnLecjx`w)^GP zqJ`C|at4n@N0n$H#r+stSPL0k?nWN&j(A5%LYKRh2Ebgtd|3mSq0?Qb`+7RBghO2$ z034l@K>`is-%%r(ry-ztV0-FeJ@O|MnO@&8_sF2RN4Rem9o3>oDDKDDBl+q?nD`=f zz%xVW0kF+9OBzjnG#nAB2s>yN;l5mz(?dE>jVrLrvA?;q)9Ay5y|eRSo%m&1Nr*nYu< zR=96??fQe4@~W#vof(*%8Vv=r_G$b-^h540p-# z2%!m?cm2ZXa#r$0ZLfeuUv@~65VZ+eLmFLAXN+P?H9M0vJMZ?swfURv3pK|UJjdr< z$C>bFz%Ril{;Vsf;h+_VdRPi}G9gi}gb_cSJ|pu=eDk7X#{Qy<4Ey1hM#IlB2oqB5 zkMK6OCa7Ig&`i4!t8noldF*x6l4xg;l^qJrLGM@yOognn3(Dp&?gDE_vD#_#}4;+ zTQD~s_6|NjIMjEXznC|{UC%7HBUym*=YRrbiC!cL$-3o5`4$2aT04Df!ODFa z(qSYAKMqB=s-G#Gv&}kjx#@gSBd$8S@u}P6$*PW|y8}0pdTQrA8&joKb2Yc0NY-^E zOFM2jN!P7v*1hbsl+?@@w}>RcWK~zv-9(} zvrqi)dxn4S7r5VZ!e31U*K&)cV!dDtnz9)Ksve=c{@|M)E1#`1W<}Cgo3^#v(}jca zX~-(h%W^#N*O<0e$vYG>E)^rvhNUKc@e#m&Eemp!KK&#jlor3q8NOFfV@6bujUQHzV2i^ z@!m)4QBHh-+sYFWx|BaYQnzwuYxnDsz@I3 zrGw~U@GYG00lxH7?{J!teYCpvU53ul~#%8|Qcg}jV8h3Qsx*M#@;u}GqwoV9!Ruc&wFRi4?qHJzDkLE80r3!2bIHXD_aaYm8PO65>&MpUBLY13bVi8yaS3ZXp!d0NVirD3X zUoE@p;Hqa=16=FaRSs8~9?#9L68IIfs}wE|xoj3WPilmUc$2n9Vv9r8G%br0wuoFHK83@arwGNC{)yr5B`~ zh}E3sJ0tCaZ;NzQ+Kn_Dq|Zo?;di6-6Vl`O-6UO;_TYCj{GY&YtMsC@7r$-j&3*W7 zmtK%;Fs z{B}v7mwNEKP2P6JI=p>&hrAQH_DX%@tArV7)2!5wymmn(u@iA@IpbWH4k6BNo8^#2 zdgf(|bXa~&hpETW?~iL++{1e^zMjbV+MDsU&*)F-3(^tfzdu)7$xr&CbQJA*GCN#) zMLGum1JX}PKP??c4o`9HSB-em4QT-WPm9)#+l>&8c~d%p(C#%te?~fq(1WP8TRLUH z75b@FI=w2dFG+(hJN16((Z(}Ze{$JBD-9v{UgX{t} z&gXe)*o5sk^Mkz4!q3S2FtGQU^hpz59ATexCZD71^C^?hF=MQ>9+ZAw@}u12+?HFK zukkC*Nh1g!Kwhs&0aIQlxIagY{zQGoOyMUvT*?TSP2s0FeB2a%Rhlq`pT_d!7x+wn z;13GG+-0hw(jtSE5U_;D!hF?Hln!V|MX_LEV@J51f#+-eLUPi&QuW*s5v-shgO`MK zC3ZeIi8(*&6-H?&XVv1;5A}o#D{n-_p7JV&i4V$*j1WKS^FAM)BE3Rx4)|B-%Enn* zC-gr=7SJjQk{#a=EIN=r3Tx4mCL+}H>3(Kq+B+4&noo4fbaV>*jkecH>pXPEG~!;? zPU@gLVCY3yg4fwg@9`+E5sr>?P1I!}c&4c_vU051EQXF6vL;27h^mK75*W?!&&ZG= z5*bnR36RD=l|`$~fQg&sa8>@sbrCzc8CI+`bz=-?)|!=5@EIjQO;9wPSQgQ3#*Qrm zl3?!CvPOl-Mo1YmY7BmoD#;=xbP-2n7F-;KqU_Z?a?3nvJk715Sh2~#m?|DUbNaC0 z=>g%0if*9|9zBv~tUn_Qu@5flD%^(r^HKBQ>+WfnoNOGEz!Bg=Lb5m(T7V|mE7ZU; z%Vj22>m$-cLWj^utD-h^KLAT_4)?mxdmQ>s#&IBmp^@CfDXwG5EK$AKQ7zMC>;Yxd zsSwlc1wrfxNrWW;YhgN)yPXC|gEW>9XAej)=7#`puNR7oL&}t_9*)9rU@bvoLGisO zP;cdOFqRRl=dZ2aGwL3TPAOwDPGG4cO)hU_3IYs;Y(xQLwCZpxw8bj$*Z^FShY3GS z;3mQ*qfiBmkLq;P&g#4qjpH&exvzXak zMX6)wqf;T+`ZDy+bmSDG*!_srb-+ix+#d+({g{!~KxoquAix%-J+Qxv-kFu7EpLAa z;vv5dx2&kT224X6mUT@9XsdPBI|1uPrXMUhrc5(bbfD-55SaF|#yDDg*-Pg1=un10 z+>DAbSyC>^eyHU^JB_g2kJ_Vd1BCsIA^23Qqs>uzP1MdjAGpK<<{-g~mJg|K#2`~c zuWD5y;!7v+rdS106L{#k<*cDeD^QaX(@qp>$fpNU8f_DT?y+fmEsItYWU@d;pI=F} zP>5J#;#>kDzj_KN27;~V)fq7%u}@Q&#-UL3E>RLj3pAT5L;Ykd(1Gm;)$=j60Ie6N zVOaQ&?j(VaLT2(!8p3+Q)w0hvRkKSiOQ>5x83WKY;%#FM3O%)^V1Y<#RfQg?q5i2! zpP%aX&9Sw)ZaKSM?@4fj5NV78ST|mstP>l9#CIQAK-F;BdT0zGKzko z!9aKFWKUHWAk2^G4bjGw5#Izpbfgm?4a5gFi)oJpaM)gp>S?KqnF%0qE%r=8U_)?y zjw*y15E_###`j|#$hPT)i6mmU(}e~(QplzewyBs@f^MZNa}k_$6)U%7WBP+e-OLi( zwnCLUyfDGfnx5y*rO9p?qe?a!J}B1{>e17+CVFGlj_D*|)}vI+6kfC8h7He5AyT-s;F%(P zfjt*bq~u|tGq!8hGX+Y1yi$vQwJeesuQtAn`$?{rM`}@%dM(WOy;=tUb;h^mx>`O1 z#YMkf_nEwF#kgswOk2t!?Eh=;UBKJA?mIy|Nss^ukOWEa4ZaDAq$G=aSWi=;Wa~xS z68(rBm8JwrqAXGJ1!Y?_70YR+g%V{64%5R zz-a74K0!6Y^rN&OzSR_=2Ekm{`^k7aU7(Ryvhp9kU&+%2`TUP)b%gOvhzkopDixRg zlbu>Q)BZ`F(4v(G^%;L&cEA5!mCSP4KkY}Y^N@6=D@a(n29FLH@p81cTPw-KYMIvI1o7(JQf8}zdUd9&p~$UX(&}?^^xVw&YW!Vn4KnMADU_(Ixi7=ijL{p zqT=)iyab01?k;`%Lcz30;6RG>A*0M9H|0O`CYa9zU}?9II}k`sM7kX*j{y3Q0X$EP zjYtGHqWl$Rr}7_p`!#+Zjmdl?i@ehM$rZhPq1x( zP37AVRLzyN6WGhSh;-B9AR?!HkEOrI+qZe6DF|r?;ICQ1AM*CUGk-q>?ME(N7{S&J zmg6K0Cu5^amr1-}gm{{8_YzUQjntt^!In=K$R0}jc&hNULS85OqTDBd-kUMfv5vk z3u;>MQ<|!4zg@RxzC7w!a0OCT^@wwS0LPG<7wb0OhCL%sRov4uHy-cUw$#`a9lZ8v zs-Yt~_~jw<)3qTK>ZyqC`oLRxx8;FZ?}sfLX1sUdkj2xn)Y!h*xHZwZHTq~Ov~DqU zFcCT!_jIJX2U%k0lG_*E@j*>jvZfok9$4~L#l0`yf8N0qPd zpWPq32#ZFIgKuT zcZL_LyHoWId^>M_V<=`#wY5W`>A>uP*bD#UaHbH+@0HRQW<%RszjEVOM9Ugl(axdN znqKrpNy_DUz4&VJ%%<3u1y>uasj-8W+~v_-C^oc%UEH1u?c{Gqs%MbDA@O_16M~4v z+D(gnk0tsZWBi(wr()65mGE@U`xiWYc#96{8ccKzerGt@bwFeV4UO*gi=lmq5Ny^V zOBB-Ezu0pq(Q`;-y#&?fOII(&9$u{9n82TRBT_u@;NtoNiS-BG@Ba@Ee(%A=`X}P+ zo}6*q@%1jP>t9?qlvp<;o}@U3fo~D9eKzY9f9#l&;Vj4953&SAFzen`&2_2cilP>o*fp0%eNsHR4%GajtrzlmFUoI}MX1%rnU@Lx2-HM%; z3#OfhZtEEx`9Yo33p%u)qRk4&Vj*n)x-P5sC4jOuY<CW2w5kB^fNlTVoF=6 z)el>kxla04WTb_wIP0|&(6P;vkKu~VXxDV1RtKYuYrhHyAuAcc<8|e z|JJ4I`giP$!Oe-_=G)bqkwZ<(VxTJ#=z7op-ii2zJ;~7Eoxt8q9m|9W6NSE{oF6(= zzc?qceyz(F#Cpwdt0s)ukM)`N$dk|VMSc_rv3XV{VvF_K=mErf^ankFSRH-TBY`lT z$+NN$TW+M$LWtE5Hd-7}t}{9sofS(P1vwX>fLe#k*03EA2w(uZ_XZLP`%se&+DFjG z(xHaNa{`p9!-|D@n2=-CgKp2V428)iUAY`bFp`5wej2nT zG6SHSBp|if=ocrqpbr2fa21~%SHK^D81My+=%7OnmFghN1^Yo~XfO{|B9as|&^v?Y zUlP`#bYox|pb*wF1RWFlL;`$}Mq;Lrt_B`MSjL}@WGR1(Zi7^R2WM06A-i-T@JHfn!l1uqv&4l-pLQ@h!fg(Xmyp4Z_^A>?1|7Qn4Z*_O zNCdFpvy|0+)iE>tm15{h$-me4U)_(;>qA$E_ye~a{5f#-KnmXN;Cnb#U3dM}*;nB_ z@A|~-1l-syHg8QdZxwK4d!l7~sy(#WzB|#r+Xz(GEmn6XsykO2yk*5vXC`Q=+)N({ zo1%kvJry&1WBu<`&->>mlg<5iJR39cn6PO{m+vH8)i1V9fPo_j1S@zoI6Bb@S zU$!cxLfH`XlH4n7yGSv1`{>)qW*- z<}9SO1*(vf;wU;s(#UxPA%*;<2npSSpa=r2$j`)BL&H^CYu?dNX^9xGixJ3Xq6or_ z6QdEM8IY|OGNn3?L!%6k;NDH_avsYJiEQFrAjl)M^e z;4&B0xrxBf1uQlrJL@IdxIvwAFNsmZPpv`tv>KSNhW9FPhI!PIl}5)Z^fVq2X!Bqd zM=g+7aEv~U!uJ^FT}V}d**F+*z`hBdhM2X4Jg`zIi3b`lj=)QwPvnt+^MPZ~MPVun za~(VdOiSU29ecJ3=;-Ft#F{`F@v*w%)uMz|CIQ%hRgdb$1Xpo9#0mko4F;hmRJssy z6cABXSMcew>Z~X01kjv2q$OhhP;hwtr~kNFoBUMqJ?P( z=>g;WcvRK0aZF(^WhrL!^;9v}q#V&60+K_B1R!a&c)Zcc*Dqha3c`m2J7O%?nZIe30Px zX@_^K#qih;htm4quP?$9EJC0}xfe{Y78t4F#L9A}C^roSDyOl~-zDV3rTtokrM9V^ zM2ZY6Vg9);>X?s5M zh{lhB@v$=WmAIzO#>cw2*>kAJIfEJEarNV#fSWGrj~^*qZVM?l!i} zZA~`zMISZHfu$;1=3x$O?UKJfRaO-*YnglX)>xu*&yp|jf!7cI!(!c|E(17W$2tWF zHEjc|!rBK(*`D7-PF{|zb=sjpqjxbVyl|!k;Y%pETCa7hL{{7A@8b3T3CJeka0XP0 zCq^POq_CQ#V}QfqPert{HYF2YILw{urSl4G0!7BpjYH9hr>ygkNxVcf{`A)8xD2s4 zSQ;>{v6oMbU6>52^cdnFh}Wm2RCNN@s%qAtd{*&97A6X!5R49LQf5;63~awKW&DI5 zt0I${R9Nu*i4zwujGM%|FxSMP61B(f3w%{>!Ya1+oF+Uf=}YVwv)qswmD7YTxzDO! z%PM8{BziUq)>GC=odp8EdLDwVR{yVAf4krxgQjG#M}U3O zbho&W|0jH_)dYu3Lo&h^c53m;5X#O&^nGo2{&>;LZ75SG|7!IBQQ7Dl2e2FK^Mw2b zfG7o1DEqQ?0t)kpC6)r1bqa@Cl%W%jjeImbhZHur9?)^8FwCwZH@nEe8|FKs2l=G; z!^A`Rdqva*I2;*S$jh0P1JwKTNu`XKaIJh&GGU$hWv&783K}iaLa#weDF2(03M~!Z zw`*bJH(VHYy;r1-+U0`DkoIn}TMHRdKVS|1%roTq&tg0VL~j}`wOlSlZ@Z>lS6ZeE zUkgqbo@voaF@EvBFyGt(v(WXLb;60S?fBYyEr@62HC--wB^DuSes z%`_6WeDzU#H&0DX^Q6dJDp;Q#Mtign@+rvw#+YIGYnz{uYA{4Fqs6=r6%S1{?vaL= zB?t}j%nyK0Muwp3O$D>xOJb);0Db}yNI|+&no(=%{FBgr-!S048xT^si40XqVHk1h z6P)gTq)FS4NBR}^l0rbP{DjHL^G@4A))8n~x)2l#!5R1#Q{3b2Bi??Ox8LE7Se5kS zN1B+@$lEt@gH;1XL~!vp^Tv|WC90q(cA@at%jr_cI=(o5{$fOKg6V2~4~mR{&pxTi zZi|+s{n*0EmWA()mnTP5hv?~I@gzwJJeP?L%Ct*0pztX-&&ul7_d2(!X~bT!q}+ZQ za;2=uj%4}HI5s4=KjuiNal4Y`55+wX@jN^JPQ`+|{k=1{YX11qg}&jtfzJ7&WZ;45 z{=am!i}!O43+}bxiu#*C?A$iHE%tJ}V$XYR^OqLa4kXqNB)fOtuGkaz>=6jxI~8-o zUqANtv1IdxWJQ0}b=O@!^I+`sg1d8m|6(Xb^t zlnQ~R%M_b-MfWdyIw0V(;MsuK#n2;(&?E0xCPRg-+Y+?wdz8uzuOYMS0^xY00EkgDj6S8Q1F z!y6ZzREeaC4SV4@%hwk7u1#$|825GF@%3Yo|&RWUq`~%vEbXB+OQ+;XVCBD%T`F`x(z%f ztnanJeXRMN|7iGwpm6ZqkaJDj-qYz7z+iNm6kr?IQ_e+}c&$#C!imFA>IlltCp==p zfx!H&!byTWF~`&k1|5qOD-+%dMGv_15!_Xcw6z-dC8mt;q(WH_-4Rfo4#M655UL`N zrV*z>gQ2Nm6_Bd3csL|$$A#5J3Yl|x7*LNCg3X3wxK;w-FnvlXKScMyxV3rYm60T&1D&2!Z=7l?Wm zT-|po8)D(N&fPfoje&S$U$Sy7*{6LlgF}c>pYU+LUcBRhl^8@r21|7&qV%DrSu7en zOVqptflniy!ZA!aJ^*iq`K;p2RH$R~6sEu)^&~P?P0*d^#ZTEAMD+yi(dU2tm8-9O z>2lm9eWPU^mi47|EGkTV95Zq+Z5bK9QNmUtC795*sefLqO|${fCCC^h2TYLqaf5VP1|vB|eC-?$87#(X5{-Eeat;oTH>ZIbYf z}Y*rNMbBF-aC7bzcKva2YU*kN> zDJ(97H*ncTs?V!7z~B~@>Z70SwA4bxCts{X>p$%m@VO1}S%}k(UPpDbiEJkIXezw- znZ)`c5Nss#L(1$V`b;gT6 zS*^a{6Hrm(v&@b3qDdIE?o)PRnkXdLgglZoOZN=MK|oq=7YBwtOgV^K+KtSVr$&_t zaF!%rubl4$3rSjhgEumabJ~TwkcU_N%=H1lf?T_Aq)15sBWvoyx{3TYvJ*!8;Gr)3 z=AH$2@NRV-=thTc98OkuUwwp3J;$4`ytgObxNf0jJ$y8jRK9-r>fw~{*}J|vcsl-Z zp`)a91ujf$V{Px)7rbrnJ#)+P`_C`*9=KcGF*lj4?wN6b(mV5_me=Wpl1^k3sE-YP zWh(l}QhO&{JXF+iN9>L6febT6mw=USyRmI9lB`>E$J4`Yv6l#Xb+mLfs3Xw8f9oFkxmtH#hf@hHmdY;T2diL?0bRw>z8LQzx{Z;y7ME8qo^hN@CV*N%2&PU zYfku@@Az7meAU;zv)((t=6gkWzZ%mg4lbt06|4zCySJL)e_rmS2Bk4w=2gLO8+elX zWSF++5g74-51?c7>RiE(FDJL@&J$X*G(xLc~iu2GSTT-T3gLDO6+^z zbY#&~wKk)#C%7~X8mm#u`}F|ZuGJ6Yqf=);{Y#_o^zT7EJ(FkeHpb7uWuRN>VBc$X z2UXL4hLy>=3_da1eF4A%Ru-rJ?&vv~wLKlAu&TgKRn$8VumF4W{Mm6RumfZW1|kjb zne~0inVUG3BMnEk4FruKGL7J?xX0dD}pVPLU_m!Ca<{&|&OMW33mRI9%d z43eQxiL#8|l8_?G5O+g(F%g|3C0hC!{ar#4?srNLR*WQheZ>+!U8Vimg*ri(Oj7g5SKLK+)B0i+37%Kg!TyAXdD=d`51=Oc@^sQKz(bRhZy znT^eG-|B5%@|9h8&APr?45zGL-4k=XRdS;w>F<~?OZdBQd%LkmmDT7%GIPy0#uC1^ zD4e|3#@4@i{*JHjuD>z%!aHm4_#e0%Xqj8T(6QxC;6YOmj*O&$%^hDb(}W7FbXm%4 zV;#w|=8r7SqQ>aJU7!D}Bk($S?(K8H{yR1$eVcP4Z&`n5Z=z#s(zgx1WIZJm2)=gk zuCHm%IydmPGwJJ)(cER%L!s-Q8~J|1u6i8(oOOWsM9_t04AO*9TLs9(La_?n6Zf?3 z1bX_Y1&dz?qh?kTc2NlTTK0ibDOQD`SaRa#rHU9nXspRlp~7UIfw(;6Z< zL?w6##S^g>@{l?NU0H6oBI6TW1l#a2us|PlJLcNH-urfMGO&)U#G0#*VE$i(wcc3a zZEsVmI`B_i)kf%DeHYqlgyAB?*ml(Pq$tbREV5}PjZ+56#S`S34VDAzzT&idBT zHq446LI_cw^2InySUDE#e17awCk`C|gTfw->}pV>sDfm&CqXzXKa@lQrt4ItN;*~l zT$+DO)uP6z!SL4eUp>+&Uow*QG~}xb=!Y_lkyPmmYLQ#T89~emSu1I!!_*K=T8^_Y zPGIr?$a$^V6H!lnjN%2lLXgnU4$)E#;d&jNFC;^<5w3>_2Mam1koE${pL-X8U=_&> zQ&*>6|J>Ej#ZJs^PI}kGU28sJbSa^BKPr@YBnb(w(3g;Tj^JBf+6D_j3P+a2Z9XIm z!WMbbp$YQRW=_Ospjrlr!e9}jK6&dx9YK9l7xlpm+=_1H;W0vKcSu{H)4D=ZVR4%vqI+FUJ6k=<7`! zdZ((?*_;!9nUnivd@go)sL)~Wj#b1?aTA0sbLa+xKeJe~B>_lQvo(4E-hO?xaaYYs ziKR3EVb;lo60kZN@q!0jz9_U{2OoRq=t4#4ZlM0nqjT-aK-Y{@&*oP9t?FdW02mv9 zkFJ{4`zrcELPjuC8+9^v z!LKZV!8cUDvg}(ktugHar%`m3)cV$*zRK<*{(i->%QAAKHRk>Kha7RYwjjG`&Bl|n6>=0*dRB2MEL8Fd^{yM1*7b8c4Rhi6`SWLuxgek3W!(t$35Hbt0gkzL>Eqvm z7%XVY_G|AL5%wi9vJ+Ub0s(j?&D<>!nvq zXCkq|JL(D$H1QLp&}kPwvAEgp2N1YU{fzsJEk+$w7)X;9oGgGHtHO7z|Cp-I)~UHY zlE$j8ZK2;h8axSu1hmwmt#u8V)5slWbz!(T4%2BdT)0RANMCR-^e{2_U7e$yA$?mg z_$us1_Lx`{hVGV>Lnn(}JM3`+VdXxL<)s-C5W2+Nt)(>sqSQ)=kL|oQ&$P#C=Jw6+y}9k4-R3J!?S4f3W^l$UUJZ+MlIe>m zJ!@~*v16#@4x)OGgWzXgnkbr=At<3dMB%}(qn4yS{p6pI#Ta&)gduG26=+xlJ^C0d zz;NMvE`v>o$&ptOLi_fzePR$b^vYV9@8KdXO{5w%EGDrv!V^lq{Pb2Mzj{LrBn*RR zXSfCDTyI#z&frgng!^jy=V8;0b6S-t+K%2;%G&B@w>{Pk4mnk@F zyNLbmXpxCqLdwIOLL{sW{ow!lyTALpscU`hB1tGREHi^*G1Tj*226B+EGTnn(NeX9 zboLc_c%&@Cq6T$z1;32vTpk7pFu?XhmYjy525R4hpoiGcRN8k{1K9+UF7_8aVdM45vHR>8DoR@@vVdX0W*S=wA(CFJ;DUD zyb<+QXo^AfjV2~iAiGVn(%6v-jmu;UiYSNhl?Lc=4q>%MM!v^o_YJ%O4F#5pywMlG zv@KTl#a*!%-+J}NtMeBZnl>&~H^ffFl$lqekKBcDHaKV*o26{TcDKAL_Q*nc`#rn0 ztm8vp3pr{$3YUcKfW zs6JM*by>5hL&_brXwA%$JfZ^;=-C?UnrmI#e1IP6>mBjB+Jo{$R=gn;y&tQIVhcGJ z)^DEJ=QpFv*Wn9veeQ)X^2CZSstvk;VFJz+r>}ITrVg=*=x@mc88s#gJd+bot zYZzFt%cMmMv!oCM6K2hy>l@xDZIOu`NMMvM6L-2DIEm>!*PTIg)E16YWF?93F34I* z=}=B6oY_^hzhGo!>;-IBLfce^m$+))Mk;ZF!5+2o>JI3bO3j{%1#dglNI!(BFlX$= z1z*SAirU!5xz2@(ZW-!csOY6bU|Or%`__RQ2X1>i_zdz@?1{IYz47dAZo$LqBD4Z{+yw$OdZ|%IXbG|uI*OT=2d{A9aLT7_GTdiI# zMAgJ`B@+pe4zL>QI=55N6xq#d-pe6o`ZDtv>1IO+C?{ zL*@W=@Q>NQ@-&ZD_ye(xvpep0n%CRYqP8cWO4GY|$4j7DO-CpVqHu1a zO@bIHRgon5s4rwq7mx*wGhoB<3)Xhd$k20^LYXuo0!!K0 zABAsl0VwDZNh6SJ#wU!qg?u!>>0%?NDXAC(;+}8V107?m6HU=di<$ zDbGEJ1#tq4h8!Ep7!|V)>eVT}>XZtVu!Rra$e41DYN%)_>_8%;A2y$d;#r&EPVvLSApWN8sldT10~4B%nwC_4FagzQ+iv_P3Tz6 zqtT$r^}8-!D^Mww!vtv0z7sNG**djiLx9JJFqpDLzhpO=OpK_df(iqh%aCaV0g6HF zCKF*wppc0LwC@zOcIixPG^;~`ovRjFr)s7}Az>a8lV%~x=@av7 z>^Y$+%jF_7(apiD4HT32IZ@55y!0w#VF)i526O~t@3Bjhr_WCa_8F!KEk1-VW{-@? z1L1l22D>0W5Kh}RtUWt^T!B}EwS-fe-!M^wUQsIGoA4W^O*Ify&jM7Y3uKEl_A@Y1 zxvJA1^MX+R01yUg#TY2xBr-`%MrJ0J`d&b8s!SHM7=vdVOQaKtuqSS^l$6naQ_M4W z`esqmvo&f3spj>Uuf7~}&2=Qbp|~p~cP29sB<3T4U=(*D?&36&`|Oj1^y1R+v`87S zD02?#djLrld{W>%Ol%OIjA)GvicXd@=0m&og)ZheXqmAdQ&fDYkSa?C7bc&WyXmb* z&CK+3(griQ?S|r>k=igTOtq=}q9@aK*i>}r0KaHrB&#-g&TnXG&)=gor@6Fg>ua6p zJxv*}*_5v?c$(9SYE#p-o;Ah-s#FSmkG*WYTzuI*;RwTHE<;&u(gkLXoY1Du>4M0o z^kP0C7H!v$6oye!*om@SmkTE9vr5e0i^WtwL&@>hJu<>iMg0Zoe`>Q*ydq^-2JXPw~_i&W}y(cqOxOwRK^Bs z&}8(W7Mj*62Ug7TYZo1saN(I|?XB@^2>$?qaE%uH90%FMx*A~4LAOZA;Qmeyje&WYcO5el#>1CD=a@Jf3B#^|fdZirSVK1$I^E_x;91}T zEmRzbt~^O3s!$epUm;AQRZg>jHX%21P$|v1@We1SMlA!NdE&cKL4+}|Hp*nd4Fkv* z(jc`wHjHOs3`7_-WKiSdO1_l3brHdWVE`c`7VHvk(1A&1AzIr(4ILHEP$6fdZHd1) zdZTB-tg=uYfeCP{|1|W5oTO3M6_>-SJ(?zR{e$0oo3|eB_Jepu|?cgPA{|VreUE&I)npKA*Avs*}YH5 z#3`=;c!bL2>6;*2`PaNTuwzSWPK880D)t_JZ1^*I4Aa8qx|~1sBBK=WDFXyolyo z6TJr$o+EKq6kW{p6!T3xMXGd(3a_NYB^^f+QiT!j_u5?Iuf&UpWl6k9_IxApqQ63( zz>E5Ys2&Jykg5y4^O*&x8Pa^n+C*S2(4@fD=>8>lb*w+(ZUQkadI-uhjV;gtTxx7t zY+RRUTz4~&Y}~qR*$L^sq3GV3&5&+-vtqGk9rO`@uXXW({fP(m#{&lv-UD}Q8{dq~ zJ)ErVnJG*Knid0V5`i`Go*lO?#g9B053ETBo|<*S=E$3^i?wSL_$yocNuN9=K6x6# z0u@d1iZv;JaBd*sZ=XH%AV129T<`9qOx1Z8M%!J3OhfFP@}FMi43U}I+J7lxkK{d|{yEcDh!h9Sy2tUyFU ziHx4z3x4F})GIjpXh*rAv_eF3gYL$hta&CB=SBcYXr*9c8^z5 zq1na|b-<9<<#M_rPc@a-FyX(%Nlv_){;(ZI(u}h5dAwPrU)Rd6u;Gm~*#*@kkTu}c z1$KUc4~eeIzESxJG)h1eVDmQRAOx22b?!x>a*aZ%Jow4_4=}c+(`EC~Tc;f-ZPE}H z%B%Pp%Cla3&_s#NC;jy>a>;W(P%2F|Apt4pnzm~-x%QeVrLKBrBsWr`?Yat?`Te`v zM6_J{x+yOmmp7-?OZ|PQdfAk&Ut)h+uXSFsU9$bQ{Us}m-X6nHs>a1&)AognKr93a zMoer{=s+@2kp!`;VN(J82X-iy1&}39ORucj`Oky8c$E1-k4{(Fv z29U@F44YF9TxNL@%2a{`gw$##dhQap5R@*tUkOUrIEXsHM^r?Mswg9t*p_k%7LddTk;wTI z<7B%T;#;P?fN>ZAh+hi=drHOsE$q`g(#IO<;k^0ya(UEwHz&)Z^3DPF)OPHMsaTkGFr2R*S zkL(|MI2(h}qyULrC`C;BKjHgy>BMs- zcJRSebNAO9-fsAaRW*xMYZ6s!=6@w#we7ZV+dXGa`eg7yiH%4dfmDTmv7#Lo z#_rZOEY_}1)ULm|K3?0O^!I<56>;0&pYk^>`r8uzwzm~#R($3bm4#S7?)xZG>nHid4#T!55?(@sGH zDuk&Pp?ox5IECam-`YoSV&n$GB%6{VERPW;kAxEU<5F0Ql_XFGiNS(>*ve6OSs}7DIUx|YVU|eo!bU+;`rEFOkR!b zDNQKl_c5%BK>P*H|2eM6S8+>wq@zk%_q1C+Nlc!UN3l3@lk0Pe>$9Bar|dHZoj9vH z2bnfYpf>9Hz#X{p*;HMdwAD9%Hc_`VdT6OC5Osgxu1?i9Mh`A|>tJ>k##z=RyuEQ( zucUl}sG?s44tC;2w@~c;M5f5m#!QABd4$wV(9ggE%B#_W^^i9{Z0DT6>=Y}h9yfrGgef7o%K{&Hz) zMUI4aG-_LG)K?3EDw)^moOG$k@4|qnqVBQKIxL|SMVlXtjokmKW0*u{2e4y{sQl%m!-1|O)|M~5+>ASq*#5r z>V=Evfq|Gr<^^9y5&&q;JzYaxDa|UB+=od(I63~ZkO>HtsssX-A>hP|{HjFts4xotd)@*>JzrPBWTAA=o=Wf{VHgwM0-#fa{u>Ni%QoeEe zhW$fm25wmBI=m1VO4awq>mOWdY+h{Km}uM>-}G>@@sXH)iGZ>{QP+R-XtM6XnL+i_ z`HCA8w1D+!V(p{x$A*(@pGY)5G4pWBS9#qt>xn&e$JY*YqNL*I230>5fVQsPUM)y_VV7&#zTYj5!{ZwH+&<5#&YHG`JlZ?Br>KUcQU9nW+(6BO%TAHAut;3PIW0 zA9A_wK=n02Zf?3}$qwZbr*uGUqIqa|jUW_89>n*U+c3ISKi3bM4cyd0#?$9t^z|lu zy>U-3j4PDvRHbF+9E-sni6BHlc4VA(Z7{HL>X*Ke4kL<#aiszsii+l5aMxrr+?Bzy zWPYV845qMprIvv~aE$V_@R+I7(ZM*jtr8<4B4rYKFvdmWZ|4`MP{j|7FR2ZvTKkh? zj4#0%SWxA&7$dTpm^~2Or*YSR=`4CQAHEf6a7aaTyPyXMS;yy|(>Mc=dqA&fhEhUo zgqi=KPc%-rE^$bt`*{;}UXYqGwRBXDa_g8-Muc(!kD4^QctuE_CCv`AwHztvi%Ufu z?J2~$_W)93?$ug6Fz#1JCqppDH$QNzW@cMbnBZGdqg=OMcz-`5pNxB+T#dc)j3ThN zhY+~0@D3&txO#cAz|XPu{Veh= zgfT$pe`XE&80(Rv<|rP=p@Q=Bzxrv3D_bX=Oynv4Q$>Jd5!nl7s#Mq6!H! zNULSg$G!kpP3N}!|B=0x+s*n!A-MP@$qng{%_KJzvI+(dKn7Vb!j8PARW4wN&Iiht zi>B51tTCIa;Et6Oxs3p$TLO%As!6kyClIe)Gyj?I_!kErPYgT`vyQ$xSgiCFo0JpO zg^e#wQho>U@X3He7y6)W4|Vqud8jwTb}~SQb(F%cp9nHcmU=#2(l47B@eiVL(o_gg z_)pqy|KAji%R(ItR6!F}6p%IxF6nC$tK*+>bx?Xsqg;yBq3@qUks-$bSK2FKo(|XK z8p(-#ifcrb0BeEN?qWq}qM~!&bMy3fijoxvU|G^z{ram{Uxi+P7sz^-*h!T+RtNtr zC(KKQVX>#KLjX&~2AYRe=)UJc=CH4te9vM**r)an>gpk?CX}Fq?>@Q#+v&LrAo3j_ z&$WO-83AA{<1d1`y;biqqPlty0miVt8eCz$;qO-Hsvi z>gF+##y$W(A;gh&BT0JOh)3&Rqf15=$i`}nENo~LGga-u^aUR!rI+}2mT)y{2#H}1 zaCjV9f$^ppkkJe&lJN#qkB)Big4LSKb3jffAuAz+B40xEL{s`$_4!#i_n6!oJUV&) zg0Mj%IM#yt%VzUQAX-Ay8XWM8XD7{__dF~-(PHG!+v`J8dPS%!3WYOFbc^x~?iw|j z=UYkZxy_JJact(ncRz1_+*YeNDx=6?%0(=Km7nIKW~6kX~6OK zTlvzmq;y^`xMadWQI-k>4rySL!%8faRHQjl>?4uL=&7+^1_+V5&TnHSfD%F9RcV(7 zHkA&n&QOu0H0J{(*}BroSwa&Kd@Y3K;*yl%=MgW-7hEhH)i(%I4kIN%$^$U)Ejh8# zA{v+s)YGyX9O-zeLk)9CQir-~u5!LeYEbVw@c!ff{i_+FO?~9)9Bt}!Aq&BtD>S{+ z9s}S2+e1b43r&?6S{DN3#(v>G$i|>WlX@m~V`}q$Y@rmr5au_~m{q%twrgcUg1%LS zZy>G{MB%FMKg%%?Vkj)6`ml3BLD51n6Jc~h(?R=de6Y&ogz}#dJJm#ptqoq^_Os_9 zq7m8IxBb)@JV#tmc7B(=PF9j&&foTiW=6kiO?X2;6^P#FJ*8IV2!ZmSAc@Ith%%2z zIeuE^f5@E3@&=v<4cBhz$zZ{x7h&#c9{&U`yaj>#9vkygmfltK;URJA$*i6?Q!N34 zg)W%3-viGx#AlB~QYJikx>xmut_tZGJ2>#;izr4qZp&@^7ua?|0?sFX@yF~3qMDe; zFjM3g*1N)sjeQB2n)j}ayVgoH*W4SVwzYETKSDqby-61T6MF#~zb4?oL>2~K!nQ#u85o~>=1}FtqIb3W8<{_wK~WupxL<>`MRpinFHq>nI3U) zhf{M2_2xezGv%CmB5NGEg0y+1BYct?{c{cD&@c`+5W9tkGpi1vVZIWg zmylGcYkKpQ`N74Wfke;1`{8)cK(gm(vUWJ?g)6Wrn(2?x_t8g>>6TCT96d@8@4&%n z_d_>;Dh?hze_ezgDVPAOh1@h`TzpI6@`0d{7p?l~XqM?@BUKHVHasp$gjyLarCzu| zw3~+xVK32X(~ z3N%kE63|J|ST9nsk&yi4X6 zT`|h9hEnNz4^%R>NP2-XUDTfqw&%bJFi*6mZc09WCJY_2q9 z3P|C?KBAfrSOGeSP47#WAh01SD6q#Y+!wtd(ZO0#%ls6+qp-3D6O0BClt`>lI5LlM zeu^jX0HUn9bxxNGG~;0{BT2x_jw>}B%3~~;|1Isjw$~q-&X2xsV=ko zA_ja+IVP>V9K&!ZBfNqhA9t1M>EOt7AXyw?kkabwO!DRoGx9hm!;5DYT5(tK%O>Sj`i2Vvf zf5>D7N+ZYai;QSus7FuqR_=S@fidU3T1+p#LNO0y=kQG#yAiQdU9z*p@dTQq&yMV$ zpbOzqg!i5uqyE4#*>|#rEL@4P1`g?QthOfj2`tW^YRgvr$NK%rRWUBYbQRqU9Pni2z(yS@rB5m`rI5|V+ z*qvfO71LDEzD1vMdsWsmov1(`LTC};pzLB1``^k~8u7_#jPeI;C%k#`)f#3axMre| zKj0%dg9?o}7}=$rf_aIrjILPiZ-QtecH zZG1x^)7+F+!Gl1RjY32=%rImd66S+2Y1yq)6?zwp>{WTd$E5hG=v?vL?{gSXJc|;Y zpRYr+DypY6hR*1Ek@DXn2{|H6DTd~242dTHmj1Po(jy`ACUz5{uX5jcm^0@HOx5YF z{0v|Jth3mq2uxB8hB$Y9hm{s(8w*m*Z1gu?aT@3QLX>B$75&?((jx+!hN;$Pxix4& zfuyR?QDr~-;UsUTcstD-m06T=hFrW^`IuzL&d_hM(dGJJ&UsMNd?Dp^7i>mMOhC+d9A!4e$$&e6hAah=Mhd03< zD`MvVf{)L$ZQo$%o4g79mb6KURPxZR@F*dUA^p7m}Y<*5wCTz8=Sqm4rsm2z#poNBUYU|F_rmd-t?o@Mos;!HWYd55J?SZkw z)c(T=XIfvfIv=&tC#+M1D9GKJDU@M|BiCn&WVqPkZ_c=782ZzVnGzX>+4n6OuMGPv zW&N2l87{X}v}Gz}*l#Io%2dj5m8G&JQ!T>*=2;`dwU(ydOq~qZTY@_>4KmzlY2BD< zlHs7G^XVN8l&2=?s7bl&l8(BRuOaDZ zP~*KKT-ua$G=VemtA|pJyOWOHOSN4|M^~zDOVY6=)rh>-fiPatHh1{u&hKnamLI%w zaK#aDRxbC~Ix90*?i8!)@3__84-l0SwUI6taa|Gq_g)Uo6XtImwg$AAlS_> zDxH4y1BAefE%5yMvDc1$WGi%bGQJ|iP{wa*S%0%V9^4Xl(1u<^%Xii+?tUV%`-zOb z)7cE!dimSEOZ+YsRV_OafA5IZ;;o*UPL{S^d3f1T<_s)%JYjX#El=3ID6GZO&>DBt z{Dspu6Nqh2I$K%82A0~!8a6DuT+YqQ{#Ix8$^om#*|J>U;cQ%f%<6V-&D2|V?zU#^ zZf6gK^W|^zR`I)3)UxbEJdzAp_aaTDvsR?xZ}SfEyi`=T?8NhOpUv64?6NxBmJ968 zrsZOrvvt{JLs5upSuU`lb6j?3kS|(rD(ZV6)fs{SN(zCdR@fuRc)iZzrPA(<6Tj#f zh~yVC1oyFlOc6uHma?9Vn;{&k8Zspem0GH5#FsE;P|=wwV_dnVxO%w)q2-oJ=bGid z3KZRKN9|B_1M+KVk2}zd(dQ9v+QjA4u{Ko|%DC&D-AmGf$FwQAw#G@Tc(I1 zRKPD%p#sI;=SPEYLQiUmLSe3rVtWbN9xqxu7yQ|OI5DnF?0Rb%j~Ze83FK=#`(O}d?1 zQi09lcd2OWvJ=mlr>(Wlz9n~Q#))4xrZ!W^5S{U6iWn+}qrr@uA&;fHE>pr#DQn|p zXv=nIajLm3W9RRBOb7n%-7kKZiag6sJg-b!i_qP*7J#IVwV6Vn^C|06d3(mm0LnzS zi8vHmT(?{#V!QO-Vl9eAPvKYXD28M|F;vXjpoYbn?fj~7BTFeNcZS4Q_{CQh^_fD3 zOh-VZgeUDt(kMB&GYm1_hivmU9S1p1eSp-9}2!`aMU`Q?shUB7PNG=M5?qSAy zL-RE^51`!AN3J~lK}GNU#H};$cP1;2Tsee72+M5FZWWdxgyI|xuOBW&M}cSV+PK@slqU$`)8ISG5fUnqIT8Fq!8 zUvNBA5QR3+Glih|6e*`s{M5Gxf;uutnu}p+J&T>KslfLHVd00KG{B9Jq;N@?6~rGB zh$tZ^2;39GGNCX7vh_LjIK5BEqd~6f6rF$3fvwpl(C*R5IIRr8&6r*bk*_KpCQDL< zAU-xIFIkx%15x(;Mdid;7W2!FzQKR%GI8qPu)@$fe&uDD>6^BE*`4h{5h6sE5q>MK zOTgg}z|rR#enj_4y!hV(>q4x;ScZi)YhnLdW0qWzs2H*6sdBx);ba8dfXR`OjVL!# zhtK~8W~~b>MWxrqWB!DzbG~4~g`K26>iDu-OqmnNK);*_iADtxFx!rYw3GD>Scd;i z-Im?wVY^~#^N~@A&;>_>r^n7-IC=4`$x#Z3!9t>t99T_EQP@QT2d!_aRj;u+4OW{9 zZ<(5I=?i}5{KZZfXn^p_aUAX;n@6J+lHH;C_yECN8fH+v1xU9>I%_aEI3563F8VTFOjh;sW)CGB_Uj) zwPmH8w+i0;yixU88k?_Xh+Gkc@(fBXZ(LtWJ#P)XHR6^olbMeQH_Z{$H=@uEp%Ub+ zm1E2)l6JG!$0hkzY2~|<9Fum2I(Q>FL#7&0t4q>=B#(77w1&4H-bj{I`gmK*+dAF^ z6-y8uHt=yHZ(?Q$qQV%<+ReDH^Tr9Fh}j~}qL1M*ZHG*;@(f>yf&45(XL);(w=2AT zfwy1dEymj$yuHsBev=__M*l7g5(jm%_mw~8?LY9A;4R79UEaRW+Y)d83vVCtCQg~( zV}4?~a&F}uL_ci$Oe%_o!H+vAp+*!HAl z`*J~n^`I3#|AL)yOLeRwY3V>?TYBcozh3)x?fkxE^M<&^H`9}}Y`E8G>0S4c4HaCr zdwY>-O>F0~#cQ>#v^7~PVy!C{{HzRGE3IwwdsZy?Sy@+OZH@=`u2}H9vZcW4iuq$F zZq%$;5L_vDSY0!NaKv^rRy})o1-cUMSzBjL#I~(i7+N{&2w2y}npQ0MS=r>U2I8JZ77L{H7geW-aFD|DGS8B^RF!Uwp}S%DJZuV&p2j|C44w~ V&mT*)qcw>7KOV4H+r%FG{{T@^d=mfw diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/exceptions.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/exceptions.cpython-312.pyc deleted file mode 100644 index fc6ef7bb7fffae6f9a515251ac9a1e4b49ef3d74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1757 zcmb7E&2QX96rb^ac{dx{q7vYM81bn^%^DJf1VV+Tq@@ysiqIVPVmbDB*NNA5XU0u- zn@T-IA{V4yP%2eO9EpNNZ}127fW##gMHGu00*M1sOBPY}#Czl2EiJw94sV{HXXd^4 zd%ri|O-|Mb$Zw@T+Fut4`2{~lQW_fjOJHmhkFu{rLfD)7^gEyiiW z0wsCqH-E<<4VsnCL~y{xuaVH9v40SZZNf>5LdJ$iTZNv{C}b0hDo##2LIzR0KR*u2 zgcHa-q{BWEoX@2}=yAaUAA-IpSsFRZA!jOPZXBr~N;ymNTbc_y#muzr$mw$1&T6*Z zjlDEPyKdWOQzsn$so1s`ySBYU_A$x33sxuYa?5WEM^3wr6^7ku6}YQh&06Ppbj}Kc zWh?2aP8`iPUzxFFp!js+xT{W^OKVxaYVk2<&7>!=QCgM3kodJpvf>A#KJx!Bpbnhi zj!Fezh}DTWjl6#MVPL5azt%WSzFmMbao{hmk8>e8^Y03+cY^h}AUdw~s~a9vnc5Wjxnq;WfCdAmk6o73xt{9XU6Q z-Qn$5=x2osROx2}|0-;fmJRaB(*$CVc2a_a*YD4-C!rHWY^~GN)#|zhFd;|wKL{LQ z92moe#tS*43FI)v*A)yE<9J`>;FH0CYfcp7Zg3CZksLuh*f-u_3k@@?1u*qeIg!h= z>bQMb)wbQxkZ1W59-b)xsCI6%dC`6(J#(io&BbI_2~8KxxWcI zZfl(nA07sjb@;5TdI>N;PeW&bJk4rLPMGp}A!3owvW|HFkl!`m%pcIB0(e9)Jvj^N tR)JFb6PfvyJTWL!dYWEp3<$0Rvp~&DD+2<{pkAk^=;hb{BDm_r{sD_XyGZ~5 diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/filter.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/filter.cpython-312.pyc deleted file mode 100644 index 436f123791ac409dc5ab569cf3623cb4d1e71210..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28612 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≀6n0+Qqa zryGY*Uj2^eEl<{c>9)Hq+t3I$th@q7m#W%#F28j-?QHoRs`U>w%gVo^u1|jc)RHXl zE1p>8UzeK41?o(7!8}sie^YW6r@!zl5|hnn|C@;5E-5iG@o)XgVnKA8Pg}J$CO`3sxpfJ28r@OfQv%`ZV@nW3`aS|KuE^JRI%K^P40h7 z6F7wLFzdj^zW@61Ysc4o+cUoH>6#r&2ba6Qzw3Lu(t95Lr00j-Yp1@NIrY`_Q-O3~ zGJP((c5WtfZYDjMN~eB3?VU|KXE~H&K8=SAU0p<9w}FGv=qqzW$_vO)G8o)V9v4g) zCodH@j9`{oI-`lc(!*&m_$%!XOGFWrnh1oz%p{1TdB}X zKGcfg(`c0Q=y~Dt?|A+JJSkA0*a!1o7ViC*>%F5J$x8L?>ND6Em=_zaL2 z>D6;|=#lCybt?Da6=mmVJ;6E*|1s@WoFGhOlhfhojD8tYNb2EwWl|sLe$$#h_)<6; z?bEIiGT6*g8tMFjH%&Qv`8PtqCUC^Mh;BWBh&_-A`0I@dH(fxwHBiq zff2^F;rPU4Ji#uXibH1$qX(%wq||O2K=5KB!tT+5;~j2d(oUztS`dlj02wqL(DR01 zqM&moKPGz4NFMwu2s!e@4i_l)B?LJqx$)6;NeY=#b7kj(Drq!KZVs7$J@0O3ERsrjFP6V-u$A0ggC?wv=n?izAZ4ZZi+jk<-S ztFGS9YFZW_TdnDZ3ktcWTHhO4^>k9=nbjKqiratNgWOlgC?&L7vwg+Aon>2XJ+$h1 zq#$4I{F#OA@N50dSAW+bG;}Nvt=1pDRdqO9*LY8;^0ds0w;MVZJ8pzOKC}4BYQx?? zy7YrrKiR%|=vlbc*0o-L_S&=AExVS*B{jYGY`QU&?dtxC-3lFqQ)u1_70Z@mw`z}N zYg@8SEo)8vnWp}wSC_Z1G#$g~)asV`!R(giZ#{9>ium1jGyCc(%wtIXgwDW0ahW9%QongOO8cpE}hQ&=Sq4|eOvgB6}6RQ z7nBpS$W8+1hhoHlCUr^KRsE&N>zG zY9Ch_pid;j7CpF>p`=&a^v?gC#WT+RSVBZ^DD z*f|4(POvixj8ZUdx^X2T-95)Hh$9=AZYd*t$lE1L8~vxI27z6f_eh~P$~ZguALRF_ z80`@%W|<57!{-MV#})O*$Zk}?Jyh}p^WpwLNe8NzxBC{gly4z_zZK~TgAc6@*~6DovW5;ed6_SYAaYduG9^&BA&bhl7ld%fbf zDsET#=7+AIzIJ-0s(VSiRploiPVY7EqL``bT&wbDs{HAy1KBFyb>}tb!qEGt-#xuF zm}%)>YdMf(JXu%eI|FYIWZOI6PraL3h%R+3J@$uB-h6UtAl-6s z?pgA(KJoU6Y_l|nLn1Bjd*Aim6UseX=4~iXw`Fx@d|jaBzTRwYN2a!KxqEHza7j&d#1TJx?<^RBh#1DWOnE6s=Chg#nH*3)xC z^IJh_-*0%gVX<~Gxze31pn{3S?*51=G&F=?OL|2`VLTn?ig;x8t9J=5&RZ6{ud&@VKM7Q%uAq|Ow~fmsKEk@vLuOO;MBeb6{{o^s1aRDA zs-0knJ$VO3!oDb@krT9JElIZW?KxQcj!A=%Q4b*3+J_4id&HAKpnyjfBEKVE7v8dh z2Ei^2#jAiAsicWkYr|l@(gKJaS}JHCLEs`A%J zQ!*5!5$KMPSNK_tR=$}`Tbk{*z`1Y~N~F|K!6q{0VtY2PwEfɥsKiqL&G*~V5_ zsXX2Dwrpn~v~1Pg^QYJWgzcGz?MnlnHXO{gcipukecg&|u$a|0G4YxquLq(8kK+G? zs!|R5rOGcGE`&e_aBzN(MoJ92zl^i(-=%~y3SOjOkOE>sa<=n{NF2EsdNL-6Rj;g3 zu3MC=nsNbQnWmH~!>vPvb~w}i7f498e(qe!Gzp~Pz$Dy+>#i zUwK?FgWhe|xIrg4vC>=KP+nZFz!*#Ms1@MTw0Qv^xLq?H!J#(we}5%cgP7q=yDkQj zXyTHjF$4P55D<8o^%5sRxeuQCW)Mv{Cj$JBb$iFjVdaOI@DZHm%v%T;b3q(BH;EFP zq5L@ow5R+ozBx})0%J&?q}X2}(43|i9^xqORr>S?6cC)!6bYaLYdgMm8rRlPsUos&&6D-E_nY2rTHOEbcJ#p4u;%N?-CXBvKDL(T;YlhfxW<$PdIc*${`YC3=a7r=2_cG?3}fJ zzdGv4-(VggT@zgZrb8Hx?b-5dHHY)R#K<2yCCP5CNOhXKt3e?jqj6oyG6CWMssJG3 zm~RzviVN~u+umDkdl`9Tmkmm{yb|nEwRAFX&ATJx-LZ6X)w>V;tih3)*Ns*RD=uzK zAhPLd^HoKT;s=NlLNGb1{k+qR#HcXKIj!&HnS$$%*yWP>CFbMS++w+OX}S!W`Ck+Y zp|~1QE5oFP{376(h=or*5K<$&YhWN>~k_7KArV$S@ZfcUjNdzPrZ9em=CD~`eQ6f4k=iY&%J-t ztX9q|$_=Vh{qwfm8KIyCgHGx-sFqX08>COE(7Ts^tF1_P=YQ)lm0B%D4-J<13^-N4 zHFyg1r`;E=-+o$nK_8oUrY2y^wE6v~h45ffTEM4=T^|xK?hk=x7iX+-cKagvtuvo# zXi2n-DS;U10x=!-%m=RdJ>uFWZscuT(A7N5Y4p^5lPDDH@I^=6{03(3rVWSi7+S}l z5MeieDS7n^An_739Z{&rWq6;HixVLzbc_E<1+!X(soH_bxLcALXbnt+>iCUw%(F@N zEeT4d3y1op7q!dO`Q=||p3Z_7R6%z+k+W4PPbBWCBH_Z-@J{JGT{^)rtQwp!-Qqi- zpIJ9wppIL>`Mr4hob!-e zDbpFoU5zPAs7E1Rb>%byjEc$BKca+xLJ1D#&+tkeHaf%48JlX-y0lX=rRBRYru;i9 z@1?(n^zyU%)lyt^Px*|i(M(@{lQ&C3daB82w&<@LjWNbQ)xj!&T@Lr%U_kWulnNEb zCLMwD0%}xVqJaEKlrso0JO*a^-?RP4-uiNn^$ERKE zWfa3{^quS*cv4@_hKtfJitP3@yM0vDu1}*V)Q5DZn$NgX4YBp@EUnDms%1nBQWoVa zNZY6p?UzL~>!@D0^x6CGcuua{@kUBr_j(z{oI*wGy>i5;CZ22KtKyR)ZfYB`bfE9G zeRRB=^?eT=@20+2RBqsScl-KDu}8b8jox%o8@=hGHoVzIZFp}yFIFM!F2`MP^^Nwr zyZg~lx_ay4Yb*BM_bgWX05!b__cYrF?pEO2e8WQTioNTe#cqFuK6T%v7)NTf1pa=y z9B*P8f1LuC<0*vJu-b_z`$Ivv>ySI*$0*r>+a@6J@bmKyq;N$R@oP#s1r-#Kl&iQY zAib7SNdYlp$|8bX75+jSYfRf^_1K| zK_dmEBV~6BD$Nultj@6p9c^J}6cmYK9SCv`?pL66QA&`4Z&2_}3a(K=GgAb$51dE& z6@tf=zr$Amt)S8d!Bxeg_%}l5-w0j*St$Rh#VuNXD(JyoifwEW#H#-$^#0W15G_9u z5d5^#L%H-|gJSokutlt$KY3rE_x#gez#TZTZr5j Y@Vf6tFt5j7a)^)2ANz?wZ??q$57xRTI{*Lx diff --git a/venv/lib/python3.12/site-packages/bs4/__pycache__/formatter.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/__pycache__/formatter.cpython-312.pyc deleted file mode 100644 index f58495f3a3d89fdce75674f8ce6f481a05607658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10525 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 diff --git a/venv/lib/python3.12/site-packages/bs4/_deprecation.py b/venv/lib/python3.12/site-packages/bs4/_deprecation.py deleted file mode 100644 index a0d7fdc..0000000 --- a/venv/lib/python3.12/site-packages/bs4/_deprecation.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Helper functions for deprecation. - -This interface is itself unstable and may change without warning. Do -not use these functions yourself, even as a joke. The underscores are -there for a reason. No support will be given. - -In particular, most of this will go away without warning once -Beautiful Soup drops support for Python 3.11, since Python 3.12 -defines a `@typing.deprecated() -decorator. `_ -""" - -import functools -import warnings - -from typing import ( - Any, - Callable, -) - - -def _deprecated_alias(old_name: str, new_name: str, version: str): - """Alias one attribute name to another for backward compatibility - - :meta private: - """ - - @property - def alias(self) -> Any: - ":meta private:" - warnings.warn( - f"Access to deprecated property {old_name}. (Replaced by {new_name}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return getattr(self, new_name) - - @alias.setter - def alias(self, value: str) -> None: - ":meta private:" - warnings.warn( - f"Write to deprecated property {old_name}. (Replaced by {new_name}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return setattr(self, new_name, value) - - return alias - - -def _deprecated_function_alias( - old_name: str, new_name: str, version: str -) -> Callable[[Any], Any]: - def alias(self, *args: Any, **kwargs: Any) -> Any: - ":meta private:" - warnings.warn( - f"Call to deprecated method {old_name}. (Replaced by {new_name}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return getattr(self, new_name)(*args, **kwargs) - - return alias - - -def _deprecated(replaced_by: str, version: str) -> Callable: - def deprecate(func: Callable) -> Callable: - @functools.wraps(func) - def with_warning(*args: Any, **kwargs: Any) -> Any: - ":meta private:" - warnings.warn( - f"Call to deprecated method {func.__name__}. (Replaced by {replaced_by}) -- Deprecated since version {version}.", - DeprecationWarning, - stacklevel=2, - ) - return func(*args, **kwargs) - - return with_warning - - return deprecate diff --git a/venv/lib/python3.12/site-packages/bs4/_typing.py b/venv/lib/python3.12/site-packages/bs4/_typing.py deleted file mode 100644 index ac4ec34..0000000 --- a/venv/lib/python3.12/site-packages/bs4/_typing.py +++ /dev/null @@ -1,196 +0,0 @@ -# Custom type aliases used throughout Beautiful Soup to improve readability. - -# Notes on improvements to the type system in newer versions of Python -# that can be used once Beautiful Soup drops support for older -# versions: -# -# * ClassVar can be put on class variables now. -# * In 3.10, x|y is an accepted shorthand for Union[x,y]. -# * In 3.10, TypeAlias gains capabilities that can be used to -# improve the tree matching types (I don't remember what, exactly). -# * In 3.9 it's possible to specialize the re.Match type, -# e.g. re.Match[str]. In 3.8 there's a typing.re namespace for this, -# but it's removed in 3.12, so to support the widest possible set of -# versions I'm not using it. - -from typing_extensions import ( - runtime_checkable, - Protocol, - TypeAlias, -) -from typing import ( - Any, - Callable, - Dict, - IO, - Iterable, - Mapping, - Optional, - Pattern, - TYPE_CHECKING, - Union, -) - -if TYPE_CHECKING: - from bs4.element import ( - AttributeValueList, - NamespacedAttribute, - NavigableString, - PageElement, - ResultSet, - Tag, - ) - - -@runtime_checkable -class _RegularExpressionProtocol(Protocol): - """A protocol object which can accept either Python's built-in - `re.Pattern` objects, or the similar ``Regex`` objects defined by the - third-party ``regex`` package. - """ - - def search( - self, string: str, pos: int = ..., endpos: int = ... - ) -> Optional[Any]: ... - - @property - def pattern(self) -> str: ... - - -# Aliases for markup in various stages of processing. -# -#: The rawest form of markup: either a string, bytestring, or an open filehandle. -_IncomingMarkup: TypeAlias = Union[str, bytes, IO[str], IO[bytes]] - -#: Markup that is in memory but has (potentially) yet to be converted -#: to Unicode. -_RawMarkup: TypeAlias = Union[str, bytes] - -# Aliases for character encodings -# - -#: A data encoding. -_Encoding: TypeAlias = str - -#: One or more data encodings. -_Encodings: TypeAlias = Iterable[_Encoding] - -# Aliases for XML namespaces -# - -#: The prefix for an XML namespace. -_NamespacePrefix: TypeAlias = str - -#: The URL of an XML namespace -_NamespaceURL: TypeAlias = str - -#: A mapping of prefixes to namespace URLs. -_NamespaceMapping: TypeAlias = Dict[_NamespacePrefix, _NamespaceURL] - -#: A mapping of namespace URLs to prefixes -_InvertedNamespaceMapping: TypeAlias = Dict[_NamespaceURL, _NamespacePrefix] - -# Aliases for the attribute values associated with HTML/XML tags. -# - -#: The value associated with an HTML or XML attribute. This is the -#: relatively unprocessed value Beautiful Soup expects to come from a -#: `TreeBuilder`. -_RawAttributeValue: TypeAlias = str - -#: A dictionary of names to `_RawAttributeValue` objects. This is how -#: Beautiful Soup expects a `TreeBuilder` to represent a tag's -#: attribute values. -_RawAttributeValues: TypeAlias = ( - "Mapping[Union[str, NamespacedAttribute], _RawAttributeValue]" -) - -#: An attribute value in its final form, as stored in the -# `Tag` class, after it has been processed and (in some cases) -# split into a list of strings. -_AttributeValue: TypeAlias = Union[str, "AttributeValueList"] - -#: A dictionary of names to :py:data:`_AttributeValue` objects. This is what -#: a tag's attributes look like after processing. -_AttributeValues: TypeAlias = Dict[str, _AttributeValue] - -#: The methods that deal with turning :py:data:`_RawAttributeValue` into -#: :py:data:`_AttributeValue` may be called several times, even after the values -#: are already processed (e.g. when cloning a tag), so they need to -#: be able to acommodate both possibilities. -_RawOrProcessedAttributeValues: TypeAlias = Union[_RawAttributeValues, _AttributeValues] - -#: A number of tree manipulation methods can take either a `PageElement` or a -#: normal Python string (which will be converted to a `NavigableString`). -_InsertableElement: TypeAlias = Union["PageElement", str] - -# Aliases to represent the many possibilities for matching bits of a -# parse tree. -# -# This is very complicated because we're applying a formal type system -# to some very DWIM code. The types we end up with will be the types -# of the arguments to the SoupStrainer constructor and (more -# familiarly to Beautiful Soup users) the find* methods. - -#: A function that takes a PageElement and returns a yes-or-no answer. -_PageElementMatchFunction: TypeAlias = Callable[["PageElement"], bool] - -#: A function that takes the raw parsed ingredients of a markup tag -#: and returns a yes-or-no answer. -# Not necessary at the moment. -# _AllowTagCreationFunction:TypeAlias = Callable[[Optional[str], str, Optional[_RawAttributeValues]], bool] - -#: A function that takes the raw parsed ingredients of a markup string node -#: and returns a yes-or-no answer. -# Not necessary at the moment. -# _AllowStringCreationFunction:TypeAlias = Callable[[Optional[str]], bool] - -#: A function that takes a `Tag` and returns a yes-or-no answer. -#: A `TagNameMatchRule` expects this kind of function, if you're -#: going to pass it a function. -_TagMatchFunction: TypeAlias = Callable[["Tag"], bool] - -#: A function that takes a single string and returns a yes-or-no -#: answer. An `AttributeValueMatchRule` expects this kind of function, if -#: you're going to pass it a function. So does a `StringMatchRule`. -_StringMatchFunction: TypeAlias = Callable[[str], bool] - -#: Either a tag name, an attribute value or a string can be matched -#: against a string, bytestring, regular expression, or a boolean. -_BaseStrainable: TypeAlias = Union[str, bytes, Pattern[str], bool] - -#: A tag can be matched either with the `_BaseStrainable` options, or -#: using a function that takes the `Tag` as its sole argument. -_BaseStrainableElement: TypeAlias = Union[_BaseStrainable, _TagMatchFunction] - -#: A tag's attribute vgalue can be matched either with the -#: `_BaseStrainable` options, or using a function that takes that -#: value as its sole argument. -_BaseStrainableAttribute: TypeAlias = Union[_BaseStrainable, _StringMatchFunction] - -#: A tag can be matched using either a single criterion or a list of -#: criteria. -_StrainableElement: TypeAlias = Union[ - _BaseStrainableElement, Iterable[_BaseStrainableElement] -] - -#: An attribute value can be matched using either a single criterion -#: or a list of criteria. -_StrainableAttribute: TypeAlias = Union[ - _BaseStrainableAttribute, Iterable[_BaseStrainableAttribute] -] - -#: An string can be matched using the same techniques as -#: an attribute value. -_StrainableString: TypeAlias = _StrainableAttribute - -#: A dictionary may be used to match against multiple attribute vlaues at once. -_StrainableAttributes: TypeAlias = Dict[str, _StrainableAttribute] - -#: Many Beautiful soup methods return a PageElement or an ResultSet of -#: PageElements. A PageElement is either a Tag or a NavigableString. -#: These convenience aliases make it easier for IDE users to see which methods -#: are available on the objects they're dealing with. -_OneElement: TypeAlias = Union["PageElement", "Tag", "NavigableString"] -_AtMostOneElement: TypeAlias = Optional[_OneElement] -_QueryResults: TypeAlias = "ResultSet[_OneElement]" diff --git a/venv/lib/python3.12/site-packages/bs4/_warnings.py b/venv/lib/python3.12/site-packages/bs4/_warnings.py deleted file mode 100644 index 4309473..0000000 --- a/venv/lib/python3.12/site-packages/bs4/_warnings.py +++ /dev/null @@ -1,98 +0,0 @@ -"""Define some custom warnings.""" - - -class GuessedAtParserWarning(UserWarning): - """The warning issued when BeautifulSoup has to guess what parser to - use -- probably because no parser was specified in the constructor. - """ - - MESSAGE: str = """No parser was explicitly specified, so I'm using the best available %(markup_type)s parser for this system ("%(parser)s"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently. - -The code that caused this warning is on line %(line_number)s of the file %(filename)s. To get rid of this warning, pass the additional argument 'features="%(parser)s"' to the BeautifulSoup constructor. -""" - - -class UnusualUsageWarning(UserWarning): - """A superclass for warnings issued when Beautiful Soup sees - something that is typically the result of a mistake in the calling - code, but might be intentional on the part of the user. If it is - in fact intentional, you can filter the individual warning class - to get rid of the warning. If you don't like Beautiful Soup - second-guessing what you are doing, you can filter the - UnusualUsageWarningclass itself and get rid of these entirely. - """ - - -class MarkupResemblesLocatorWarning(UnusualUsageWarning): - """The warning issued when BeautifulSoup is given 'markup' that - actually looks like a resource locator -- a URL or a path to a file - on disk. - """ - - #: :meta private: - GENERIC_MESSAGE: str = """ - -However, if you want to parse some data that happens to look like a %(what)s, then nothing has gone wrong: you are using Beautiful Soup correctly, and this warning is spurious and can be filtered. To make this warning go away, run this code before calling the BeautifulSoup constructor: - - from bs4 import MarkupResemblesLocatorWarning - import warnings - - warnings.filterwarnings("ignore", category=MarkupResemblesLocatorWarning) - """ - - URL_MESSAGE: str = ( - """The input passed in on this line looks more like a URL than HTML or XML. - -If you meant to use Beautiful Soup to parse the web page found at a certain URL, then something has gone wrong. You should use an Python package like 'requests' to fetch the content behind the URL. Once you have the content as a string, you can feed that string into Beautiful Soup.""" - + GENERIC_MESSAGE - ) - - FILENAME_MESSAGE: str = ( - """The input passed in on this line looks more like a filename than HTML or XML. - -If you meant to use Beautiful Soup to parse the contents of a file on disk, then something has gone wrong. You should open the file first, using code like this: - - filehandle = open(your filename) - -You can then feed the open filehandle into Beautiful Soup instead of using the filename.""" - + GENERIC_MESSAGE - ) - - -class AttributeResemblesVariableWarning(UnusualUsageWarning, SyntaxWarning): - """The warning issued when Beautiful Soup suspects a provided - attribute name may actually be the misspelled name of a Beautiful - Soup variable. Generally speaking, this is only used in cases like - "_class" where it's very unlikely the user would be referencing an - XML attribute with that name. - """ - - MESSAGE: str = """%(original)r is an unusual attribute name and is a common misspelling for %(autocorrect)r. - -If you meant %(autocorrect)r, change your code to use it, and this warning will go away. - -If you really did mean to check the %(original)r attribute, this warning is spurious and can be filtered. To make it go away, run this code before creating your BeautifulSoup object: - - from bs4 import AttributeResemblesVariableWarning - import warnings - - warnings.filterwarnings("ignore", category=AttributeResemblesVariableWarning) -""" - - -class XMLParsedAsHTMLWarning(UnusualUsageWarning): - """The warning issued when an HTML parser is used to parse - XML that is not (as far as we can tell) XHTML. - """ - - MESSAGE: str = """It looks like you're using an HTML parser to parse an XML document. - -Assuming this really is an XML document, what you're doing might work, but you should know that using an XML parser will be more reliable. To parse this document as XML, make sure you have the Python package 'lxml' installed, and pass the keyword argument `features="xml"` into the BeautifulSoup constructor. - -If you want or need to use an HTML parser on this document, you can make this warning go away by filtering it. To do that, run this code before calling the BeautifulSoup constructor: - - from bs4 import XMLParsedAsHTMLWarning - import warnings - - warnings.filterwarnings("ignore", category=XMLParsedAsHTMLWarning) -""" diff --git a/venv/lib/python3.12/site-packages/bs4/builder/__init__.py b/venv/lib/python3.12/site-packages/bs4/builder/__init__.py deleted file mode 100644 index 5f2b38d..0000000 --- a/venv/lib/python3.12/site-packages/bs4/builder/__init__.py +++ /dev/null @@ -1,848 +0,0 @@ -from __future__ import annotations - -# Use of this source code is governed by the MIT license. -__license__ = "MIT" - -from collections import defaultdict -import re -from types import ModuleType -from typing import ( - Any, - cast, - Dict, - Iterable, - List, - Optional, - Pattern, - Set, - Tuple, - Type, - TYPE_CHECKING, -) -import warnings -import sys -from bs4.element import ( - AttributeDict, - AttributeValueList, - CharsetMetaAttributeValue, - ContentMetaAttributeValue, - RubyParenthesisString, - RubyTextString, - Stylesheet, - Script, - TemplateString, - nonwhitespace_re, -) - -# Exceptions were moved to their own module in 4.13. Import here for -# backwards compatibility. -from bs4.exceptions import ParserRejectedMarkup - -from bs4._typing import ( - _AttributeValues, - _RawAttributeValue, -) - -from bs4._warnings import XMLParsedAsHTMLWarning - -if TYPE_CHECKING: - from bs4 import BeautifulSoup - from bs4.element import ( - NavigableString, - Tag, - ) - from bs4._typing import ( - _AttributeValue, - _Encoding, - _Encodings, - _RawOrProcessedAttributeValues, - _RawMarkup, - ) - -__all__ = [ - "HTMLTreeBuilder", - "SAXTreeBuilder", - "TreeBuilder", - "TreeBuilderRegistry", -] - -# Some useful features for a TreeBuilder to have. -FAST = "fast" -PERMISSIVE = "permissive" -STRICT = "strict" -XML = "xml" -HTML = "html" -HTML_5 = "html5" - -__all__ = [ - "TreeBuilderRegistry", - "TreeBuilder", - "HTMLTreeBuilder", - "DetectsXMLParsedAsHTML", - - "ParserRejectedMarkup", # backwards compatibility only as of 4.13.0 -] - -class TreeBuilderRegistry(object): - """A way of looking up TreeBuilder subclasses by their name or by desired - features. - """ - - builders_for_feature: Dict[str, List[Type[TreeBuilder]]] - builders: List[Type[TreeBuilder]] - - def __init__(self) -> None: - self.builders_for_feature = defaultdict(list) - self.builders = [] - - def register(self, treebuilder_class: type[TreeBuilder]) -> None: - """Register a treebuilder based on its advertised features. - - :param treebuilder_class: A subclass of `TreeBuilder`. its - `TreeBuilder.features` attribute should list its features. - """ - for feature in treebuilder_class.features: - self.builders_for_feature[feature].insert(0, treebuilder_class) - self.builders.insert(0, treebuilder_class) - - def lookup(self, *features: str) -> Optional[Type[TreeBuilder]]: - """Look up a TreeBuilder subclass with the desired features. - - :param features: A list of features to look for. If none are - provided, the most recently registered TreeBuilder subclass - will be used. - :return: A TreeBuilder subclass, or None if there's no - registered subclass with all the requested features. - """ - if len(self.builders) == 0: - # There are no builders at all. - return None - - if len(features) == 0: - # They didn't ask for any features. Give them the most - # recently registered builder. - return self.builders[0] - - # Go down the list of features in order, and eliminate any builders - # that don't match every feature. - feature_list = list(features) - feature_list.reverse() - candidates = None - candidate_set = None - while len(feature_list) > 0: - feature = feature_list.pop() - we_have_the_feature = self.builders_for_feature.get(feature, []) - if len(we_have_the_feature) > 0: - if candidates is None: - candidates = we_have_the_feature - candidate_set = set(candidates) - else: - # Eliminate any candidates that don't have this feature. - candidate_set = candidate_set.intersection(set(we_have_the_feature)) - - # The only valid candidates are the ones in candidate_set. - # Go through the original list of candidates and pick the first one - # that's in candidate_set. - if candidate_set is None or candidates is None: - return None - for candidate in candidates: - if candidate in candidate_set: - return candidate - return None - - -#: The `BeautifulSoup` constructor will take a list of features -#: and use it to look up `TreeBuilder` classes in this registry. -builder_registry: TreeBuilderRegistry = TreeBuilderRegistry() - - -class TreeBuilder(object): - """Turn a textual document into a Beautiful Soup object tree. - - This is an abstract superclass which smooths out the behavior of - different parser libraries into a single, unified interface. - - :param multi_valued_attributes: If this is set to None, the - TreeBuilder will not turn any values for attributes like - 'class' into lists. Setting this to a dictionary will - customize this behavior; look at :py:attr:`bs4.builder.HTMLTreeBuilder.DEFAULT_CDATA_LIST_ATTRIBUTES` - for an example. - - Internally, these are called "CDATA list attributes", but that - probably doesn't make sense to an end-user, so the argument name - is ``multi_valued_attributes``. - - :param preserve_whitespace_tags: A set of tags to treat - the way
 tags are treated in HTML. Tags in this set
-     are immune from pretty-printing; their contents will always be
-     output as-is.
-
-    :param string_containers: A dictionary mapping tag names to
-     the classes that should be instantiated to contain the textual
-     contents of those tags. The default is to use NavigableString
-     for every tag, no matter what the name. You can override the
-     default by changing :py:attr:`DEFAULT_STRING_CONTAINERS`.
-
-    :param store_line_numbers: If the parser keeps track of the line
-     numbers and positions of the original markup, that information
-     will, by default, be stored in each corresponding
-     :py:class:`bs4.element.Tag` object. You can turn this off by
-     passing store_line_numbers=False; then Tag.sourcepos and
-     Tag.sourceline will always be None. If the parser you're using
-     doesn't keep track of this information, then store_line_numbers
-     is irrelevant.
-
-    :param attribute_dict_class: The value of a multi-valued attribute
-      (such as HTML's 'class') willl be stored in an instance of this
-      class.  The default is Beautiful Soup's built-in
-      `AttributeValueList`, which is a normal Python list, and you
-      will probably never need to change it.
-    """
-
-    USE_DEFAULT: Any = object()  #: :meta private:
-
-    def __init__(
-        self,
-        multi_valued_attributes: Dict[str, Set[str]] = USE_DEFAULT,
-        preserve_whitespace_tags: Set[str] = USE_DEFAULT,
-        store_line_numbers: bool = USE_DEFAULT,
-        string_containers: Dict[str, Type[NavigableString]] = USE_DEFAULT,
-        empty_element_tags: Set[str] = USE_DEFAULT,
-        attribute_dict_class: Type[AttributeDict] = AttributeDict,
-        attribute_value_list_class: Type[AttributeValueList] = AttributeValueList,
-    ):
-        self.soup = None
-        if multi_valued_attributes is self.USE_DEFAULT:
-            multi_valued_attributes = self.DEFAULT_CDATA_LIST_ATTRIBUTES
-        self.cdata_list_attributes = multi_valued_attributes
-        if preserve_whitespace_tags is self.USE_DEFAULT:
-            preserve_whitespace_tags = self.DEFAULT_PRESERVE_WHITESPACE_TAGS
-        self.preserve_whitespace_tags = preserve_whitespace_tags
-        if empty_element_tags is self.USE_DEFAULT:
-            self.empty_element_tags = self.DEFAULT_EMPTY_ELEMENT_TAGS
-        else:
-            self.empty_element_tags = empty_element_tags
-        # TODO: store_line_numbers is probably irrelevant now that
-        # the behavior of sourceline and sourcepos has been made consistent
-        # everywhere.
-        if store_line_numbers == self.USE_DEFAULT:
-            store_line_numbers = self.TRACKS_LINE_NUMBERS
-        self.store_line_numbers = store_line_numbers
-        if string_containers == self.USE_DEFAULT:
-            string_containers = self.DEFAULT_STRING_CONTAINERS
-        self.string_containers = string_containers
-        self.attribute_dict_class = attribute_dict_class
-        self.attribute_value_list_class = attribute_value_list_class
-
-    NAME: str = "[Unknown tree builder]"
-    ALTERNATE_NAMES: Iterable[str] = []
-    features: Iterable[str] = []
-
-    is_xml: bool = False
-    picklable: bool = False
-
-    soup: Optional[BeautifulSoup]  #: :meta private:
-
-    #: A tag will be considered an empty-element
-    #: tag when and only when it has no contents.
-    empty_element_tags: Optional[Set[str]] = None  #: :meta private:
-    cdata_list_attributes: Dict[str, Set[str]]  #: :meta private:
-    preserve_whitespace_tags: Set[str]  #: :meta private:
-    string_containers: Dict[str, Type[NavigableString]]  #: :meta private:
-    tracks_line_numbers: bool  #: :meta private:
-
-    #: A value for these tag/attribute combinations is a space- or
-    #: comma-separated list of CDATA, rather than a single CDATA.
-    DEFAULT_CDATA_LIST_ATTRIBUTES: Dict[str, Set[str]] = defaultdict(set)
-
-    #: Whitespace should be preserved inside these tags.
-    DEFAULT_PRESERVE_WHITESPACE_TAGS: Set[str] = set()
-
-    #: The textual contents of tags with these names should be
-    #: instantiated with some class other than `bs4.element.NavigableString`.
-    DEFAULT_STRING_CONTAINERS: Dict[str, Type[bs4.element.NavigableString]] = {}
-
-    #: By default, tags are treated as empty-element tags if they have
-    #: no contents--that is, using XML rules. HTMLTreeBuilder
-    #: defines a different set of DEFAULT_EMPTY_ELEMENT_TAGS based on the
-    #: HTML 4 and HTML5 standards.
-    DEFAULT_EMPTY_ELEMENT_TAGS: Optional[Set[str]] = None
-
-    #: Most parsers don't keep track of line numbers.
-    TRACKS_LINE_NUMBERS: bool = False
-
-    def initialize_soup(self, soup: BeautifulSoup) -> None:
-        """The BeautifulSoup object has been initialized and is now
-        being associated with the TreeBuilder.
-
-        :param soup: A BeautifulSoup object.
-        """
-        self.soup = soup
-
-    def reset(self) -> None:
-        """Do any work necessary to reset the underlying parser
-        for a new document.
-
-        By default, this does nothing.
-        """
-        pass
-
-    def can_be_empty_element(self, tag_name: str) -> bool:
-        """Might a tag with this name be an empty-element tag?
-
-        The final markup may or may not actually present this tag as
-        self-closing.
-
-        For instance: an HTMLBuilder does not consider a 

tag to be - an empty-element tag (it's not in - HTMLBuilder.empty_element_tags). This means an empty

tag - will be presented as "

", not "

" or "

". - - The default implementation has no opinion about which tags are - empty-element tags, so a tag will be presented as an - empty-element tag if and only if it has no children. - "" will become "", and "bar" will - be left alone. - - :param tag_name: The name of a markup tag. - """ - if self.empty_element_tags is None: - return True - return tag_name in self.empty_element_tags - - def feed(self, markup: _RawMarkup) -> None: - """Run incoming markup through some parsing process.""" - raise NotImplementedError() - - def prepare_markup( - self, - markup: _RawMarkup, - user_specified_encoding: Optional[_Encoding] = None, - document_declared_encoding: Optional[_Encoding] = None, - exclude_encodings: Optional[_Encodings] = None, - ) -> Iterable[Tuple[_RawMarkup, Optional[_Encoding], Optional[_Encoding], bool]]: - """Run any preliminary steps necessary to make incoming markup - acceptable to the parser. - - :param markup: The markup that's about to be parsed. - :param user_specified_encoding: The user asked to try this encoding - to convert the markup into a Unicode string. - :param document_declared_encoding: The markup itself claims to be - in this encoding. NOTE: This argument is not used by the - calling code and can probably be removed. - :param exclude_encodings: The user asked *not* to try any of - these encodings. - - :yield: A series of 4-tuples: (markup, encoding, declared encoding, - has undergone character replacement) - - Each 4-tuple represents a strategy that the parser can try - to convert the document to Unicode and parse it. Each - strategy will be tried in turn. - - By default, the only strategy is to parse the markup - as-is. See `LXMLTreeBuilderForXML` and - `HTMLParserTreeBuilder` for implementations that take into - account the quirks of particular parsers. - - :meta private: - - """ - yield markup, None, None, False - - def test_fragment_to_document(self, fragment: str) -> str: - """Wrap an HTML fragment to make it look like a document. - - Different parsers do this differently. For instance, lxml - introduces an empty tag, and html5lib - doesn't. Abstracting this away lets us write simple tests - which run HTML fragments through the parser and compare the - results against other HTML fragments. - - This method should not be used outside of unit tests. - - :param fragment: A fragment of HTML. - :return: A full HTML document. - :meta private: - """ - return fragment - - def set_up_substitutions(self, tag: Tag) -> bool: - """Set up any substitutions that will need to be performed on - a `Tag` when it's output as a string. - - By default, this does nothing. See `HTMLTreeBuilder` for a - case where this is used. - - :return: Whether or not a substitution was performed. - :meta private: - """ - return False - - def _replace_cdata_list_attribute_values( - self, tag_name: str, attrs: _RawOrProcessedAttributeValues - ) -> _AttributeValues: - """When an attribute value is associated with a tag that can - have multiple values for that attribute, convert the string - value to a list of strings. - - Basically, replaces class="foo bar" with class=["foo", "bar"] - - NOTE: This method modifies its input in place. - - :param tag_name: The name of a tag. - :param attrs: A dictionary containing the tag's attributes. - Any appropriate attribute values will be modified in place. - :return: The modified dictionary that was originally passed in. - """ - - # First, cast the attrs dict to _AttributeValues. This might - # not be accurate yet, but it will be by the time this method - # returns. - modified_attrs = cast(_AttributeValues, attrs) - if not modified_attrs or not self.cdata_list_attributes: - # Nothing to do. - return modified_attrs - - # There is at least a possibility that we need to modify one of - # the attribute values. - universal: Set[str] = self.cdata_list_attributes.get("*", set()) - tag_specific = self.cdata_list_attributes.get(tag_name.lower(), None) - for attr in list(modified_attrs.keys()): - modified_value: _AttributeValue - if attr in universal or (tag_specific and attr in tag_specific): - # We have a "class"-type attribute whose string - # value is a whitespace-separated list of - # values. Split it into a list. - original_value: _AttributeValue = modified_attrs[attr] - if isinstance(original_value, _RawAttributeValue): - # This is a _RawAttributeValue (a string) that - # needs to be split and converted to a - # AttributeValueList so it can be an - # _AttributeValue. - modified_value = self.attribute_value_list_class( - nonwhitespace_re.findall(original_value) - ) - else: - # html5lib calls setAttributes twice for the - # same tag when rearranging the parse tree. On - # the second call the attribute value here is - # already a list. This can also happen when a - # Tag object is cloned. If this happens, leave - # the value alone rather than trying to split - # it again. - modified_value = original_value - modified_attrs[attr] = modified_value - return modified_attrs - - -class SAXTreeBuilder(TreeBuilder): - """A Beautiful Soup treebuilder that listens for SAX events. - - This is not currently used for anything, and it will be removed - soon. It was a good idea, but it wasn't properly integrated into the - rest of Beautiful Soup, so there have been long stretches where it - hasn't worked properly. - """ - - def __init__(self, *args: Any, **kwargs: Any) -> None: - warnings.warn( - "The SAXTreeBuilder class was deprecated in 4.13.0 and will be removed soon thereafter. It is completely untested and probably doesn't work; do not use it.", - DeprecationWarning, - stacklevel=2, - ) - super(SAXTreeBuilder, self).__init__(*args, **kwargs) - - def feed(self, markup: _RawMarkup) -> None: - raise NotImplementedError() - - def close(self) -> None: - pass - - def startElement(self, name: str, attrs: Dict[str, str]) -> None: - attrs = AttributeDict((key[1], value) for key, value in list(attrs.items())) - # print("Start %s, %r" % (name, attrs)) - assert self.soup is not None - self.soup.handle_starttag(name, None, None, attrs) - - def endElement(self, name: str) -> None: - # print("End %s" % name) - assert self.soup is not None - self.soup.handle_endtag(name) - - def startElementNS( - self, nsTuple: Tuple[str, str], nodeName: str, attrs: Dict[str, str] - ) -> None: - # Throw away (ns, nodeName) for now. - self.startElement(nodeName, attrs) - - def endElementNS(self, nsTuple: Tuple[str, str], nodeName: str) -> None: - # Throw away (ns, nodeName) for now. - self.endElement(nodeName) - # handler.endElementNS((ns, node.nodeName), node.nodeName) - - def startPrefixMapping(self, prefix: str, nodeValue: str) -> None: - # Ignore the prefix for now. - pass - - def endPrefixMapping(self, prefix: str) -> None: - # Ignore the prefix for now. - # handler.endPrefixMapping(prefix) - pass - - def characters(self, content: str) -> None: - assert self.soup is not None - self.soup.handle_data(content) - - def startDocument(self) -> None: - pass - - def endDocument(self) -> None: - pass - - -class HTMLTreeBuilder(TreeBuilder): - """This TreeBuilder knows facts about HTML, such as which tags are treated - specially by the HTML standard. - """ - - #: Some HTML tags are defined as having no contents. Beautiful Soup - #: treats these specially. - DEFAULT_EMPTY_ELEMENT_TAGS: Set[str] = set( - [ - # These are from HTML5. - "area", - "base", - "br", - "col", - "embed", - "hr", - "img", - "input", - "keygen", - "link", - "menuitem", - "meta", - "param", - "source", - "track", - "wbr", - # These are from earlier versions of HTML and are removed in HTML5. - "basefont", - "bgsound", - "command", - "frame", - "image", - "isindex", - "nextid", - "spacer", - ] - ) - - #: The HTML standard defines these tags as block-level elements. Beautiful - #: Soup does not treat these elements differently from other elements, - #: but it may do so eventually, and this information is available if - #: you need to use it. - DEFAULT_BLOCK_ELEMENTS: Set[str] = set( - [ - "address", - "article", - "aside", - "blockquote", - "canvas", - "dd", - "div", - "dl", - "dt", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "header", - "hr", - "li", - "main", - "nav", - "noscript", - "ol", - "output", - "p", - "pre", - "section", - "table", - "tfoot", - "ul", - "video", - ] - ) - - #: These HTML tags need special treatment so they can be - #: represented by a string class other than `bs4.element.NavigableString`. - #: - #: For some of these tags, it's because the HTML standard defines - #: an unusual content model for them. I made this list by going - #: through the HTML spec - #: (https://html.spec.whatwg.org/#metadata-content) and looking for - #: "metadata content" elements that can contain strings. - #: - #: The Ruby tags ( and ) are here despite being normal - #: "phrasing content" tags, because the content they contain is - #: qualitatively different from other text in the document, and it - #: can be useful to be able to distinguish it. - #: - #: TODO: Arguably

foo

" - soup = self.soup(markup) - return doctype.encode("utf8"), soup - - def test_normal_doctypes(self): - """Make sure normal, everyday HTML doctypes are handled correctly.""" - self.assertDoctypeHandled("html") - self.assertDoctypeHandled( - 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' - ) - - def test_empty_doctype(self): - soup = self.soup("") - doctype = soup.contents[0] - assert "" == doctype.strip() - - def test_mixed_case_doctype(self): - # A lowercase or mixed-case doctype becomes a Doctype. - for doctype_fragment in ("doctype", "DocType"): - doctype_str, soup = self._document_with_doctype("html", doctype_fragment) - - # Make sure a Doctype object was created and that the DOCTYPE - # is uppercase. - doctype = soup.contents[0] - assert doctype.__class__ == Doctype - assert doctype == "html" - assert soup.encode("utf8")[: len(doctype_str)] == b"" - - # Make sure that the doctype was correctly associated with the - # parse tree and that the rest of the document parsed. - assert soup.p.contents[0] == "foo" - - def test_public_doctype_with_url(self): - doctype = 'html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"' - self.assertDoctypeHandled(doctype) - - def test_system_doctype(self): - self.assertDoctypeHandled('foo SYSTEM "http://www.example.com/"') - - def test_namespaced_system_doctype(self): - # We can handle a namespaced doctype with a system ID. - self.assertDoctypeHandled('xsl:stylesheet SYSTEM "htmlent.dtd"') - - def test_namespaced_public_doctype(self): - # Test a namespaced doctype with a public id. - self.assertDoctypeHandled('xsl:stylesheet PUBLIC "htmlent.dtd"') - - def test_real_xhtml_document(self): - """A real XHTML document should come out more or less the same as it went in.""" - markup = b""" - - -Hello. -Goodbye. -""" - with warnings.catch_warnings(record=True) as w: - soup = self.soup(markup) - assert soup.encode("utf-8").replace(b"\n", b"") == markup.replace(b"\n", b"") - - # No warning was issued about parsing an XML document as HTML, - # because XHTML is both. - assert w == [] - - def test_namespaced_html(self): - # When a namespaced XML document is parsed as HTML it should - # be treated as HTML with weird tag names. - markup = b"""content""" - with warnings.catch_warnings(record=True) as w: - soup = self.soup(markup) - - assert 2 == len(soup.find_all("ns1:foo")) - - # n.b. no "you're parsing XML as HTML" warning was given - # because there was no XML declaration. - assert [] == w - - def test_detect_xml_parsed_as_html(self): - # A warning is issued when parsing an XML document as HTML, - # but basic stuff should still work. - markup = b"""string""" - with warnings.catch_warnings(record=True) as w: - soup = self.soup(markup) - assert soup.tag.string == "string" - [warning] = w - assert isinstance(warning.message, XMLParsedAsHTMLWarning) - assert str(warning.message) == XMLParsedAsHTMLWarning.MESSAGE - - # NOTE: the warning is not issued if the document appears to - # be XHTML (tested with test_real_xhtml_document in the - # superclass) or if there is no XML declaration (tested with - # test_namespaced_html in the superclass). - - def test_processing_instruction(self): - # We test both Unicode and bytestring to verify that - # process_markup correctly sets processing_instruction_class - # even when the markup is already Unicode and there is no - # need to process anything. - markup = """""" - soup = self.soup(markup) - assert markup == soup.decode() - - markup = b"""""" - soup = self.soup(markup) - assert markup == soup.encode("utf8") - - def test_deepcopy(self): - """Make sure you can copy the tree builder. - - This is important because the builder is part of a - BeautifulSoup object, and we want to be able to copy that. - """ - copy.deepcopy(self.default_builder) - - def test_p_tag_is_never_empty_element(self): - """A

tag is never designated as an empty-element tag. - - Even if the markup shows it as an empty-element tag, it - shouldn't be presented that way. - """ - soup = self.soup("

") - assert not soup.p.is_empty_element - assert str(soup.p) == "

" - - def test_unclosed_tags_get_closed(self): - """A tag that's not closed by the end of the document should be closed. - - This applies to all tags except empty-element tags. - """ - self.assert_soup("

", "

") - self.assert_soup("", "") - - self.assert_soup("
", "
") - - def test_br_is_always_empty_element_tag(self): - """A
tag is designated as an empty-element tag. - - Some parsers treat

as one
tag, some parsers as - two tags, but it should always be an empty-element tag. - """ - soup = self.soup("

") - assert soup.br.is_empty_element - assert str(soup.br) == "
" - - def test_nested_formatting_elements(self): - self.assert_soup("") - - def test_double_head(self): - html = """ - - -Ordinary HEAD element test - - - -Hello, world! - - -""" - soup = self.soup(html) - assert "text/javascript" == soup.find("script")["type"] - - def test_comment(self): - # Comments are represented as Comment objects. - markup = "

foobaz

" - self.assert_soup(markup) - - soup = self.soup(markup) - comment = soup.find(string="foobar") - assert comment.__class__ == Comment - - # The comment is properly integrated into the tree. - foo = soup.find(string="foo") - assert comment == foo.next_element - baz = soup.find(string="baz") - assert comment == baz.previous_element - - def test_preserved_whitespace_in_pre_and_textarea(self): - """Whitespace must be preserved in
 and \n"
-        self.assert_soup(pre_markup)
-        self.assert_soup(textarea_markup)
-
-        soup = self.soup(pre_markup)
-        assert soup.pre.prettify() == pre_markup
-
-        soup = self.soup(textarea_markup)
-        assert soup.textarea.prettify() == textarea_markup
-
-        soup = self.soup("")
-        assert soup.textarea.prettify() == "\n"
-
-    def test_nested_inline_elements(self):
-        """Inline elements can be nested indefinitely."""
-        b_tag = "Inside a B tag"
-        self.assert_soup(b_tag)
-
-        nested_b_tag = "

A nested tag

" - self.assert_soup(nested_b_tag) - - double_nested_b_tag = "

A doubly nested tag

" - self.assert_soup(double_nested_b_tag) - - def test_nested_block_level_elements(self): - """Block elements can be nested.""" - soup = self.soup("

Foo

") - blockquote = soup.blockquote - assert blockquote.p.b.string == "Foo" - assert blockquote.b.string == "Foo" - - def test_correctly_nested_tables(self): - """One table can go inside another one.""" - markup = ( - '' - "" - "" - ) - - self.assert_soup( - markup, - '
Here's another table:" - '' - "" - "
foo
Here\'s another table:' - '
foo
' - "
", - ) - - self.assert_soup( - "" - "" - "
Foo
Bar
Baz
" - ) - - def test_multivalued_attribute_with_whitespace(self): - # Whitespace separating the values of a multi-valued attribute - # should be ignored. - - markup = '
' - soup = self.soup(markup) - assert ["foo", "bar"] == soup.div["class"] - - # If you search by the literal name of the class it's like the whitespace - # wasn't there. - assert soup.div == soup.find("div", class_="foo bar") - - def test_deeply_nested_multivalued_attribute(self): - # html5lib can set the attributes of the same tag many times - # as it rearranges the tree. This has caused problems with - # multivalued attributes. - markup = '
' - soup = self.soup(markup) - assert ["css"] == soup.div.div["class"] - - def test_multivalued_attribute_on_html(self): - # html5lib uses a different API to set the attributes ot the - # tag. This has caused problems with multivalued - # attributes. - markup = '' - soup = self.soup(markup) - assert ["a", "b"] == soup.html["class"] - - def test_angle_brackets_in_attribute_values_are_escaped(self): - self.assert_soup('', '') - - def test_strings_resembling_character_entity_references(self): - # "&T" and "&p" look like incomplete character entities, but they are - # not. - self.assert_soup( - "

• AT&T is in the s&p 500

", - "

\u2022 AT&T is in the s&p 500

", - ) - - def test_apos_entity(self): - self.assert_soup( - "

Bob's Bar

", - "

Bob's Bar

", - ) - - def test_entities_in_foreign_document_encoding(self): - # “ and ” are invalid numeric entities referencing - # Windows-1252 characters. - references a character common - # to Windows-1252 and Unicode, and ☃ references a - # character only found in Unicode. - # - # All of these entities should be converted to Unicode - # characters. - markup = "

“Hello” -☃

" - soup = self.soup(markup) - assert "“Hello” -â" == soup.p.string - - def test_entities_in_attributes_converted_to_unicode(self): - expect = '

' - self.assert_soup('

', expect) - self.assert_soup('

', expect) - self.assert_soup('

', expect) - self.assert_soup('

', expect) - - def test_entities_in_text_converted_to_unicode(self): - expect = "

pi\N{LATIN SMALL LETTER N WITH TILDE}ata

" - self.assert_soup("

piñata

", expect) - self.assert_soup("

piñata

", expect) - self.assert_soup("

piñata

", expect) - self.assert_soup("

piñata

", expect) - - def test_quot_entity_converted_to_quotation_mark(self): - self.assert_soup( - "

I said "good day!"

", '

I said "good day!"

' - ) - - def test_out_of_range_entity(self): - expect = "\N{REPLACEMENT CHARACTER}" - self.assert_soup("�", expect) - self.assert_soup("�", expect) - self.assert_soup("�", expect) - - def test_multipart_strings(self): - "Mostly to prevent a recurrence of a bug in the html5lib treebuilder." - soup = self.soup("

\nfoo

") - assert "p" == soup.h2.string.next_element.name - assert "p" == soup.p.name - self.assertConnectedness(soup) - - def test_invalid_html_entity(self): - # The html.parser treebuilder can't distinguish between an - # invalid HTML entity with a semicolon and an invalid HTML - # entity with no semicolon (see its subclass for the tested - # behavior). But the other treebuilders can. - markup = "

a &nosuchentity b

" - soup = self.soup(markup) - assert "

a &nosuchentity b

" == soup.p.decode() - - markup = "

a &nosuchentity; b

" - soup = self.soup(markup) - assert "

a &nosuchentity; b

" == soup.p.decode() - - def test_head_tag_between_head_and_body(self): - "Prevent recurrence of a bug in the html5lib treebuilder." - content = """ - - foo - -""" - soup = self.soup(content) - assert soup.html.body is not None - self.assertConnectedness(soup) - - def test_multiple_copies_of_a_tag(self): - "Prevent recurrence of a bug in the html5lib treebuilder." - content = """ - - - - - -""" - soup = self.soup(content) - self.assertConnectedness(soup.article) - - def test_basic_namespaces(self): - """Parsers don't need to *understand* namespaces, but at the - very least they should not choke on namespaces or lose - data.""" - - markup = b'4' - soup = self.soup(markup) - assert markup == soup.encode() - assert "http://www.w3.org/1999/xhtml" == soup.html["xmlns"] - assert "http://www.w3.org/1998/Math/MathML" == soup.html["xmlns:mathml"] - assert "http://www.w3.org/2000/svg" == soup.html["xmlns:svg"] - - def test_multivalued_attribute_value_becomes_list(self): - markup = b'' - soup = self.soup(markup) - assert ["foo", "bar"] == soup.a["class"] - - # - # Generally speaking, tests below this point are more tests of - # Beautiful Soup than tests of the tree builders. But parsers are - # weird, so we run these tests separately for every tree builder - # to detect any differences between them. - # - - def test_can_parse_unicode_document(self): - # A seemingly innocuous document... but it's in Unicode! And - # it contains characters that can't be represented in the - # encoding found in the declaration! The horror! - markup = 'Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' - soup = self.soup(markup) - assert "Sacr\xe9 bleu!" == soup.body.string - - def test_soupstrainer(self): - """Parsers should be able to work with SoupStrainers.""" - strainer = SoupStrainer("b") - soup = self.soup("A bold statement", parse_only=strainer) - assert soup.decode() == "bold" - - def test_single_quote_attribute_values_become_double_quotes(self): - self.assert_soup("", '') - - def test_attribute_values_with_nested_quotes_are_left_alone(self): - text = """a""" - self.assert_soup(text) - - def test_attribute_values_with_double_nested_quotes_get_quoted(self): - text = """a""" - soup = self.soup(text) - soup.foo["attr"] = 'Brawls happen at "Bob\'s Bar"' - self.assert_soup( - soup.foo.decode(), - """a""", - ) - - def test_ampersand_in_attribute_value_gets_escaped(self): - self.assert_soup( - '', - '', - ) - - self.assert_soup( - 'foo', - 'foo', - ) - - def test_escaped_ampersand_in_attribute_value_is_left_alone(self): - self.assert_soup('') - - def test_entities_in_strings_converted_during_parsing(self): - # Both XML and HTML entities are converted to Unicode characters - # during parsing. - text = "

<<sacré bleu!>>

" - expected = ( - "

<<sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>

" - ) - self.assert_soup(text, expected) - - def test_smart_quotes_converted_on_the_way_in(self): - # Microsoft smart quotes are converted to Unicode characters during - # parsing. - quote = b"

\x91Foo\x92

" - soup = self.soup(quote, from_encoding="windows-1252") - assert ( - soup.p.string - == "\N{LEFT SINGLE QUOTATION MARK}Foo\N{RIGHT SINGLE QUOTATION MARK}" - ) - - def test_non_breaking_spaces_converted_on_the_way_in(self): - soup = self.soup("  ") - assert soup.a.string == "\N{NO-BREAK SPACE}" * 2 - - def test_entities_converted_on_the_way_out(self): - text = "

<<sacré bleu!>>

" - expected = "

<<sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!>>

".encode( - "utf-8" - ) - soup = self.soup(text) - assert soup.p.encode("utf-8") == expected - - def test_real_iso_8859_document(self): - # Smoke test of interrelated functionality, using an - # easy-to-understand document. - - # Here it is in Unicode. Note that it claims to be in ISO-8859-1. - unicode_html = '

Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!

' - - # That's because we're going to encode it into ISO-8859-1, - # and use that to test. - iso_latin_html = unicode_html.encode("iso-8859-1") - - # Parse the ISO-8859-1 HTML. - soup = self.soup(iso_latin_html) - - # Encode it to UTF-8. - result = soup.encode("utf-8") - - # What do we expect the result to look like? Well, it would - # look like unicode_html, except that the META tag would say - # UTF-8 instead of ISO-8859-1. - expected = unicode_html.replace("ISO-8859-1", "utf-8") - - # And, of course, it would be in UTF-8, not Unicode. - expected = expected.encode("utf-8") - - # Ta-da! - assert result == expected - - def test_real_shift_jis_document(self): - # Smoke test to make sure the parser can handle a document in - # Shift-JIS encoding, without choking. - shift_jis_html = ( - b"
"
-            b"\x82\xb1\x82\xea\x82\xcdShift-JIS\x82\xc5\x83R\x81[\x83f"
-            b"\x83B\x83\x93\x83O\x82\xb3\x82\xea\x82\xbd\x93\xfa\x96{\x8c"
-            b"\xea\x82\xcc\x83t\x83@\x83C\x83\x8b\x82\xc5\x82\xb7\x81B"
-            b"
" - ) - unicode_html = shift_jis_html.decode("shift-jis") - soup = self.soup(unicode_html) - - # Make sure the parse tree is correctly encoded to various - # encodings. - assert soup.encode("utf-8") == unicode_html.encode("utf-8") - assert soup.encode("euc_jp") == unicode_html.encode("euc_jp") - - def test_real_hebrew_document(self): - # A real-world test to make sure we can convert ISO-8859-9 (a - # Hebrew encoding) to UTF-8. - hebrew_document = b"Hebrew (ISO 8859-8) in Visual Directionality

Hebrew (ISO 8859-8) in Visual Directionality

\xed\xe5\xec\xf9" - soup = self.soup(hebrew_document, from_encoding="iso8859-8") - # Some tree builders call it iso8859-8, others call it iso-8859-9. - # That's not a difference we really care about. - assert soup.original_encoding in ("iso8859-8", "iso-8859-8") - assert soup.encode("utf-8") == ( - hebrew_document.decode("iso8859-8").encode("utf-8") - ) - - def test_meta_tag_reflects_current_encoding(self): - # Here's the tag saying that a document is - # encoded in Shift-JIS. - meta_tag = ( - '' - ) - - # Here's a document incorporating that meta tag. - shift_jis_html = ( - "\n%s\n" - '' - "Shift-JIS markup goes here." - ) % meta_tag - soup = self.soup(shift_jis_html) - - # Parse the document, and the charset is seemingly unaffected. - parsed_meta = soup.find("meta", {"http-equiv": "Content-type"}) - content = parsed_meta["content"] - assert "text/html; charset=x-sjis" == content - - # But that value is actually a ContentMetaAttributeValue object. - assert isinstance(content, ContentMetaAttributeValue) - - # And it will take on a value that reflects its current - # encoding. - assert "text/html; charset=utf8" == content.substitute_encoding("utf8") - - # No matter how the tag is encoded, its charset attribute - # will always be accurate. - assert b"charset=utf8" in parsed_meta.encode("utf8") - assert b"charset=shift-jis" in parsed_meta.encode("shift-jis") - - # For the rest of the story, see TestSubstitutions in - # test_tree.py. - - def test_html5_style_meta_tag_reflects_current_encoding(self): - # Here's the tag saying that a document is - # encoded in Shift-JIS. - meta_tag = '' - - # Here's a document incorporating that meta tag. - shift_jis_html = ( - "\n%s\n" - '' - "Shift-JIS markup goes here." - ) % meta_tag - soup = self.soup(shift_jis_html) - - # Parse the document, and the charset is seemingly unaffected. - parsed_meta = soup.find("meta", id="encoding") - charset = parsed_meta["charset"] - assert "x-sjis" == charset - - # But that value is actually a CharsetMetaAttributeValue object. - assert isinstance(charset, CharsetMetaAttributeValue) - - # And it will take on a value that reflects its current - # encoding. - assert "utf8" == charset.substitute_encoding("utf8") - - # No matter how the tag is encoded, its charset attribute - # will always be accurate. - assert b'charset="utf8"' in parsed_meta.encode("utf8") - assert b'charset="shift-jis"' in parsed_meta.encode("shift-jis") - - def test_python_specific_encodings_not_used_in_charset(self): - # You can encode an HTML document using a Python-specific - # encoding, but that encoding won't be mentioned _inside_ the - # resulting document. Instead, the document will appear to - # have no encoding. - for markup in [ - b'' b'' - ]: - soup = self.soup(markup) - for encoding in PYTHON_SPECIFIC_ENCODINGS: - if encoding in ( - "idna", - "mbcs", - "oem", - "undefined", - "string_escape", - "string-escape", - ): - # For one reason or another, these will raise an - # exception if we actually try to use them, so don't - # bother. - continue - encoded = soup.encode(encoding) - assert b'meta charset=""' in encoded - assert encoding.encode("ascii") not in encoded - - def test_tag_with_no_attributes_can_have_attributes_added(self): - data = self.soup("text") - data.a["foo"] = "bar" - assert 'text' == data.a.decode() - - def test_closing_tag_with_no_opening_tag(self): - # Without BeautifulSoup.open_tag_counter, the tag will - # cause _popToTag to be called over and over again as we look - # for a tag that wasn't there. The result is that 'text2' - # will show up outside the body of the document. - soup = self.soup("

text1

text2
") - assert "

text1

text2
" == soup.body.decode() - - def test_worst_case(self): - """Test the worst case (currently) for linking issues.""" - - soup = self.soup(BAD_DOCUMENT) - self.linkage_validator(soup) - - -class XMLTreeBuilderSmokeTest(TreeBuilderSmokeTest): - def test_pickle_and_unpickle_identity(self): - # Pickling a tree, then unpickling it, yields a tree identical - # to the original. - tree = self.soup("foo") - dumped = pickle.dumps(tree, 2) - loaded = pickle.loads(dumped) - assert loaded.__class__ == BeautifulSoup - assert loaded.decode() == tree.decode() - - def test_docstring_generated(self): - soup = self.soup("") - assert soup.encode() == b'\n' - - def test_xml_declaration(self): - markup = b"""\n""" - soup = self.soup(markup) - assert markup == soup.encode("utf8") - - def test_python_specific_encodings_not_used_in_xml_declaration(self): - # You can encode an XML document using a Python-specific - # encoding, but that encoding won't be mentioned _inside_ the - # resulting document. - markup = b"""\n""" - soup = self.soup(markup) - for encoding in PYTHON_SPECIFIC_ENCODINGS: - if encoding in ( - "idna", - "mbcs", - "oem", - "undefined", - "string_escape", - "string-escape", - ): - # For one reason or another, these will raise an - # exception if we actually try to use them, so don't - # bother. - continue - encoded = soup.encode(encoding) - assert b'' in encoded - assert encoding.encode("ascii") not in encoded - - def test_processing_instruction(self): - markup = b"""\n""" - soup = self.soup(markup) - assert markup == soup.encode("utf8") - - def test_real_xhtml_document(self): - """A real XHTML document should come out *exactly* the same as it went in.""" - markup = b""" - - -Hello. -Goodbye. -""" - soup = self.soup(markup) - assert soup.encode("utf-8") == markup - - def test_nested_namespaces(self): - doc = b""" - - - - - -""" - soup = self.soup(doc) - assert doc == soup.encode() - - def test_formatter_processes_script_tag_for_xml_documents(self): - doc = """ - -""" - soup = BeautifulSoup(doc, "lxml-xml") - # lxml would have stripped this while parsing, but we can add - # it later. - soup.script.string = 'console.log("< < hey > > ");' - encoded = soup.encode() - assert b"< < hey > >" in encoded - - def test_can_parse_unicode_document(self): - markup = 'Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' - soup = self.soup(markup) - assert "Sacr\xe9 bleu!" == soup.root.string - - def test_can_parse_unicode_document_begining_with_bom(self): - markup = '\N{BYTE ORDER MARK}Sacr\N{LATIN SMALL LETTER E WITH ACUTE} bleu!' - soup = self.soup(markup) - assert "Sacr\xe9 bleu!" == soup.root.string - - def test_popping_namespaced_tag(self): - markup = 'b2012-07-02T20:33:42Zcd' - soup = self.soup(markup) - assert str(soup.rss) == markup - - def test_docstring_includes_correct_encoding(self): - soup = self.soup("") - assert ( - soup.encode("latin1") == b'\n' - ) - - def test_large_xml_document(self): - """A large XML document should come out the same as it went in.""" - markup = ( - b'\n' - + b"0" * (2**12) - + b"" - ) - soup = self.soup(markup) - assert soup.encode("utf-8") == markup - - def test_tags_are_empty_element_if_and_only_if_they_are_empty(self): - self.assert_soup("

", "

") - self.assert_soup("

foo

") - - def test_namespaces_are_preserved(self): - markup = 'This tag is in the a namespaceThis tag is in the b namespace' - soup = self.soup(markup) - root = soup.root - assert "http://example.com/" == root["xmlns:a"] - assert "http://example.net/" == root["xmlns:b"] - - def test_closing_namespaced_tag(self): - markup = '

20010504

' - soup = self.soup(markup) - assert str(soup.p) == markup - - def test_namespaced_attributes(self): - markup = '' - soup = self.soup(markup) - assert str(soup.foo) == markup - - def test_namespaced_attributes_xml_namespace(self): - markup = 'bar' - soup = self.soup(markup) - assert str(soup.foo) == markup - - def test_find_by_prefixed_name(self): - doc = """ - - foo - bar - baz - -""" - soup = self.soup(doc) - - # There are three tags. - assert 3 == len(soup.find_all("tag")) - - # But two of them are ns1:tag and one of them is ns2:tag. - assert 2 == len(soup.find_all("ns1:tag")) - assert 1 == len(soup.find_all("ns2:tag")) - - assert 1, len(soup.find_all("ns2:tag", key="value")) - assert 3, len(soup.find_all(["ns1:tag", "ns2:tag"])) - - def test_copy_tag_preserves_namespace(self): - xml = """ -""" - - soup = self.soup(xml) - tag = soup.document - duplicate = copy.copy(tag) - - # The two tags have the same namespace prefix. - assert tag.prefix == duplicate.prefix - - def test_worst_case(self): - """Test the worst case (currently) for linking issues.""" - - soup = self.soup(BAD_DOCUMENT) - self.linkage_validator(soup) - - -class HTML5TreeBuilderSmokeTest(HTMLTreeBuilderSmokeTest): - """Smoke test for a tree builder that supports HTML5.""" - - def test_real_xhtml_document(self): - # Since XHTML is not HTML5, HTML5 parsers are not tested to handle - # XHTML documents in any particular way. - pass - - def test_html_tags_have_namespace(self): - markup = "" - soup = self.soup(markup) - assert "http://www.w3.org/1999/xhtml" == soup.a.namespace - - def test_svg_tags_have_namespace(self): - markup = "" - soup = self.soup(markup) - namespace = "http://www.w3.org/2000/svg" - assert namespace == soup.svg.namespace - assert namespace == soup.circle.namespace - - def test_mathml_tags_have_namespace(self): - markup = "5" - soup = self.soup(markup) - namespace = "http://www.w3.org/1998/Math/MathML" - assert namespace == soup.math.namespace - assert namespace == soup.msqrt.namespace - - def test_xml_declaration_becomes_comment(self): - markup = '' - soup = self.soup(markup) - assert isinstance(soup.contents[0], Comment) - assert soup.contents[0] == '?xml version="1.0" encoding="utf-8"?' - assert "html" == soup.contents[0].next_element.name diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/__init__.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 8ba5c2dcca29689f2103f7004da526540fc370c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67411 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 diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_builder.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_builder.cpython-312.pyc deleted file mode 100644 index b988d5c37a7b5c7496b83c51fd8611a5ed81574e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1571 zcmah}-D?|15TCs-%Ti>UT8Tg6#EM)>)K)su)R16B!6h`M*dkC-5`}V{?^d#`lTN)| z*^wecTMT{4L;B>9m!y4Zi~ouCtxrbN9oP$(4oP>8L9!B5@2^HDWX=m_R!cIP*{ zGxJ;h7>$O3$sh7xrK=La@7xK5`JVJHu+KJ_U?K|&{3}?fDij37ZP5~|Qb9r>z*R7% zEimOB!3P%PCQ2%QawnHWu3XotvC51SS1`o}CD)giuIUcJ<|277zr1AlC|}D*PA|`l zZNN}KCKLoLu7&!;e0weO;+ly{?4n*0cB^V7<)qMhC1=N(9XGLI>5fjzcI{oZJe^skRV!<+te5Quv6^vSQ%2>B zd^?f3%t2W{YSEw#-C{x4|BcG>Fx3mo#``40Z7+A;DI1j+F|i)JALlxFAXhqKd*5_-F}WQ=-9$V2x*gPTEp{*p%CH zTd14`Aj13b8EOm8NPFNI$(Xl4aL@6v;-FCnV?}T$C&4ghCHn<~N6>^hI0po6Fvi{h z#C}b_nb=7WW6IKt9BKu#ge0wl%cDZRZUUG4ouIh>$tYATIChB-lVH`?R@&&TPi72oT}?aMK58Z zvXWKG$WJ`21=ZJ^Zh|j+<-W9>)}@!foAm#~hgcD0i>XiG?`aqr?~GsCjb@)gXgKlR ztKG@d50$T@Uq-(v?#Aaklk@v96iwWfew|VuPc1*1TK>V@o%-Oe(w#W<@bpg;YG+LC zOsKz%pXr{QeXwwUp%Z)U-okIQa}RFczuk$we(!R3EVe!R#pustXZA)}rUQ{3bHLBq zM3!!!jEdw~uMs$L!4>?I^6btW&PU z$LB`s?2n*|sZ(xYC&p5K3q7X68Rv?R%~RYUZ!on5T{-gk%};MWmS-NxGu_bazMu?; zd-AZN?8PE-qIW#7oS6X4m^aC6H`=I`DL*{TDdMv+(nn&ClK!D5Io3>B0}g1M4!U!Q%D~uCs1M^nDUVS0PlW|vH$=8 diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_builder_registry.cpython-312.pyc deleted file mode 100644 index 60fa1341485327687646d528459e705f3309e808..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7595 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 R^n1^0vbY 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 qZ3;=}Al>tr02Ym;$o>KF!miClnC!0sjVP*YZ*T diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_filter.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_filter.cpython-312.pyc deleted file mode 100644 index 43f98bf7b50dca597321083f9f1739a0eedb9b72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31904 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 Mul$N*5jJ4|4?uc%-2eap diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_formatter.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_formatter.cpython-312.pyc deleted file mode 100644 index 072138869dac8768f828a2f597ca8aec7295f34b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7797 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 ZfZsU@)BH&IAN_KLgz@>8bz# diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_fuzz.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_fuzz.cpython-312.pyc deleted file mode 100644 index d320c40d4c51d3f5713bcb819faf18cfc3de0e35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7036 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 X=4oy16f^EdcibK0`=~nu1myn#-tV;? diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_html5lib.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_html5lib.cpython-312.pyc deleted file mode 100644 index 4e41695b028b738dd48af2d69a8869be097c8a96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11959 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 JAT&pp_5Uf|=A8fl diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_lxml.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_lxml.cpython-312.pyc deleted file mode 100644 index 35ba915570ec05d690c0db4b2cc30fdd8e07ca74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8094 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

Q`o^xW>5-96ot+1NS1(VxbDBh{a+ zd#3hIj?MJU9#3!4Gka3}t_4@c#PP|>dDq6YYvc5hdoC#Y#v9irufcybb7Z#cy)${f z*tNPPyM1n!qmz{09PQ0{@Y~0|LJz@ZSg&g)F~MWdv#nSALw(9{r9*do5y-Elz|SYis~+ zw`0>{qXYZ&t7{zREQ?#6j*i6|x1)8j(dpQ>SYvlIEmdxC9I~(>vkrskD|?`Gb}TjG zCqE>Ko%H%gAxCX+#l|o*zqBR!L<0(F&zhnU)8vKo5&=N@exZiyC=1NPln$M=HBGFbN2Sx*)5q( z?P=HgiL$B2g_a%P8+mW!Cp|MGnU_>|ax$21ku9t=AoE%_k;z8)$l!>TnT z${*vhgnYE`lu#Z0J0%5#L*=tXGJk@$pPOVzDKtzSe{=l1_L*0{Q$5GGr(EqRzMabJ zrnbHLjdurT8s7=e8Cgj9Ru$@>$?#3zy)fIBd8X$cf9hvP|EBS$@FMBkHS;!Y_CrS& zWsLj}di%!&ip1qVP#J++^ipI-y}>Qos~p~?r>c<1p-Dfw@2%I;PFURILu%DbfJH?} z%BnVeL{;;$SK!R}U@z0zY_+4hsdx|pd3?W+{0Ay0li8m#O1bAq(SS-KcI)2Ah{FbX?|J}dk`2Wmp{?ux-SU+)bmaU&ytrqJecdw;+ zs^<}hpGV)cB(0YAsaGCx^!q63IBK;VvP=y>;@HWfe*06F)0U~8PdNHzGw^=_=AZTb diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_soup.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_soup.cpython-312.pyc deleted file mode 100644 index 7e58d8a4354c6a14a81b39cca9e93e6b734a4cc4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31496 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 Y&r>Y!pbPl9SHGKXIsYSpe%VC)pSN5x0{{R3 diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_tag.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_tag.cpython-312.pyc deleted file mode 100644 index 4226b510c4f272787bda76f728b698996cd656f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14116 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 diff --git a/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_tree.cpython-312.pyc b/venv/lib/python3.12/site-packages/bs4/tests/__pycache__/test_tree.cpython-312.pyc deleted file mode 100644 index 93ad22105f03ae71aabc2355dc56a1f94e596a2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 93179 zcmeFa30z!PdM8>dT%h2x3n3(x03o3T1ZX!xmXNUJ1uv2}*=|yBO9+`oeXGz?jcoVC zlYzGTCz0+%DBUl{Jv}jso!2DuCZkCv8MU2EJTG~ZDhdUq;z=}FW?s*mm!Dg7$BAZn z@Bf{1_c{forL#@0t;4N*&pG$rbH4ri&Ub#hurS|+<3IWT-~L^{=W_iC{m>7;cCz?i z+%DH;m*P6^QrwDX(0$y^{(6pk*kA8)FaCN5eMA1^emB+e4dx8x9?xax{y}Ld?|9x& z{_*^wg5w24f#ZRp!sCVPUd~|AkbGRmd9ET277vviFLAp(u18!--dipuKV0&Gm%qdD zQg*cfR|A%-W$bDpt`=FYmb0ret`=LaRI!zX0#_?7SF707 z6}Vbuxw?{FU5TsJmaEn5>MC5V30E6mv5H+?jjL-cS8LeSwYVCz^st&;U5Bf+;nhYD zYuME~T&=fUUCXYn$JGW)55azyvf*3qK2ZKjPMo({u1fyy=j3RUT9E?x1en_ z7(ySyHhrPtV6XALVFizio@9M!A0CWisBrxx-l{48djzrFjqX&T(HngcE)=s@468kA zxPKrLRnIs2Q|k^yqv`;jAAU9*2@mxSh9l31)PWFAUI?kf7@3s6^H3-nO67Kr3=QF{ zQ*w9c%s@ZYIEtpI;5`=VNB04G3@%}S!|L}igDzZ@=ps#JA4eo!(oH%R_oBG$3cG;O zF2ZJDvga+=ai8Kv=~sLxa}++vsvdJde5lk^8)>(bpXdwud@e+M7ci?Y$kX?ajR%_}!-c-cG+$ z?%tHUwb7gMMKF9RAALtE2UCXOzUsl%@Zbrx6x~NWD1yN|N1IQM427Fd^sAxB*1k~l z;NZ~K=s@3V;b>bkAnr`_;6QKl>GQyo;kKrh*5=4SG`#h6sP8r4K%}`hvb~vLD8kAf z!l0(p=Tn7rt%si716+w!>O3H_zZ@(59`uLaC z{*V7zq`eteeprZGw#!%DYB{bode}&-WjI$WP-tVWuE2S!l8wda@Ic>)67GqH&+!3^ zt+fwUT7?GcXcG#{sI?^JR%6trP*O;>Pl3%4H*F&1K-zilFg7s z4d5L!fEvut1F+VaEqc-q#rvU8AIeiX`c?CA_KC%mi zW&95$<%8qCPo;wKL+|9>lvhnf-#vfj{LE8R=aXyO7uFs~tUWL%ABal_67qrc$)Evb zlhKQlY$ikTSf@iY0Uw|zI`m1f47j(^7i**s4T3w2oQ@6*4a7pxfe~UZp(rDK5yn!0 zxsj$j<)APpMn*Im(;HHW%6yNANB32)Ht2)l;grO%9jqvQ%*)xBv-@E%N6-=wqu6Tu zU^{L%;{h6!-_mJAGoYHFy!h*#Q@(c#uM~bmPL^++lQ+htjR|>U`oI$8v4K@^@?Zv5 zF-U}9Xnl?T*hAS4Eoa6djj<1dsW-*ehz1+idP6aq0G040j zhx(6gSaQhCirdk7!r=oG#|JIpydm8)Mf|7O{@SNvuc2A*g3sh?%nH)rjo?aIKJj`n6&p2o@Pj+7Ta zQts1N{U#$x`DiLr6%1catKl;PBcqX?$UyHP2~;KQ@-Q(I?NU0Fa1zKWa?lv*390>~ zB%wu|Bv4#y556yQ28D$LZcWNf1Rv!<&Acml-zZq9+L)-)urn@iH115-eWPfhsy$KF zo~-IvsOn5qb#g`(mpgCDrI(b;1Cs;O{$yptLgns6;IQttTcgt6|%f|S(5XlGAPD!->^Xhazu4C6e|)APmA&>*2A ze&zP`C?kD6J!%yV)@my1s31{6B>`96K?Mm7S6vKxnFy#B(N!we;9sN(#apiLd)$8M zc8FTOhW$(+>Vhf=NV4dESv5X_ z*NwzbSQyP?N%?V85CN-MsM?f(BvQ2{S-y2n-Wr#-#^tTLl!*JB;p|IP?MqhePnJJC zCqEpQ9*)ZoTkEV(R&89UdMHu#P!jdZJLcq$xYUu5JJOkrA+A?u3EG(?2dlc-?>6O_ z4E24Ar{7~~!+tNalK31!QoZ@~GidZr{kz>4Cv;It*8t+>5}F-lm7WjVb=51FKo< zDLgUq4vIHj4)K_NUYNKreR%vrQr2O>=thN63!S^3~@3EO^vVJ?&+A+5Wn*397>8ZHUH2bfUll)H@+ zd;-Pq<)diyt8~ups!y{j+f(ixDh;cls27DIFhoN&2oHw)q7lv#(qy|bJ9e-~n^viG z#9$R(!E+*Sqp;vaXHq@{N-YHzq*V!N)zqPPpS<$qOx^4=Q%@#qcKyoQdFe=|o7d{D zRm@BK({DdZZFkS@JvuKP14`u;3j3bh^Xv`jXgcXOP~uy7(`*z{F(7+fWAG+f5kT?Z zGuY;Qn5#<*ie&8t(m-B!Y@GoxWbqA=iEIPxF&i|qFN`rNK?(wN%H=#f1klH7X+B0c&AV)(chYq7|MoSW-4GBr7Y$3-4N zVd3HJNqL_IGOiq&E}Jq^&jc&aN|vt=eS6TTsBUt(7GW=ZJ! zT^BrK9wCV`?D1~bGOW|Wig&m!c>4hprvy^wn9-w!ReN8-n_lpZ`A!k;I*w>SzhJhA z%KA05p$T*xIs{$tkHPn0w#$R>lm64mtJ`(nRp)APMcijSZr4jLH~u^CI_G`Kb=KYJ z@4k}@Xd~)#3`8eK4flVKL`%PY6yZh2p3TB<(He9nqGZ17##_Q&WsEw zj0T<_iNNeIFgOrB&j{f#zy{P1w6Jefjljm()R@O@hB=|rr^9efNN2gPD3U7b3q|`* z_UOMkABR;D#ziuCKo6sHC|T?9?Wx?Ma3lg3L}QLhmU-T3F7s}LPo&&uQ@L74Deq9E zKSGF4KAd2X8{d!FX&lo=sWBW}+(S1I8thTvyy}5Ld9)9dJPZ{t9D$e+1x}1c!aW1p z$DxV#aj_puLk_!~eBV!a4WAKt55=1FN`GPN=(*Nyvbm6ng^-jw8vMH5Ar&dy6~ ze;~PvDi;dt6NU9Nhvo}gK66QVMYGS`EUTC*e|Pnj)zfE_E1T!an&W}ycv}T4_w0hl#MUuTW*y$S z?<|u*ZD7s4wDy0PlU@7sxs6h6J@}>}20$(z9MmO*U?>O&>gZtfXgI3AjPYRf96q~| zQME68Ons3qk@(xKQ*qMdQn@EX5pqnx2yY?)P?ma%(AXNVzQPXcT9t4#R+kxEjY@Bz zr^p}*gRg7wcC)17^6JUeQ;}pz-FVKYa^JC-HivUWNlQ*-K#!CMJE-HQSm$#FHv!lieW0+sUUY3x3F~385Ldl7g>+u zE!Xe+ns57j{{6QD1!P~Tmi))ux68f$9k=sK{Y8r#^Zkvy2Wr=cf5ri#&5lK4rdGoW zoXTE=A9z#MmLX+ElWx$i2;8ONhz$WqqNYh&{E+puy!$u{+cqJU<1iV4;>&;pekEtX zZHgcwEz#@+B8k);+txl5ik=)A+&dKcq8cT!)%F`gO5{xcUQp}7eYI*>sqIjo#e2m9 z)>;h6W0GDmc`ht=i1dbE z#j_&x#ukC)@ud6&869-J4a&8640o*1iO`55ghlue9N`0``dL^+ z4hxIOWnmE#3ya93(52(~NRqpAB(-{E}@ct7; zj?f!x;zl3>W$<(lkGhGiNgKo_>;0dm#zevZf8|w|k4zr<%;j18n0wLXsd(Hy?)z$9 zx(IC0lP{oMCWeYp)?oy-^h2oK8$NzgbNW3xJ0)T9s;`?N@11;e{O=T4Mg|;-=^13V z<0|HtaAqBjl~If%^AM0y+yfNEh;pReoIW-gD}RH!Z9oCuWKlAYTsg8()0C)bnu#Q9 z+GYo@KN;U4RtE{G7!)4FTs??UQ%EV$#u(N*yCuVbU_4bj?q)_5pS5o&oR(P;KO){|iTKl!8 zA9y`^`JYLKb-`J6JFB{Fw*C6*cEF4r#dk?&DV;U#QuZsM$7KmaN%vt#I~@8`2|7j3dd4ON=8C z0LNh+A1C=!Uq@v`b{Qj+2EBGmiZ%#P7tf5m1_e^r2xB(!gt1b)Jtb4aU&QkxYf)HW z8KyN*z3IMhbkDqUZC`xLksH!u=_5iY&dA+8K$gG+Y?2IfymXByoo(=Ovp^IFC$fK} zjo@lKOlkZ9nm7v(jWsU^PmTuv2aOncS1luEL+Njh&2%Q$Zc7GQW}mpeHQx604~YPz z4*7e;p6dqcVjYX8PEyFR^wS7I|8lWW_Of$f=x&=7=GHiU}%Ef-?1#nIUY0Kpn8c362t!m$|u zt9TWkRSW~l`t5p-4{t$Q>>}9`*o@+@^AJDWB&wu;A0@3v4WcRFnzZ4Rw?7<(szIP) zm96Cgr3Z?3-$^o7l79B=a@fv{pODZZyd9bUxuVk4J~#qPRivZI(dYj~&(t)OvdYW5 zCwEUp-aUKe>~!=S7ZPP#;(;xUcE*0Zo%t(jL$w`G(klg9meLAr|FYPP{nKr;?fY|lN9@Bc{; zC9VHW*XFq- zGA~Uq&8R?-3?*PxnUR;eR&;^lC=q+R=3u zU>Ea-f(jMA%t^-_ckpMF;#2vW0aHUF2F%wKSp6LywFQw5t@zi5f7{c%99$A*)Rw{T z5NyK(J!e9LqhY1Th-%L$i7wah_wZ7YpG5)DfX8Ux3_QQ+^%Um=Y;#;ir59hCcD9ydk+%=So;FwIC>ZyUZUbB zsrWh-KSRYd6%MQ2S-M8W*YGcL00kMGw=Md-{>Kr;=OJ6O6!7QYuJQOE#i^Sv=Xh}e z!F?!vC=lC+BH#bKd$B6tA7t;(`s_n@#sTDJ$0Awht>!)$>+WJL6f^o2Fr#098T|^G z(XWUZ{bZ#Gy%j51k$AjBDMnd(zNE1D`1?AzpCX&FXv~lK{9^ESQ%*`y03Gsos&U4 zGf>Y%$QA!kzBLF*xUUno)OuD!s3kl%;l?Ix9IW}*MbD(8wM1ObG<;p8_?LV zUx@E|?uPXI61&bye}MI0-YqX1cy zFbqiqnkoP3Fg#%?A34@p)rb$53HZ5J-omdmh@+RXfGcBNvG#1?Rn+>=@x%y`Z!oRm z>V@KUiQ;wB4awrhasN%ZaY5dez|y(Oq`aHlJ#10pRQcO);74)!<($c!@pDt#-`#g* z-^}RLzT~PMMtEP^?eC0T9lO?*Z0@9bhvwu%ap_Q8KBU!~I2V^5;ePm;aD2z%_|~qe z)yb8QB&A0t&Mko!u53lRd#0rhqqV>~1_4fB4O0Ay2aZI;P<$VOe3Fu9>nY#*PN41u z-Jxw5hb0L-sXqH^scfm$1h!fxw?VP!#?`Ep3SffSPpiG3*4mCvk^}F)qc(d-ZFnJ_ zUo6Lg*!OfCU|uzfAwV$B26k-&TJoEjMl@ zVSid<0qeIjbxM7o5Gz~0!|W^fz;~$KU(katpa9>ID5w@eFrT^n)vFg>{^B*@JH<}E zbCv}h#`iuG-}CIebkyoBLPX+h<+T;@Z3n2%!RxPHe`;Pj=B%;e+Q#^{PO5R}`s?wo z=Wj?aEPQ*HrIsY{b1V;uZVz%s2{)!!T@LE$9@-vE^(gW)p)Xam&XNPw5ptWhr-fd!OE< zEx28OwKgmvR)X6>d-|3Thq)P+qEacSkbPcHOwvD29mfr(|Hg{=HN96BHKGzJ%0OWF z3VN$Ck#!#1nyq}ms!L!cksmU0qA`3MF)4Ktle*bHA_OqOTzf(o!OU;R_dOYJ@1B>Q zG8~RZ{IjEiAdH!Nu20RrGA|u;w4e3T)3?vYuJ4WS6!y;=$9HzccRVsLJ?dyaQ)jt- zLwa-xGB%d2tZ|>FA(Mw@ zuO3a94+LXwHsT)B_ zX-v6K*iE3@OvMpOBSV&+vnRvDJ zJCgE#gt@|N|K!AzQ|mwUd?){E{%qR^^7xZ*+mE|VKtC{@KQ%TlZMmDekR)KAvi7_q zxp5D5y*I7v8xpr~+sqxLOflc!#%$5%u0-@@d^u)T0+PURz%gNoKB0)Oj7|=*IFA5% zorm>X!pA9U3>x!Yz5AFM6JvWTfOu|qY?Z;lHaLJA2@gn>OnGpf{A;%Hrm-%=zr{5u zF1w-_b$*N)NiP)lYlp~lauuGFCvX#z??(0~d9UCrt8zP%1fhP+dJ)^?1%@} zr4#AwzP_5iUi}U9sQxAu{}zSyqbnjq^a0M#W?7fIbhlk5d(gdow(yDD(?7gqa(_Hf z%RXGse!wCw>@-X>EO7Gn34J2-srYbaS{3%1WbAIIEB4F-hX7g+9eD#UXc*1oD|aSk zczPU4$4uRa>UUySW7q1F&HIxz4`1JVeG9~i+dg+*tw3amHy=#abY6#k^C(rR6IMBt ztU3Hi{`IjN(y?@yG7Pql;uW(p*k)kEx+KngI37?7&lo&Akrl90WoTh~noJwj7~;x3#a;$#kCXuarb!Z&Ek?vtrKVCQVY-cGu=0{BU#mwlv>8m;@(6A ztGzEBy8Ptilhbw6qgVi*l(vpXz|2cZ$0JB3GBi0f-8q|gX$Y~{bMoG}v^OsAMMLxE z%*teC+nn4Mm)hcT+fBLT(y`00PQE(bHj|gEXq}T=<5FuvZe0Rh$X%2Tx|sP0C^`xj zE+hW{W6c7a8URydfHutEcBvS^2EWI^5^5j!##=oR%Nd+_3*F^mw^OM>e7O2^R4{u{ z4s%a50U#N0vdAujX4?c!Ne|_+%bO0DyUkHS+3fUIv5u^$a>n+D2>>6)dmAK}9PWF` z;r`IL59_ANgVWKO7p6z%%XW@Srd-L_uWqEE;*+z-Z%7ZP14RycWm4de#_6TFEb+Ha zSqjVdz6_E=In-c0IC3bcN#)DTF&HI9wvPnwt_6Dzd(1#27#=zuJ*rV`_t(%%PP=3TQx83b&~9(1YIq&yKhMC>6mPg>}&z+Zj@gH^&+G)GdAB{UuHj6 zm7MeaNt5)m{1TbP07mc`Ai-eFa!_Pb7j7z+Xm**poRKh42FoX-FOO|{md;F&dzyX{ z+@-sXHVPO5tvEM9jBDqS*#4}<07jyO9h@L&BMHS8z~HUky6Ey2Bbi-V=-tov5FqWl z?!A8WT5Mi=ES+<(^c34>Yi~$9(jm*9R7i^T2PVtGSk_@rCYR+5UiFf z(*jL~n6YUCHx*>2PK)dNMfEwYTZ4t1P=hIe%1juAX=c|ntD(7Wo@vrowG1evA+wby zxIi%}Tvws1c3x-EMW9EJ7NL-E%C+4rbde?7zfKcN#L>`2;w!aOtFUx; zO>~XBZ&}sVSwHEr)>X%*!a92C)ntVhl9G@G1jv}^C?1#<0m@*n`2cTCM@GwuaI!IZ z{_a??pa# zHs6NWoB=O8vzgvyI++k4r#71+uy zvCJ8YJVW0;O9hFe>aS37or>R~B2Gn;ir=H+CKZ1`#ebmUkEr+)D*lX$|4fA=Jo(#n zjS8w3c?HE=uG=2T{{k{#kDEa-n*hjL*_2Egzp%D+)A`xI~ z%Q@}*Naa~-2uEtnuz6zh02KjuDK3Qf#jW z##_=I3$UEeA-*t$FN++<%f|Aw?OB2?=4orntzff|)1hIm!_lCBkMx)C5n!aeq24~0 zS}^5lY2}ogh}O$+8Xe(njrG+6C6Gv~r=eAyL|pEZsPs z`zaQ&Y@b?z2xGYs&yfNb3nmIKbFgQ?}7K-z?DFmQc_+ZL*{0n`6n=5V6uUhA%oTY~-Vm2I#N`dl z6ly+ZPJay5Up3YD?%_ zfY!%UFZvq%O`KiO&3j-MdBh@)3@hPtu_A+8z=s_^XX6!ywWk)(zaL&9f zr$dKaudZ^rm@Cu^$_i(wDD>Z?i$n!f_dBbI+WA~2jTTYLs6i?9r|m$1ID~RSFvnqT zR6vwB>zshz?$Ak$6eAt^4BavmkmZjkz~2GHB`>d%_rgwuJzdNOOT`}IiD|tr{Vq@? z6!UfXP8)qEL3}{`pkXW(tw;~+?Km(P8DVQr@8T8j^Pz0LAfu&?l1WBWd0}QH4MoH1 zZA@v(&tN*0gDsf=@L1Fq8i<4=sr=_@Ro`J%9Z_|{Nv2%3&M@U3NabqjB%EY3pOH=0 zXRO>nAx<>e)$4?(Z=frKW+IVbb;F`dD&7DSS*Z()BpB)Zw7PD(^Zh5@dm>rga@*z3 z+dT2u_yKrn%gRB0C=K@p+ApMRQ#`OKUbg8oFKYa0VcEr3Ctm&L-eh6J_tB)9vNAk2 z@z|v=zVqbgs8IbmU1WE7Lc#BDDn01;e&qKbEXwW1ckZT7+(QNVcX)m{U_ctx`JC=j z@oV%oI@PIK^cDH5In|+?Hmaiwh>P90;}B8{?o#lq3Pn`~{Z2z5z zws*`h+a!(c$U`4Q{5Ur3xD@|l{@vK~-c08pWyX}z=lKBKFs$q0+iQr(Jn&_>fBd3>KTIZ}k zG@vMh;jEej^=I^sM57}^*|pJ^??td;35x}f(jT^69@#3EBtqJoX8HX=R!{exGt{L> zu#}%Y*qL&HEmn=KBYbrNku8X=UU*{o$7{yIOsC6SXK$f#1ev8_Qu4(;Qw#2)?{+4)# zC4nxpSura`Du=^ODu=@yvRaLth6TfiF$OtiXy}}$6qic*%~()4UyK0r8h=RB^%};6 z)7scXY(WktMr9;6eak-V^)Qy`9@`i-GVa5k(Y_@7n-V>Mh#N|DLDhqN` zLT;LgCgknc{B!cYxU?@J?_=c8CL$R#K8QED`x$5X1bpceEuJk?>A^@NPLm!E#}PvS z;&*Bu#ss5Gsz53iBhI#zp<24&&le5y0qhw$(WBL&WoFE>s$E|k_MO6#YeNtA9t(p|ao;_DNyPnW;H^1YRF@}{`7DIsrKVqA%9 z(WbQG5fQNLxT_aIMf&+tf(27@dY*V7Khqv=TIXxSV6 zXZrqX{{3>(m?LGP}1^_^HPIt;PItYJ54(_YiTG*x1niGD;T%trm zkUX~3o}RyFK#6eb5@2gw_zXtUro4nv5Nj2llT$p))_VU1&y5UW^a0qEv}kQYTC0g* z3xT>spl3w3y!gpu^U@0j z>1iOU1zi)mZ|iLDoV+_O?M}$M(_w|E1>-Sa!AVAnW5^mNxM0I(YsN)imK;aalizfV zep%meHK$uGHKvQrR1nW*bD|Ue0?T-&%}lX#W@76zQz1)7-=}$b1drlLml>&FpODv2 zD>I`|`LQR+tdfu)x;APoE2d}(quR_0R;dMS0L&mE?@1qV8UZ%qDo*Zh#6L95p_wSX zNF7!zd>c67>%Nn3%2F&>B(q3C0AjSQjK-M}xK^B9)lwVO;@su};#=8q#9;KBc5=~V zW1b~aj0EBqpVP26;TfF$Vp%Dp>#vNzZfvjmrHL;s$ZL^QWEwG}WS9YnFEP5q=0dVwLENt<02X-eX(c==ldNa2adO z48ED#{5N{U_N4|@8&F@802~|q&Ya^8l!VM32sYt_2803bJ2=TWv;wAb$aT@(=jnI# zd0t%s8#jW!zg(tJ=r<7`$8pA``mw_Y6JRGj@2vE}H-HvsP0>8o;qJpO3VpbD7WA8^ z=Tgh?!5C>K7Upt5i>OgN0T-D;lY#X*8W#Exs0lpzK?Nfg8f5l|u@iPEI-8 z-T#mJd>(zWc$QUb-`#X&(?a!@MD>=x@cYX0ZxvVGlq=$JKPodPzB71rFwwC0Gry~_ z?9%qPpZLs+8soXh-%*xNCcqVQ)ut!;uWlFM@*<7>m6`)?-`}kn0ZpOFaIjx}ii+8$ z43t_n(_E!;wQTtI`O+jU+BCv!-D6JNQj%7tM!5jo^cmcdsNQi;GidH&#%EBiqj7kT zV6jMOI~l_*HJ>UKQc+9=?Q*8Bq+&G{YpEdPsk(uRc4|Rvm*?9DI=ECS68IO{h3jPA zJ-q0X{Oc&keg~yM+DvJWHr~$h`}f=~^7;4P4tV?Auzmit{m|6&cy*_!!3_e{wlB9?0!j$7s?ZX=O|t}eT!l}2kglr&>AJL> z;tV#frlqH6VBwhQMw)3Vim7Mv^StHy0n*cR69T(qn>iYFIu;*8@lULCmpAS@0b=`B zKzIMbx<*;*eJFDjtXw>v%W~CAELVLV%T=F0?mFi_UVyBK`KeMi&EWi|CCx^lj5+@? zJo%^GSSyIX{D|uC1YPW_aEF>sK|qGUsDDb*Tbh4i1v9wxd6z0WGCF{i{N8)h6c0SM~j!7)vA|_+Ydf=<*|jD?FnShIGU{4bM5f;UGaw=pO>B>S3JD_3sNv41*Z?h zrQp2Oz$_xphS%Kjn(dVQbInRA|wU6`AA8li~tk|=+IBm{&mm_h7Z9kxfEJ)6xgydU8a8R>^`pdB>V;NIv+JIuVbA}PQ+u$UTwvmI(B zqzUI?_9_g$SKA0vXg+vwP6z!Y>_JXg(txXHf=TSVE&!?L zZoxDQgv5-!=b(3NyQH|Pk+9JsN98EF^qet^Y;_)11!h_BoVA=GBaF(Rf&oboZTR9E zMq&xzxckInLrWF1`PT%eNUGA%c5TxCx`&lo|{@I1<}%jMOlIp(&r6BAKZ$M|Ki`eG6X!07J6Hyve-FMUzF? zB(5k~yam}AH*8thus5+`@9$MSG!^|xC0_B+cs`0-Rkag^QTN{^Z<8tk-jawHs9!hLH^m~*ze;yb-<}pkI|IuAPl9Q zNmcTWs}EDrNd+xKR%vhMRH3E?^o79+dyuB21y@<3j)%EEz|;sTR?rxciSjSs!p_$o zDAiD#5tNIvk&33`?StKl;PBcl;> z-fc1xJ)NQWAWrU6FB8yUt8DGi(RN`ZK~yQPjDO}S6rIeo{JApqbZ|AkQ|=HIHiiQ42sRQZhcP^<_Z~Y(5vx{)&=8e ztMw=iq^Yl+n>e>1Z^ZtPBI&`nxge9v;~JRH!MJoVAs1oF>R+^s15+~T0cAf3pN$+Br8tl3ncVnj^7AL6s=!)AuL8IA#FSgOw zsWZvq2FiU~zN}J%mw$jN8;wO8lyLup^*gMJSZq77lI5U=zTVpEY5H!5`bP3eTy8;L zk%Zim4j_j5c1;Hm`gX^0FY4O^cV5#%EA8C`*+7^edDY7$eI_|D8Iy?$%%4d=b(M@E za*3fw>64H)M~<|MdOe>>b@-e6I z3>Ea5NK>=4K&1>6e(AP7G_B7V)2gdzHnZHi1RQ|St{WC)GF{EC;BgsodA9}07HV1( zNXOBJ94K>pp1vVHvjmC!<-49^Ys?1ts7qw66026uxyjg8V5di0zhhqED`ysY6ZyPY zWWs$l*kGHxbC{_LK17zwAWZX0c?0-WzeO=G$JJDcF|UToRc)wTY4>zdfYdIVC{Se= z1uV)`b5G!2J|;Z$_e3)6BRO~Yv=wWgD4 zI8bgpe*E^6hJ#gx`$)ri*8LaQIpw6AzZvz=hsMT1=tsv=4#R?@1HFR?u%@B4y9<42 z$yAiraYEZsTyRI}rP(2rmyO^U5l}1G{75(5GQcOdnd2~b7lYD5&u0e)U}spV;hrAiYjwKr1}aor{F8Bc=aa=9n9KA0!LBf8v^+8)f4kl%XA zk8dWqz9Z&;W%!lIrW6*nt0c#;t!z`?$Y?KLy+P`vhTsSp4ymspff+%g#tgW}w#ou} zHXZUcLW7;C4)MrSP`Y+J=La>e((=pIlhsp?CQH^Ylr$zv8fR)}PGG;J@f^*kJ9Pp} z!|dK%bu)m*>85{;u2DfSY&dU={XCY5-LYX2;Q$>E-cTSjq=Rut8;HLh76J<9Vf3Da zWZhEmMH)1_rGRmP43+}J6RCZfZF=9JaVK4jn+V<+nTjT)mU*d7cinzr@(a_EOJ7J< zz_cm~%g4JsI9)8o-K!B!2Ge9szQr#y7;06VDwgR&)IXLnu%(*(IE?_;%18u-tg@{B zi5C2ue+MTS#Y(E>IR3_#A{g}Bd?D>!EH-7(b_ke3RADY}X41XmZE0$OV#WfOh~=o; zsrV8qF|Mf@TzTlPb(l@ZOvah`2^#qjda^iX$O}G=l>u93y_Q^YoN2WPE^WWLi$1*; zjfD~j2&UYy31L6qvowuN^?nv_sfWA1Kv&r`m(f)oD3~f3hCqU(e8g;1dCUnb*)(1Nn>k;Lf-njmOmT}x8eQ(5?4Its)SWEfG@f@;u38q+4JdgG zuaObab*6+m`e8O2T|V|UZPSALK<>e>>SqN<-zr71IjcrYrUVQajZwj z7Bt&T;jLZd+FUlK#L%JtPMM%=t0y>N`>z-Rn4lQ&1L`WdA=D4GXu z>aY%NBv$JX8`6O~a)rkKFdu(I$I;d;>`MgqT|1Es9{%VJELdQPx2?+>==SxpcyJ$T zeB!-6dP9102?hAucm@Mfe1`J?A;D`n4-t`odg`{Sr)Zgde*!Ng`b*!;S$z|I>bk6b zMsU@b2hD4!k%u&|p?*CLW4QI!Hd7Y=9ybuCAx@_1KTGpR5v0H$=ltzX1b6>RGcxd{ z-8qm59+>M~CeImZiJ4~1Bq5ANh=>d=Inm~Z<&5z;=NIfpFeA3G0U@Ih!G+D=EDkpC z2!jnwyKs(eNt5SPVfyH^H>vwhaTk)Z^>!djIfbqEhGHsN9?X!2 zl$Wj%PNpP^JcBd&BwWv>REZcLXMwchg9kS-azL~h^n>}QSxsgwp?QIJ%l*!^>Cz@` zz#xuz$S4=3nc}`h5IBPe8JsY_a&uC~%2~}nJza4rFNtOF+%{oIp^kF=WL&vTMuUD24gLqoAqH0tAw@0@m*^h_AX@UUN^lxA?=u#c3E7|(?`h#jkGi(7c?IJ02NHrKddp2 zG~S^tYN2`{mXtLeb9rMbWzhPa?(DavRNE{01GHyV$_l5<+>sWW!6_>i=au-)V z9X)9DRk(JHs15yF{0HTej9WJ4lTEor`BY<={!~7XKuFg*9kB{J%Gnf2zOQ_CxN2+o zuL(v38YnT)xV$qi?L?VT10@{`J9+T^JZ@<#AuQ&!{G0Mht2Qg#+`|BsAEgFL$fvn` z)i#``VOuqmYwSKhZKz{S0tUxXPFVjpX-w(C1t0ywn>7w>=jgs@Zp?qrf-e~zaa$92>e@+cOozGH3(4q zzq@eC51+|S7 zR74Zt_tPwf;AN(uc4-PK_0VU9GTn@`NGskf>y6!5l}c-lUB|IV0Oc~PRh2x{DNyoJ z29yGng-QTrky40KR*Fy-D>BLwr5I(YQi8HfDMeYXl%cFp%28G-6)0CIl_;yiD^HPW z#BrP=^5Zy^6-w1xE@kCgu6|=rPo?@TW3}t?n!D(0l~RMgR`+|9HTb)>-*dw3Gid2^ zwXzOxxkjl)xmKw|8C2>~u2a^dtW_FN)+rlM)+-xPu2&jSHYl4=ZcsL(+^B3p*{Ezq zxk+h4xmjsOxkcHAa;wsUvPo%0*{rmo+@@?t*`n+~*{bYB*{1A5x&1D_Za2)PdrUK| zve)uOJCuje+fJn&<&Im z4pTx%zskl4sdx|z1?Y1ginkq?aF1j&$MJ#o8%AV7h>4kk+7c$7;Tikx?Fq&rH1i2c zPKNKuz31;R5>lH_fzKhYJ66(MY4MpKG2Hqaa z#=JrxHWs$(Ae$*5kk9~DXAKc9c+8CI*k05PkS3(UfxPAh$g?|sq_yk)P#!}0&Ogvf_p&;Eu+6sFU4)*OMgLnul z*pnay5#>td433N-l8NI4t-4VkW|s$sBVjeFeuy7>{#o{BChq(^Uf-F0mYb7?!)Gb0 zUr(PJX7rNlQerG|*8RT;KfZyd0zXPy=1XfAN*fcUjWfu;-I6SAqwIVvxMXVW?1u64 zNg4b7eHxH2`7ZTOMUsKKardW%#h1!2ot^e23)hc(ZX$fjJ>D>p2Pyqx-bCJlRF#mb zrb?y`%u8#W*AC80YiW=1BNIm!0yT+1O){|NrrdSg>n?o6{h8OBm;Zeaou-TR1`}vt zSVD1y8T@?)elSmy2IKf#<6yzG=!Fj2YFFe#Lf&bQaJ8_-lOyD7-EyoIcS{$ z+mA!Qt!#c;@qQdR#=H8layiH3C}Vyh=H+6K4~=JC$iZ4={O-4|CG?+?&9BhUlsqNh zXq7vbOTTTce5c66;5d{5B>;6qr(DvQ#IIQ1(RYdr(vCx?9ZI2D6V#!o8?2GV6{Ueg*Mj(US;f*RqL= ziNUgsbAUM!N@Zk-ol|T14i*|atxU>6zUZIud;7cXSK4QClB=4N@-}`M0i9D26!o>& z$eX))a`RLOS#oRMtC{IfuG^U`-8GRrUIA+XMG#KCFelf?rTVyBf2+9Sa$qumt+I;O zG2i->_bX#@Y1R1H&63K6lKMnR{q)h9x@1Wc0-xoIsk*7iRP~%(7nkagID*xwOOznd z#7tSTWNU^xmun_#rXtgwQ>T(8jlw#3FC;WbBG=;{zAhZ$k?CZKNDL!OKY4eNFYqb`=8V|M6Zn@ZTjNj=@M3ffx@TdDE=)o9BD3dyi4GpT?Y zK0O%f3-{0tnd&&Yx~grtQj2p_>q+?u{zFc7)WYmr);>-3`Kj+BKxpbM~QW1 zW>0t1&q@N$hwzRBoDC+pmB0N4esE1^+>Kq{DSyCJ^xZR8^fj)DA2Hf6nRp0FhzpR!N~e6ofNoyr*2}@YGXzW&Vgvz)sZGgTgCTjq~I>l5Jpw{Iu25hS6_$DEy+BBO-7K#DbyF` znS1{mE~)>WivK~y?_g%te@g|C8o~a4N74xjCDzp7v47x9xMwsHJ~29oz~;X2X|k;G ztsO~sv}Za0LT2!`5t@7Ke**!(!zi;eDetmUA1RLn<9A3{zVt=f%n3<@u=y!KPa zt|u#Q1`5gd_s(Oq=gA7^rYLoEyL+M=Om^p$o%4ZOs#S-5vGeLa_oF_Yt+?~KPrrDF z1-X28MajV???-tx2lskEYVsf4mHW|Nf2TKBY>WK&n34M?c^;90N6632@JZhownQ=o zIdD3G=&fTC_^N@Ocwy}@7tERcKp+I%Zsl;xfVQuLz?U}v;Tr%kCgx1Kqn(o8%KR%*ngAOH^)+kiePu)IbeeY6(|rdPVkR4D1Wi}k9W;xn?+g}* zzUfh@1{l~Kes+P#I*(dv;U2zMlS#g^5s0$sXAc3%<9I^?lC=&Xagv*jnuN3vSepn? zCjXrGa^?dYh^lO){gyV;eoGtguoOqX&~Tu}``sGGlIq~Gwx~XIDK7Zx;`9M9*|9YDL^)&zMwfWz0V72$VtNjNW z?DJ13OUS-RUfL|hHG?>yopz8-U&J63FUw=733wUnp8|r(FnK$`9p4;%!DbMLv77u}wwmZen zF7C*5#nM_w5rz)GN;pwYz4!*P{tO#?(#Ct(qztvpApTFO)_*{ON3`JI_6U8C)y%;c zlV}()gzZBIP7j9l^imO?!BEUfGqpKPX!09)43SCZ6^O5VG$|he!36(YHMwf)8IZ%k zdx4pw*UF~@$zaEI-){xJ8~EgC{H0f~2a*qeAz9J`f179gAW3y9?SnHX2azr`E(g=E z{OQWoQ_8zTSB8=+w@egKt4p3sXt{3s+4o<1@1;2eGfIeOY)Wq_x)Pi|`2Laij_`#A zOXr;Z*I6Q^;(-ZNyv)cn%pqlg(2NROg^qlB!bBjQPsI66lu}@ZT)GCHCID<~q6vt) zkYho~oT!14`g=s&@04rXW*Tk<^jCx#cN{j<%?0xMFGwH=xl6y>gZMrW2x;l3oR=E& zVqZVP{Asl7AJ)kP4~9dd(E+GFN3lm!knd;}B&LGB0I@$d5@ti|8bu;qq?>0ABSHMg z*UW~&krP2MpP-J2!L3_^=SN023=Rf|!)MSKp2FUN43CL48QrLV0Kkfsf_j{8)yT-{ zHs(Sp!1$^LN~?cJ$o)qsy7jFr8D(HZp+E^o`d}Rm(N@3t0};G$G&I~7R*65Tx2WZR zL}4?TlE8%|-(aEK%V<97e^R4Arbd5)LS!xFQW5$n;1XDO-dZu)tK z$ju+)1zCox;&NK!t`nSFavi7+UmiQ9eC;W$i#144Ub19U_EhFpNyS3RxJXteal~L(dPCal+`&nf5`xCd(ZDz|`DiE& zwvP79yDlIaj4ZJ|cSUNW>1AYoOo3u)tpUO%lmSF4iAnCjg>$-NtAQ}kHh{;PK^E3l zePai>9|?D`mmrw)5I`9I0J^K|Bc_yj8`Ze^gefJ2OS+?-iKkQ(95;L-n)0gy{U@VN z&9u#?nKG?(C*6Iy^5`!+E%(>hh_{QxgT_zVR@Nnq8TYR!-H zg*=T63BjN=QvJ=jWw8+Jd?1 zBbW9h%bLa|172^+E3|Z^2Q14yS6qB!;*IHbraMZnwIEYUjBD7UlU8f8Fj=(6nkKls zDC@A$yJV12vYuuMumUnF1X4Q*6*|2?z(CO(5t!A~T~Ie?bn#&J0M71R*f&>j5}iFF)W_7RWpt=y-GKsyd|l)xBryJOYd24!H8 z#p}a$vD=vR*g8us4YM?hrtTu*q3ho#Y%1Wk3dSOs%w^ax`2uT(e1vx@i)4?|**IPk zUM2$#)kR#j8#H)KBLYqkqyj+{mUyX31L4%F12NO+Jtn6P51WWj49Mk9Pj!6&@T8L7y z0J~To{e;?R1|cvaMFBQEEN&2IcB;cS&*p(^eDiGa%<&pOLsQm;PE5{Tos{djaR<(k z%d00>Bj&TDj=M(6zH%Wh)r?=D>7^;TFmd7SH>NjdV_*3tAV{W}&^aax=%jgb9JJ*m zGDc}AhA?I$0F4DJdv!x5iv_s^KIXdEBs3Pn~1(L*PJPk)co$) zdM-P58ew#gQ20q%tSyF+vn&+uh)SZ z?ajt7NHe0&Q$Bh+6ImK%_50|Mi!7vobAJja?(~x)W%-gkCa5rxg=rIv;2)#AB)srF z;w3J@{6Oz9mB(I%;$l<&Ui!mCpp?Ilo&OKCju7&YhCv6{GGwM@XuJSz_(la{x?|Rw zCfXB1kDxuJl?$Z}iBbfhZ#1IM<0~KjgoU3!i}3UE6;r;c{^?kN5m|`W)VA^?}7;_XEMiBH0}X+1gjVUI4FheG-*vz9cW};-#m**q<`fMW znWqtm*wZ(v!sin0864q@(D*vjB>_2O+g~H_?!eQDwXS1u!bBn-aA%W<%HOTLg4l27 z4vAj=(&U%Ec7exrLeEW?iHSkdzr~+L@!;o9>;u%<2iaz_pE-3N=xv)MCc1D<3vaLb z08sXc*~Dmx7I@FB%Pb}`(i0lQN*CpP58@+fs$dO|?aypz%c_HqX^LoN6HSpb1i(sE zl*=b3Pml=>9<1djhyb5WP$|Ct{w4@RO{nTP#8ZT;0=WiPMaC|nt)M@Lna>2iA5kzm zWFveZ9f%{LK!PO#&zLI@^WnR*o#CB(f&ZS%aI|9pIyeWa@K_}&a|D$WNYwFOuU01rM z553>@Uf0Z_?{r=5nmzO{yMD3j+M$2b^{=|(Wu36OS!m2j(z)b=*OlLT?YpmiJTxaC zjY~%p^3inaLe!iA?+i||1zz$jn1M{Di3_`{_!vkDfLJ7O+dwJ@ASLiH2suQqrunj2 zWjuh*bUw&StbkZYpTZmoIxQkZVG96NWA@boqDAzgreMQ!T$c+N(6W*@k(l<7L!Rn#L^Ng9zQ5uIrKC8vE{;{w`>095lIX2q?go!FD#T ze6P@z4~WMuLR#+>o1UST-%`u(A?|7TIiN22MMmZ^V+9fjYYtR8fl8Z>1#pu4v#SZU zM(U0o)mF4B183O!K!vt82$A&xL4KhQSRL43_^R38?d)$eYJ+6!P1u5Pc8M>oRhu!e zDUZ^^^7P@PHCATUW_u@4?O2<6k-Et0sroVurpp*u3x5f-!P5FR)gatz1^uiCvA|J2|q=0zmBsWPDjafkCoMA^S98EY*6>l zh=h>L@uti4M{4LBlK~tI@-(}c?cLFa<1-=lW!HH(Z6N0l5wYh~tr`$;mv8f*=xxx< z^<_@XV&w*S_I9wY$q3L#WJEs!5@OV_`|L% z5Nl20bGl%92TRwB;=M~L9^ZOOG)7z638^^n>A+!zi zfpz2~-aWZ{p=@)aY;&?~>ulv**{*nCSG;W3&8n3XN5)^cSysJJR+lKN`}VoHvgUZ8 zIbPQMX=%l!{>vkiBgxW+@y=VtWjD*dfaC!sJ(N74un5TmaQb-(p8Yw!!1t-R6A9p@ zfBwMkgIl~GZSf!6VGqnD>OuItIE^A(kr%=#Q3=N(V&}^nL$JkB_M$Gl1T{nyH7M7# z9*ZH8UW-@JF4}97Vx+Cw;6_6rHP?%n+cRAwuV?T@>*X0NA)>4|+&?fp3=kuI2W#(P zGKuZU3|h-H{Y!!>-B7aC0aI2bCNyOlO193H|I1asxayy;UShX%V_ts}Ba+GY;7DDb z^_*HmsVvD;ggzjh&RJ<3bJxZE?Y(NV7S1GfjtoPhh(?f5r&sOJe}Ubo`Wn=fr&s0n zUPemNym!`B&OHc@dM(le3J@MT9X+qp0Gh+4q#Dg6mbvl&r0IGHBMKsr@8S`9Q!A3p z#08BrcOv&<(L~XuFHUWmm)3tu+e=^GHM#5UvH03nZrT*)4mEgaCAxpmbES_z3oN21 zISwJ#8oZjdT0#*8uP<{CJ@;a46_wxyNL@ryGH!q`Xj=)~;Wv%n zwrVMCSbsWv$BTd_#)rnWXxfj|SE&o|dYfhhZTh~^XC=R zIX&{u=lRqWr}cLh$(#9cb?M*=Z!nQsPKh5lSh{Om;QX%L9bf*y7_dRQ)p(%*B@L;(94 zL=yo%nT!oA@Im3N;En!4G=XSoP?U_Ki9iU!ysQ8kIu7Kn0uP`=|9d~838QA5lu`Z* zO)9aIFHkpi6J}Q3OvM&f;PH(COBC*};hnM(K$xJy)=q9kKX%EZgsH6>QDQl!_$G8> zSB)*5IEL?x$&}SwS?TUM$dK8G9Oq?qQsgd z&*xT%~|EtLt_~pskT290!ZI#l*wK>7 z8ioJ?)MT-c33&A zsw1i%x58BLw*VB(Y2XND*qg=<(~@fR44mj;7^NqM8VZNV${TxXS&Zb(oT*web@&Wn z?62cR4V_@B^z92!d5cOf4o(bCwIz$zBHj^^nQJH4PM0Q2>c?}O3N$iulxo>nym}@M zEeq8As-|RNGpXd@cEt;U)rr9BsXjdklrvRS?ahG9GZ9Z6g;#b6jntmp%?j?5Yz-}hWK14U#Q8O7JqQy$ zAhgpeX&K&hM1FZ$M85aVDWl8%B6R~p>R=)eoGzOWtS4M-NJDCv&VbZw5`i^S5#4y^ zL~0;DklK#;gvxb<)D3jjz>r!qommpWsT~-8n>35>;t1Of0-U9_Y)S5{=iAAYxK!s- z%-*y_><dqs|aV=<<|AMvHy0d0|drjEnXqi_+6)xibhKG~cchc*8) ztYBE_{}5LCAEP|v8zPjEe3<1+4EBz~g&mGWf`bFEh3R_aZiVznqowkQa`Qr`U#Q#86IhH$N0+UlkyATkMNl9o7^{DmMmL8At5==A;_`|lDWd) zse0ZFbT}kXzUqOgd@zp3^;E+*rh1vC%6$kvvQcJ!J2KSc?Uuekq zq0k~O?bikO(g83T65k1JOD4n%TujS2=R{C`&+lePv-%ffPip~&n#mW_-}fFzCCevM zMh@tk8g)v4xbBskS|18^ifSk%KM_ekGi?}WNNh|mx zjg*rsvNVDWIa#a%p*uEzq=-Mnd9hGE;2#2Z`8uR3#wM+})WaBJgzus*w)_aHM+pNz zLdS2q{$Kq@&v&d|u z(~WmNm-PF0B6awTpDXRG@_u)FO=rFLqn0(D+q@rF`8(I;eq8VG+?xCGHh<@y3?k|+ zhQar@(}scZUWB=LduYDc0sbK3l4f*lru{bzH#RcIfP3uNod9ikZ@FmyRTeZt`ZeS6 z;prVS8)sou-b?%AJU;RG+fUwF^x3?v=26 zFAPxS7sn>XwEQaATCgQ9wdlJQu460bHzwqbGmp;6+vC#qxV)V$7UXxbUsL}#v+RsT z(FvHT9;s@IrT}S}R|uqOeA!h?A(NJ>dY3TWy4J@)qe_r zv#7_nr2&raR-N(})B;;-BOLd5R(!al@GLdX|U;CCf>`mS(b~cs%_( zMG=FVhC8Ao;O5u_5Bmx*p5EUl+GdLc_Ezg zL`RV0fXV!fEd2l7U2kj~M|R((xD-WET-lN=$$xaTY>8rQOSY^yv1MC->^jjkQS4et zjN}}K5@}hnWa*Y-6tmYDy{0%B@x@Ym2g?EOtRO9NX@hHm`;c$<;ZU?F&=yP4sT^Le z=zVE%K!Ms6Q=|S+^!H|VmrHU;$;qJwN#FKc0&O>k4$#aj`tkXzDYbJ|?MnUlH^B$(@3q^22u!56lNOW@Lw_SEs8#hqQa$kT$fqxS z0#K@6-HlrGT6a0N8z>Aae1qU(aJgq8$gv@EC<fjz%Nc z=yEhVg@qZ~6hfzBZU_B!>bQR*=8qfq$v>8tH}MTCYc88ThcTR|9nmQsuVg><*j6I6 z?kf*oilYmBlwtJ~xUaU>t^v7YlNm_QSZ{vE-9$6EbJynPuj=lW z`K$CFK@^dftEG>}=T549#lyd~SmEFCpxf^SR(quywgwrfq*0J$+ug3uW zf8XvAhYi17$Rnbu9g}Zz{T=*OQ^1D!*Bpo-H-yGPaXDOW>|x@8&CQHPF^q80QG%n| z@t}k_M=}2~5o5TBnEsbzzYdhc0Rk*pQ_P5b3lw9fnK+n`)>8mclWnZBW5@KCmp!3! znLj61oI!1DtavJ=KD8bz*8bqclJmCfmg}~9OHI{x*mR|Wy$W}|hYM7?5{r{9AHa9f zK{vv!xd{ev1m2_YCyFFsa)DjV5RXH7=A>X(l*w<*ST4hlc?O+up^jOS9jW$fy<5Js zSKv0aOj=^gf}eFyV3dgrHA}%0jOBS~eH2MTl*VI2!z1ts!E^JB!3v>4X)^{(7^QYx zKBo{-&z1tRp?Wy+dqzlE76Se3Gy+W<{jbw+!9H9LzutO$IQ+VQ3?l~YOYGG4KZ~HS zR#J$8>Btp~Q7k;I_6)vvx&pZvutefe=|_|+2D@VMB!+e&sDQ@glrO)=%q~s%@=G<> zDl>u9kE(I0#0*llF^b72Hg!BgR%s6rCdUYk5Bf5Lte_@KR~e&aG?K0|K2zvG?zFoQ zklxF*CnHm0XK5j3B>6Ros;BT&OH|$UzG|47m~X1B!}iR>i-%Y1+LCo`DYgA40O2;> z$vo1+a>K$p0HVZ*WLuoF~oJF#LKm58EH z_913AT@C2&04OVnF!$iOHvQKIVBV_Qjm@LFdPH|00fpt+(0p@faY%1_oa%T8$bh`g zwhL5#TT*Sa0qe0Rh^{fDKfvo9(%px2^^jGQpBUGY>Y-vi(UQPF#aG^l1V)b*XnG=9 z%%o&l3j)qXv5jGA{LBp{dY(Y46u2Y>%R)r5Cxy1PwR+c4);cop5VxL;Xz`3fq&!G1-3vEY}pwogho9Al1gY0PmR z&c;&idXa5r>KcoV>n%>?{{uvP1>l+0gT<YE3yly@I?l%Rk4g@7Fzi9K!+7BF8;P zV`JLH%q-tGW1M?11oE3~K=k;{L~NI@naEEQU2w4?HBXjHl{ngErZPs;w2NOzG;#I;d%- zGkU-lu@~`3iTUz7)Te&b8jVI82M=k$+Oud^#$cYD;t&w9 z+kqg#*PDkXVxbryQm5mW;YkdQUJ*#G7uT0sU#Z|`YWQP#0juHl=7AK0M}%lX)Zm5o zl)HJ=y))_F$@fzMsS~m0mbauDY1UhJ6D<}q5RKf;bLwji-(N+X*n?U_giuWiexgCm z6f1UPEC-YTNO}vhJm#RlZkQ7k7&E12C0PtfdLr~8NJuM*L@uS1d}*7`xg5U3t{=&md*c#x`lzHnByX} zS)Y1iU=K;4_eg7}eq8pIvHjGo4+=Bj!m7RDk`VpKz0x&}2GQfR- z5^pLMvUI)PiIr$5(NZXQ8AQ!gw*JM!bU$CZJp!yn1B8cGzC8qAiUUKXE61a=m><$K z>R){DCzIBgN=;YWm@cgra2*?E(r)0ZY2n#vO=J2&;fyMeQ)<|#p-7zKj3Cx8WkH1c za&bya<=IO;^DHU}SfV2al16S;6;^2dHXaOqxi?kUg*nwt%@q8vX?}pV&kkK1`u^`y z)W4>GQCpUGf3WAhJ@4;ZQM+_^S5oaNGin?KV{L$Q5WqsX+R+-%tvvxkz-Mric$K4I zE)e_%UcyR8<$}q9F08zCiN=z+q{-Je^YEW|LV458!OE;KxY~ulp6ixLD?Y`~y{>~8 zH%Oblt8cJThcW>yZD9xH=%5^pO9yTry>)b@E}(k@dR>5WbkNLw0|pjYXRyFvoeAwQ z%fFGudu))^4IzjO)(;AjkhMkrW`v?9aVTJJQ|-mwYO84L#1xifot4keLS2_(_dIb6 z77Z99k;$YOLD_I=@GOt)ic6OIYSRF({j7%Trxg zO5)7|)ukbyCk@v@;;{{|rja&G96EuLZEE#kN<9J2!)DBj*Dmt76FGil);p#z5GvB} z*FpUT;2WQSht7R<@hUACF#=R{e?0c-YoEOKv&j{8P88vWV~UN*3^?u;dDR$yb~~CDA}?G57EIkNGiB)3_H%Y%%O_ z+UH~~SH*%X%Plo*E}3LPig8PZn5ULVkr~IsvGBq}vFL2Ma4fl0WRV({wI!<#q||P3 zLeq|UCxPl*uQ69u(5|4zmjf&C(z@ZO4X&32?%Xo%{?iS%ySUZGikPTH)@{WyGR1Cg zaihDDT5Xg&YgoH6kIdNd*fzWlzsIiF?~$crdROMD@mO23W@JtKk+4C#SU1l#RVXqI z&ml%aY}dX3jXyMvb$TqeCr^_&Sy}*WycCTXqQK(rPN@fpA-1zwObi@_jKLy;>8<@M zYQOI8PpbXJ&Hkubw{53b&Y4HU3D`lPgNH09V4j0ckW$1V9p*H8>w?AsQlc)R+2Ya0J*KIYQ(EQkrPa zL;D$#zb5i`ME-$@PGp71Dv{5L(1v&IH$?t}NS4Td5}}QP+Cw4^8UulLEoqfRYKW*r zXt#9QITh9}rK?Hzg9W0&f1owdO+S%VBJD&vi5w*IIFToa93#?C>HUcO zGj7J-#mQSz#!;y}C1*BQE1t|&6{K~OvMD-Oub8aGE?hRIx=3T(w6ah zl+H|39mr!|T-)wOj`~eXSEjuZ={7rY!@CXFj#*)U za!;wK@~kN?m+QW-M)9qwIJ-w@nHHzgm+@9A2Q!-+l>M1*_Kx*9+wZ}PHdQIDnJra# zy)D(K@zxsUc&4QmFRxS8Wz)LMuxO$tY#=g7q>sp}M9vfGq4pjma*)UX$Qb^tpDBUXPUF%|DJs1rN2He= zQK6zMQg0)2)WRZ+INq{+120uxsR%mLjU@C>Mj=fQyeb+&gxolRgv7L~U^rrF>qkb(Jl%VAqsAyndRevfrCZUI;JVYZ=qJqYa*D^oAsJ+kyF}c zt))v?6;ESn!O!$jVy~dfzFg#yVCE}_A2wl7k6}FnTL(XSoP<#vix)->ka=wy^+pJj zRy-b%DHo&u04*vH_`^m^_-Cj62&x_F2=1G`G86T4FG`Ho(nhRi-mt)1s940+Df$;w^K0tvgjSM3oE~t{y|N=qbTt zolHY1k?RHxLo{(>bDADZsXYkmx2cI^dM|HFZQ4g5FZl@aZiXQ5-Mr-f40!R61PUJ^ zQ21yL6h10Hs6lZLB#`?=9>z%9`+47BWyLQlmBHFd@+=pOaSWs527SW?kaRTjB`A>ge?r%YyhAS^z?0sR?kd$b*?V5!JCITa?>nj?HX(IS$n2Dl7?ksWRd{%* zVP6bug!fZUVo=}w|1U9S$v4D)`C8ztg{!!pq(R&s*XvmOPQJBAlr!27(D*!VMOuzy z^25dT!o+ZZp9Dx^gfC;semoWrPx{GIJ24ucMQ{t~MQkF45@0RW)YSB4|I|b*HWQtk zM9ccIg5MwDT4un6d@e6iNTp>lE65x$LRkC|6)ct$#fY|q&!_#ENP*CJ zm#z`{@w!68n-dy17@ylp5)@XWBJ5FSV$Q+SBBk~&}4~Ssd z0{{q#>?3lT$R#4*Ch~nEOh0CyhRII$E%Lt)f|5;5N8*#w9kZw96S5p! z=*UWR%s%6A;_7l!R-$9p_pB`Ym)u#2j@efommKmFOXso@9kbt3f^z2qlH!m(CvTFs zE+8ci*^Z-f-_ny=35V>PvQzdfJWU09vc8}kSlU530?4sjz9=u9&q{R64x@l}ss|3) zj=l1ryl^Qi(J}jq+$o=um-b{OI%Y@Z^B#FWl~2b^e?v{PLzfz|{u

\ No newline at end of file diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5000587759190016.testcase deleted file mode 100644 index 8a585ce9270e58b125922297f2d099298adac822..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15347 zcmeHOKW`H;6u+P#aRU+(18Xxd6l%E*Nl7L5s!A+KhygMnL5ETmLXBVgZv$er@K!|sD^YeJSDOAWa&ttPlG6X?Atl{} z^qDpjS}5Y|WIWoTq(csczd4*??66BhVoGhy6y1ZDBgWIhQ~nf$4?LB=5tQo zxX3XIMJ!OhCjE@@G@nnHL!!ULItAw?J4Na|Tz{fnYNoHpCUhroxQ^Xm|6~3AZ`jNU z_1CN>Z8L2Ov5UvVto$ukPyf~8Z|ZG_z+Cw)}rtPVgJ$Y!^aQq_qB2x+d@%#VL&Ee zscL#D6CO7NUrf^%e&SnKww(HyG#lR3!%5nHqKHLiq!Uq%XT(ATAI~R!c+#u~ktD)W z#Z-lH42O%htTt3XpZZq_8E}9wb>zG-$Bf4}bwbGBM0e%#VflQ3>E%3$>n4SKSi0u< zER%m$TsEp5ifAh3ZBVWkB$KNF37662`3#lv#vffpN$8m zN~NsW&nsp9m$XI|Y?vkxR-@e#J2vfv={I9yD{8L>?bJ5jl{m^X>DgR>Pz4nzY55>9 zaJF$P4nM{r0N0v8sLEMw1+^QiLKN+(xQwxB!0bXrBv?Z{w${rqtoY4tO&Vk2ajs38ITfhY1|%rRV$pMf6PhuP>A~gb(by@6 zIYN?5j_g2E=LC?WXmn7m$gyJwVL_x)6E>WMna*0~7+ng6=am8TKe^U~eF_~XCRZkW z#PW{M(|AZY!jT)*wowa!XyA7C+-+hS%aO@_kcpK7$) zCWCD<@Kz>oC}@WX+hj0SGTJ5s9fT9I*)juIwVk>gO$LI&wIfvqDdYl5f{7)#xCTIF z2SI2-qp#%56T}6sGt3_+us`Vd;ONzB-y@~Ll>LlA@XZVW@(&R0YF diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5167584867909632.testcase deleted file mode 100644 index 0fe66dd23fe94a8e451dfb1a84da38ed0984c1f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19469 zcmeHP%}&BV5UwW1c<}1c&|0d-m{hN9YYZMVF=z-E6E3Azz?Aa07`*ugp1gb37w}np z1J6Ey_J;^Y+hVrDb~+?vcLObSXLo15`M%w!71Cc4g4b8Y>@_=7*S$g~EsGkt2Bn={ zt2=1kXi~B5P|KmamD`Rb<;p=_zIm%4C&qy-Vu088oOsuGz>Kq!-D0_0%~Ls_F?gfesF!B~xlP=*UCbCH?n*-O%0 z!Q*F>?46hl=N3}p9^s$pfQ;#K?C}VRg&?#Cu4Gl`M+NhN`Lsc{A^94o$;0t3y>S870B{5&zz9DFt<}-BMx(8V;~9 zu^`3{e->4K<9oQkG(Mym>pheEPdQ^GK5fr%nc+{ydd)pa{!emW8I*DurdQ@~y8Kk4 zgV7-WU60=nl>ER&`8c&A8JzU^4}@gt+g^h^gT@rwKLtV<2l@NX63OYId;^?(0~P60 z?9W6QN1A0E6WR+_CBVe3&|S@XJ2R{CP{xr=dJz@rVH;L3n4Q9zrUy|Y_Y}rG!O4js mqyYzMPzM!p)C@wIG(#Cwq{BE*384&|DuI`yvfSgo2>k@d3|T1v diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5270998950477824.testcase deleted file mode 100644 index fd411427d765e9b17e1e6a015485a70632bb9554..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12 TcmY$eDbjbbRX@cb^ZOhC75W5K diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase deleted file mode 100644 index 6248b2c..0000000 --- a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5375146639360000.testcase +++ /dev/null @@ -1 +0,0 @@ -˙ >tet>< \ No newline at end of file diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5492400320282624.testcase deleted file mode 100644 index 107da539fc15bd1664e35287ace9feda21cb5820..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11502 zcmeHNy>HV%6gOf+VqhSEDxuawNKi#?;xtXg#SCTdK!q3y#cd3AnkG&P3ldWY7XAYy zCT0f2N_Q3{#Kh8pfq{iTAiQ_)?sEPrNt;$FI=4Ds&hO(s-o1P8XBP^E%c~a(bbUIR z>pt6&8VYYetR1|1@3DT}-suHUu57m=zZDhNUbKCCoqp6en~h@8f`8Us?*#40@z@;v zvWixx>qm8ug?`kSZAMZ199wmM)@|Fljl~QWU$J;93#i=Gnw~*BlHQ#|0?zbH*5 zb%|;A>ykT1x$T5V0o|~j6!-jKFyP&Q0fx?{e_SD_qO!^BSE=P1b3*t-8C14p{iSNc z2V3ItzI+T%ukbpRx(HH0EkaF-OQ}&>bS_;QQIeM5QcmbNA;V7VgCSi+Ka`)}b4~+u zIOf`Y|F-|bcGS`*xVc><+HeK=DuR7kbb;M|VG*n$UVC7lv5TH2TY-e=Ct3={xQ+R4 zwyZppvo(W_ZxdtZ*>Zz`2*oa8?n9GW;CglXx z<}63=pqMsNj5^H-eT8Y@E zP=-sP&U&-KBcEQhQFN;n4^K@xO-DQbCK=e7a4zp`HQ}5I=Oz-?nQ%^KGA3<_C5= zlRW%*ktfj|g`Fl))G`RHqfkU^=K$nAEVm4Oss1xm@?`cmF%gp;&h|LjDKbyFFvm(o zWHM`)cSw5|y>6c;zMKmSoRv`l zPeWS%fLuIZqeLOxJve;>FPgW-2pF5U#T0&+x5X53 zjQLv8ye*brDwwY#Fm>Y}L;QzdMc~-Z@auB}FN(+qLgC{?R>|o0jGKi4oeBP!uvKWO zmx{C@5I3Jxz--`-k(ePz3Jtudax^kV11};Vc?{4p4le@a3||N1H!?MkT}(oo#aihv D9d3o5 diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase deleted file mode 100644 index 367106c..0000000 --- a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-5703933063462912.testcase +++ /dev/null @@ -1,2 +0,0 @@ - -t \ No newline at end of file diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/clusterfuzz-testcase-minimized-bs4_fuzzer-6450958476902400.testcase deleted file mode 100644 index a823d557b4bebed8a9cdb880d281c9de69a1aa0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3546 zcmdP2$xSTDup1>uLtr!nMnhmU1V%$(Gz3ONU^E0qLtw~uwSNNv*}xU^oQ!vv$DtbH{XnB<{4q&MBMIvxRFa&-_pUv zaZ?A@)wk1eCmnC=bU*Q=8+sfD%u9F-wunGF9Af5kU{XeIH<5gU7$((-f1t0?R%dI;Jq*Qch%_#M(x|K>?1-n+*fFB zm6{d^8#<{hj+7bdpv`Q#2CcfFkUioNUyXr5z+=fRP%u7K(G*r#6$M^Z_&u?|;XuBN z@N6(okxftZk53XI6>lL`P*y0e{H4&t=5>jM|{*N|q#^8%sAhqM+Y3%AITJ zj+ie=x^@H_p!D;o#ZMNvPoPiY!4dto?gr%>8ZfxWSt4CK@!+{gLI_zD^Y~@@!h9AT zhwtJ(69K8%&(5%E2fpgGkYsM!X=s?z8oHP}&TI@w9WRoXm;n8Ha{-ib=yrZ_~b; zLif2&eN24}r`0u!2Q^n!;Z(g+b!QW%0&VHg*@TwX)&r$x>#WdFWGZjuEVhzaKfVQc zE1wv%%}(9W_#3HHZI>9f_+=c57M9cCNo@`2bnw)yoeHG+-$q-W|1arjzM|GxoYGoC z;*bTH!DdtxtcOJ%%uC0=se>6mD|1!l76U4^eq4Nq!{I_ly+tmKJqqfTb*ceU6z362 ztyNgQGww04iSboml65FWdBXI!jzWnWgo#v19R>P(S{7XznX3V~Twq+Re44__&~>h> q43wHvMb7{ew`wA?1}AsyPlT5DF{Md(5}xqoqavh!LXgNIAN~adfn_KF diff --git a/venv/lib/python3.12/site-packages/bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase b/venv/lib/python3.12/site-packages/bs4/tests/fuzz/crash-ffbdfa8a2b26f13537b68d3794b0478a4090ee4a.testcase deleted file mode 100644 index 885711554056588a381fd9a251d48ce76a916a59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103 zcma!IT*$!C&%p3|?)u|48N3V(Hi{|v$wno$1*wb-3(;hvkz^S9^*|aEj@#ts@G|Jx OROIF`00A~ppfmtd#~j4~ diff --git a/venv/lib/python3.12/site-packages/bs4/tests/test_builder.py b/venv/lib/python3.12/site-packages/bs4/tests/test_builder.py deleted file mode 100644 index 87d6758..0000000 --- a/venv/lib/python3.12/site-packages/bs4/tests/test_builder.py +++ /dev/null @@ -1,28 +0,0 @@ -import pytest -from unittest.mock import patch -from bs4.builder import DetectsXMLParsedAsHTML - - -class TestDetectsXMLParsedAsHTML: - @pytest.mark.parametrize( - "markup,looks_like_xml", - [ - ("No xml declaration", False), - ("obviously HTMLActually XHTML", False), - (" < html>Tricky XHTML", False), - ("", True), - ], - ) - def test_warn_if_markup_looks_like_xml(self, markup, looks_like_xml): - # Test of our ability to guess at whether markup looks XML-ish - # _and_ not HTML-ish. - with patch("bs4.builder.DetectsXMLParsedAsHTML._warn") as mock: - for data in markup, markup.encode("utf8"): - result = DetectsXMLParsedAsHTML.warn_if_markup_looks_like_xml(data) - assert result == looks_like_xml - if looks_like_xml: - assert mock.called - else: - assert not mock.called - mock.reset_mock() diff --git a/venv/lib/python3.12/site-packages/bs4/tests/test_builder_registry.py b/venv/lib/python3.12/site-packages/bs4/tests/test_builder_registry.py deleted file mode 100644 index ad4b5a9..0000000 --- a/venv/lib/python3.12/site-packages/bs4/tests/test_builder_registry.py +++ /dev/null @@ -1,139 +0,0 @@ -"""Tests of the builder registry.""" - -import pytest -import warnings -from typing import Type - -from bs4 import BeautifulSoup -from bs4.builder import ( - builder_registry as registry, - TreeBuilder, - TreeBuilderRegistry, -) -from bs4.builder._htmlparser import HTMLParserTreeBuilder - -from . import ( - HTML5LIB_PRESENT, - LXML_PRESENT, -) - -if HTML5LIB_PRESENT: - from bs4.builder._html5lib import HTML5TreeBuilder - -if LXML_PRESENT: - from bs4.builder._lxml import ( - LXMLTreeBuilderForXML, - LXMLTreeBuilder, - ) - - -# TODO: Split out the lxml and html5lib tests into their own classes -# and gate with pytest.mark.skipIf. -class TestBuiltInRegistry(object): - """Test the built-in registry with the default builders registered.""" - - def test_combination(self): - assert registry.lookup("strict", "html") == HTMLParserTreeBuilder - if LXML_PRESENT: - assert registry.lookup("fast", "html") == LXMLTreeBuilder - assert registry.lookup("permissive", "xml") == LXMLTreeBuilderForXML - if HTML5LIB_PRESENT: - assert registry.lookup("html5lib", "html") == HTML5TreeBuilder - - def test_lookup_by_markup_type(self): - if LXML_PRESENT: - assert registry.lookup("html") == LXMLTreeBuilder - assert registry.lookup("xml") == LXMLTreeBuilderForXML - else: - assert registry.lookup("xml") is None - if HTML5LIB_PRESENT: - assert registry.lookup("html") == HTML5TreeBuilder - else: - assert registry.lookup("html") == HTMLParserTreeBuilder - - def test_named_library(self): - if LXML_PRESENT: - assert registry.lookup("lxml", "xml") == LXMLTreeBuilderForXML - assert registry.lookup("lxml", "html") == LXMLTreeBuilder - if HTML5LIB_PRESENT: - assert registry.lookup("html5lib") == HTML5TreeBuilder - - assert registry.lookup("html.parser") == HTMLParserTreeBuilder - - def test_beautifulsoup_constructor_does_lookup(self): - with warnings.catch_warnings(record=True): - # This will create a warning about not explicitly - # specifying a parser, but we'll ignore it. - - # You can pass in a string. - BeautifulSoup("", features="html") - # Or a list of strings. - BeautifulSoup("", features=["html", "fast"]) - pass - - # You'll get an exception if BS can't find an appropriate - # builder. - with pytest.raises(ValueError): - BeautifulSoup("", features="no-such-feature") - - -class TestRegistry(object): - """Test the TreeBuilderRegistry class in general.""" - - def setup_method(self): - self.registry = TreeBuilderRegistry() - - def builder_for_features(self, *feature_list: str) -> Type[TreeBuilder]: - cls = type( - "Builder_" + "_".join(feature_list), (object,), {"features": feature_list} - ) - - self.registry.register(cls) - return cls - - def test_register_with_no_features(self): - builder = self.builder_for_features() - - # Since the builder advertises no features, you can't find it - # by looking up features. - assert self.registry.lookup("foo") is None - - # But you can find it by doing a lookup with no features, if - # this happens to be the only registered builder. - assert self.registry.lookup() == builder - - def test_register_with_features_makes_lookup_succeed(self): - builder = self.builder_for_features("foo", "bar") - assert self.registry.lookup("foo") is builder - assert self.registry.lookup("bar") is builder - - def test_lookup_fails_when_no_builder_implements_feature(self): - assert self.registry.lookup("baz") is None - - def test_lookup_gets_most_recent_registration_when_no_feature_specified(self): - self.builder_for_features("foo") - builder2 = self.builder_for_features("bar") - assert self.registry.lookup() == builder2 - - def test_lookup_fails_when_no_tree_builders_registered(self): - assert self.registry.lookup() is None - - def test_lookup_gets_most_recent_builder_supporting_all_features(self): - self.builder_for_features("foo") - self.builder_for_features("bar") - has_both_early = self.builder_for_features("foo", "bar", "baz") - has_both_late = self.builder_for_features("foo", "bar", "quux") - self.builder_for_features("bar") - self.builder_for_features("foo") - - # There are two builders featuring 'foo' and 'bar', but - # the one that also features 'quux' was registered later. - assert self.registry.lookup("foo", "bar") == has_both_late - - # There is only one builder featuring 'foo', 'bar', and 'baz'. - assert self.registry.lookup("foo", "bar", "baz") == has_both_early - - def test_lookup_fails_when_cannot_reconcile_requested_features(self): - self.builder_for_features("foo", "bar") - self.builder_for_features("foo", "baz") - assert self.registry.lookup("bar", "baz") is None diff --git a/venv/lib/python3.12/site-packages/bs4/tests/test_css.py b/venv/lib/python3.12/site-packages/bs4/tests/test_css.py deleted file mode 100644 index b1c4237..0000000 --- a/venv/lib/python3.12/site-packages/bs4/tests/test_css.py +++ /dev/null @@ -1,536 +0,0 @@ -import pytest -import types - -from bs4 import ( - BeautifulSoup, - ResultSet, -) - -from typing import ( - Any, - List, - Tuple, - Type, -) - -from packaging.version import Version - -from . import ( - SoupTest, - SOUP_SIEVE_PRESENT, -) - -SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS: Type[Exception] -if SOUP_SIEVE_PRESENT: - from soupsieve import __version__, SelectorSyntaxError - - # Some behavior changes in soupsieve 2.6 that affects one of our - # tests. For the test to run under all versions of Python - # supported by Beautiful Soup (which includes versions of Python - # not supported by soupsieve 2.6) we need to check both behaviors. - SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS = SelectorSyntaxError - if Version(__version__) < Version("2.6"): - SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS = NotImplementedError - - -@pytest.mark.skipif(not SOUP_SIEVE_PRESENT, reason="Soup Sieve not installed") -class TestCSSSelectors(SoupTest): - """Test basic CSS selector functionality. - - This functionality is implemented in soupsieve, which has a much - more comprehensive test suite, so this is basically an extra check - that soupsieve works as expected. - """ - - HTML = """ - - - -The title - - - -Hello there. -
-
-

An H1

-

Some text

-

Some more text

-

An H2

-

Another

-Bob -

Another H2

-me - -span1a1 -span1a2 test - -span2a1 - - - -
- -
- - - - - - - - -

English

-

English UK

-

English US

-

French

-
- - -""" - - def setup_method(self): - self._soup = BeautifulSoup(self.HTML, "html.parser") - - def assert_css_selects( - self, selector: str, expected_ids: List[str], **kwargs: Any - ) -> None: - results = self._soup.select(selector, **kwargs) - assert isinstance(results, ResultSet) - el_ids = [el["id"] for el in results] - el_ids.sort() - expected_ids.sort() - assert expected_ids == el_ids, "Selector %s, expected [%s], got [%s]" % ( - selector, - ", ".join(expected_ids), - ", ".join(el_ids), - ) - - assertSelect = assert_css_selects - - def assert_css_select_multiple(self, *tests: Tuple[str, List[str]]): - for selector, expected_ids in tests: - self.assert_css_selects(selector, expected_ids) - - def test_precompiled(self): - sel = self._soup.css.compile("div") - - els = self._soup.select(sel) - assert len(els) == 4 - for div in els: - assert div.name == "div" - - el = self._soup.select_one(sel) - assert "main" == el["id"] - - def test_one_tag_one(self): - els = self._soup.select("title") - assert len(els) == 1 - assert els[0].name == "title" - assert els[0].contents == ["The title"] - - def test_one_tag_many(self): - els = self._soup.select("div") - assert len(els) == 4 - for div in els: - assert div.name == "div" - - el = self._soup.select_one("div") - assert "main" == el["id"] - - def test_select_one_returns_none_if_no_match(self): - match = self._soup.select_one("nonexistenttag") - assert None is match - - def test_tag_in_tag_one(self): - self.assert_css_selects("div div", ["inner", "data1"]) - - def test_tag_in_tag_many(self): - for selector in ("html div", "html body div", "body div"): - self.assert_css_selects(selector, ["data1", "main", "inner", "footer"]) - - def test_limit(self): - self.assert_css_selects("html div", ["main"], limit=1) - self.assert_css_selects("html body div", ["inner", "main"], limit=2) - self.assert_css_selects( - "body div", ["data1", "main", "inner", "footer"], limit=10 - ) - - def test_tag_no_match(self): - assert len(self._soup.select("del")) == 0 - - def test_invalid_tag(self): - with pytest.raises(SelectorSyntaxError): - self._soup.select("tag%t") - - def test_select_dashed_tag_ids(self): - self.assert_css_selects("custom-dashed-tag", ["dash1", "dash2"]) - - def test_select_dashed_by_id(self): - dashed = self._soup.select('custom-dashed-tag[id="dash2"]') - assert dashed[0].name == "custom-dashed-tag" - assert dashed[0]["id"] == "dash2" - - def test_dashed_tag_text(self): - assert self._soup.select("body > custom-dashed-tag")[0].text == "Hello there." - - def test_select_dashed_matches_find_all(self): - assert self._soup.select("custom-dashed-tag") == self._soup.find_all( - "custom-dashed-tag" - ) - - def test_header_tags(self): - self.assert_css_select_multiple( - ("h1", ["header1"]), - ("h2", ["header2", "header3"]), - ) - - def test_class_one(self): - for selector in (".onep", "p.onep", "html p.onep"): - els = self._soup.select(selector) - assert len(els) == 1 - assert els[0].name == "p" - assert els[0]["class"] == ["onep"] - - def test_class_mismatched_tag(self): - els = self._soup.select("div.onep") - assert len(els) == 0 - - def test_one_id(self): - for selector in ("div#inner", "#inner", "div div#inner"): - self.assert_css_selects(selector, ["inner"]) - - def test_bad_id(self): - els = self._soup.select("#doesnotexist") - assert len(els) == 0 - - def test_items_in_id(self): - els = self._soup.select("div#inner p") - assert len(els) == 3 - for el in els: - assert el.name == "p" - assert els[1]["class"] == ["onep"] - assert not els[0].has_attr("class") - - def test_a_bunch_of_emptys(self): - for selector in ("div#main del", "div#main div.oops", "div div#main"): - assert len(self._soup.select(selector)) == 0 - - def test_multi_class_support(self): - for selector in ( - ".class1", - "p.class1", - ".class2", - "p.class2", - ".class3", - "p.class3", - "html p.class2", - "div#inner .class2", - ): - self.assert_css_selects(selector, ["pmulti"]) - - def test_multi_class_selection(self): - for selector in (".class1.class3", ".class3.class2", ".class1.class2.class3"): - self.assert_css_selects(selector, ["pmulti"]) - - def test_child_selector(self): - self.assert_css_selects(".s1 > a", ["s1a1", "s1a2"]) - self.assert_css_selects(".s1 > a span", ["s1a2s1"]) - - def test_child_selector_id(self): - self.assert_css_selects(".s1 > a#s1a2 span", ["s1a2s1"]) - - def test_attribute_equals(self): - self.assert_css_select_multiple( - ('p[class="onep"]', ["p1"]), - ('p[id="p1"]', ["p1"]), - ('[class="onep"]', ["p1"]), - ('[id="p1"]', ["p1"]), - ('link[rel="stylesheet"]', ["l1"]), - ('link[type="text/css"]', ["l1"]), - ('link[href="blah.css"]', ["l1"]), - ('link[href="no-blah.css"]', []), - ('[rel="stylesheet"]', ["l1"]), - ('[type="text/css"]', ["l1"]), - ('[href="blah.css"]', ["l1"]), - ('[href="no-blah.css"]', []), - ('p[href="no-blah.css"]', []), - ('[href="no-blah.css"]', []), - ) - - def test_attribute_tilde(self): - self.assert_css_select_multiple( - ('p[class~="class1"]', ["pmulti"]), - ('p[class~="class2"]', ["pmulti"]), - ('p[class~="class3"]', ["pmulti"]), - ('[class~="class1"]', ["pmulti"]), - ('[class~="class2"]', ["pmulti"]), - ('[class~="class3"]', ["pmulti"]), - ('a[rel~="friend"]', ["bob"]), - ('a[rel~="met"]', ["bob"]), - ('[rel~="friend"]', ["bob"]), - ('[rel~="met"]', ["bob"]), - ) - - def test_attribute_startswith(self): - self.assert_css_select_multiple( - ('[rel^="style"]', ["l1"]), - ('link[rel^="style"]', ["l1"]), - ('notlink[rel^="notstyle"]', []), - ('[rel^="notstyle"]', []), - ('link[rel^="notstyle"]', []), - ('link[href^="bla"]', ["l1"]), - ('a[href^="http://"]', ["bob", "me"]), - ('[href^="http://"]', ["bob", "me"]), - ('[id^="p"]', ["pmulti", "p1"]), - ('[id^="m"]', ["me", "main"]), - ('div[id^="m"]', ["main"]), - ('a[id^="m"]', ["me"]), - ('div[data-tag^="dashed"]', ["data1"]), - ) - - def test_attribute_endswith(self): - self.assert_css_select_multiple( - ('[href$=".css"]', ["l1"]), - ('link[href$=".css"]', ["l1"]), - ('link[id$="1"]', ["l1"]), - ( - '[id$="1"]', - ["data1", "l1", "p1", "header1", "s1a1", "s2a1", "s1a2s1", "dash1"], - ), - ('div[id$="1"]', ["data1"]), - ('[id$="noending"]', []), - ) - - def test_attribute_contains(self): - self.assert_css_select_multiple( - # From test_attribute_startswith - ('[rel*="style"]', ["l1"]), - ('link[rel*="style"]', ["l1"]), - ('notlink[rel*="notstyle"]', []), - ('[rel*="notstyle"]', []), - ('link[rel*="notstyle"]', []), - ('link[href*="bla"]', ["l1"]), - ('[href*="http://"]', ["bob", "me"]), - ('[id*="p"]', ["pmulti", "p1"]), - ('div[id*="m"]', ["main"]), - ('a[id*="m"]', ["me"]), - # From test_attribute_endswith - ('[href*=".css"]', ["l1"]), - ('link[href*=".css"]', ["l1"]), - ('link[id*="1"]', ["l1"]), - ( - '[id*="1"]', - [ - "data1", - "l1", - "p1", - "header1", - "s1a1", - "s1a2", - "s2a1", - "s1a2s1", - "dash1", - ], - ), - ('div[id*="1"]', ["data1"]), - ('[id*="noending"]', []), - # New for this test - ('[href*="."]', ["bob", "me", "l1"]), - ('a[href*="."]', ["bob", "me"]), - ('link[href*="."]', ["l1"]), - ('div[id*="n"]', ["main", "inner"]), - ('div[id*="nn"]', ["inner"]), - ('div[data-tag*="edval"]', ["data1"]), - ) - - def test_attribute_exact_or_hypen(self): - self.assert_css_select_multiple( - ('p[lang|="en"]', ["lang-en", "lang-en-gb", "lang-en-us"]), - ('[lang|="en"]', ["lang-en", "lang-en-gb", "lang-en-us"]), - ('p[lang|="fr"]', ["lang-fr"]), - ('p[lang|="gb"]', []), - ) - - def test_attribute_exists(self): - self.assert_css_select_multiple( - ("[rel]", ["l1", "bob", "me"]), - ("link[rel]", ["l1"]), - ("a[rel]", ["bob", "me"]), - ("[lang]", ["lang-en", "lang-en-gb", "lang-en-us", "lang-fr"]), - ("p[class]", ["p1", "pmulti"]), - ("[blah]", []), - ("p[blah]", []), - ("div[data-tag]", ["data1"]), - ) - - def test_quoted_space_in_selector_name(self): - html = """
nope
-
yes
- """ - soup = BeautifulSoup(html, "html.parser") - [chosen] = soup.select('div[style="display: right"]') - assert "yes" == chosen.string - - def test_unsupported_pseudoclass(self): - with pytest.raises(SOUPSIEVE_EXCEPTION_ON_UNSUPPORTED_PSEUDOCLASS): - self._soup.select("a:no-such-pseudoclass") - - with pytest.raises(SelectorSyntaxError): - self._soup.select("a:nth-of-type(a)") - - def test_nth_of_type(self): - # Try to select first paragraph - els = self._soup.select("div#inner p:nth-of-type(1)") - assert len(els) == 1 - assert els[0].string == "Some text" - - # Try to select third paragraph - els = self._soup.select("div#inner p:nth-of-type(3)") - assert len(els) == 1 - assert els[0].string == "Another" - - # Try to select (non-existent!) fourth paragraph - els = self._soup.select("div#inner p:nth-of-type(4)") - assert len(els) == 0 - - # Zero will select no tags. - els = self._soup.select("div p:nth-of-type(0)") - assert len(els) == 0 - - def test_nth_of_type_direct_descendant(self): - els = self._soup.select("div#inner > p:nth-of-type(1)") - assert len(els) == 1 - assert els[0].string == "Some text" - - def test_id_child_selector_nth_of_type(self): - self.assert_css_selects("#inner > p:nth-of-type(2)", ["p1"]) - - def test_select_on_element(self): - # Other tests operate on the tree; this operates on an element - # within the tree. - inner = self._soup.find("div", id="main") - selected = inner.select("div") - # The
tag was selected. The

\r\n
\r\n

\r\n
\r\n -------- Message transféré --------\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Sujet :\r\n De retour !
Date : Mon, 20 Apr 2020 14:52:05 +0000
De : LENEVEU Guillaume <Guillaume.LENEVEU@calvados.fr>
Pour : Youness BENDEQ <youness.bendeq@cbao.fr>
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n

Bonjour Youness,

\r\n

 

\r\n

J’espère que tu vas bien ainsi que toute\r\n l’équipe BRG-LAB.

\r\n

 

\r\n

Je viens vers toi car Mr NOVO m’a fait\r\n remonter un léger beug sur le numéro d’échantillon B2020-0001\r\n (Voir PJ). En effet, il n’arrive pas à mettre le nom de la\r\n partie dans la partie ( en rouge sur la PJ). Il faudrait\r\n mettre « joint de chaussée côté giberville » comme stipulé\r\n dans le numéro d’affaire -> 20017 SETR -> LIAISON RD403\r\n – RD402 DESSERTE PORTUAIRE VIADUC -> JOINT DE CHAUSSEE COTE\r\n GIBERVILLE.

\r\n

 

\r\n

J’ai essayé de modifié la partie mais je\r\n n’y arrive pas.

\r\n

 

\r\n

Merci de ta réponse.

\r\n

Bonne fin de journée.

\r\n

Cordialement,

\r\n

Guillaume\r\n LENEVEU

\r\n

DGA\r\n Aménagement et Environnement
\r\n Direction de l’eau et des Risques
\r\n Adjoint au Chef du service Laboratoire Routes et Matériaux
\r\n 24 rue des Monts Panneaux ZI Ouest

\r\n

14650\r\n Carpiquet

\r\n

Tél.\r\n 02 31 26 52 62

\r\n

Port.\r\n 06 11 39 10 60

\r\n

Fax.\r\n 02\r\n 31 26 99 38
\r\n Mail.
guillaume.leneveu@calvados.fr

\r\n

\r\n

 

\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
**************************************************************************************************\r\n« Cette transmission contient des informations confidentielles et/ou personnelles\r\nappartenant au conseil départemental du Calvados pour être utilisées exclusivement par le\r\ndestinataire. Toute utilisation, reproduction, publication, diffusion en l'état ou\r\npartiellement par une autre personne que le destinataire est interdite, sauf autorisation\r\nexpresse du conseil départemental du Calvados. En cas d'erreur de transmission, merci de\r\ndétruire le(s) document(s) reçu(s). Le conseil départemental du Calvados n'est pas\r\nresponsable des virus, altérations, falsifications.\r\nDroits réservés - conseil départemental du Calvados».\r\n**************************************************************************************************
\r\n
\r\n
\r\n
\r\n
\r\n

\r\n
\r\n -------- Message transféré --------\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Sujet :\r\n Re: [T0150] Problème d'impression des PV de compression\r\n des éprouvettes 11H22
Date : Thu, 23 Apr 2020 14:33:46 +0200 (CEST)
De : CAZARD Yoan <yoan.cazard@cd66.fr>
Pour : support <support@cbao.fr>
\r\n
\r\n
\r\n
\r\n
Oui, il faut prendre la valeur corrigée (selon EN 206/CN)\r\n pour évaluer la conformité du béton.
\r\n Il faut bien distinguer :
\r\n - la norme d'essai 12390-3 qui ne traite que de l'essai et qui\r\n n'a pas vocation à se prononcer sur la conformité du matériau\r\n : le résultat d'essai est bien la force appliquée (en N)\r\n divisée par la section de l'éprouvette, quelle que soit cette\r\n section,
\r\n - la norme béton EN 206/CN, qui donne des indications pour se\r\n prononcer sur la conformité du béton, notamment la prise en\r\n compte de la taille de éprouvette (11x22) et des corrections à\r\n apporter pour se ramener à une éprouvette normalisée 15x30.
\r\n
\r\n Le mode de correction des valeurs brutes d'essai est\r\n indépendant de la norme d'essai et vous appartient.
\r\n Dans le cas de carottes prélevées sur ouvrages existant par\r\n exemple, la correction ne se fera pas selon l'EN 206/CN mais\r\n selon d'autres dispositions.
\r\n
\r\n cdlt
\r\n
\r\n
Le 23/04/2020 à 10:36, >\r\n CAZARD Yoan (par Internet) a écrit :
\r\n
\r\n
\r\n
\r\n
Bonjour et merci beaucoup Pierre pour ces précisions.\r\n C'est plus clair.
\r\n
\r\n

\r\n
\r\n
Donc, on peut bien avoir, comme ce qui se faisait\r\n déjà, les deux valeurs affichées sur le rapport\r\n d'essais.
\r\n
\r\n

\r\n
\r\n
Par contre, pour la vérification de résistances\r\n d'éprouvettes béton, pour des laboratoires\r\n départementaux comme nous, et notamment pour de petites\r\n valeurs (pour le RAANE par exemple), pouvons-nous\r\n continuer à prendre les résistances corrigées pour la\r\n conformité du matériau?
\r\n
\r\n

\r\n
\r\n
Yoan CAZARD
\r\n Responsable Laboratoire Départemental Routes et Ouvrages\r\n d'Art
\r\n Conseil Départemental 66
\r\n Direction Infrastructures et Déplacements
\r\n Développement et Expertise Technique
\r\n 1265 avenue Julien Panchot
\r\n 66000 Perpignan
\r\n 04-68-68-36-90
\r\n 06-73-87-52-43
\r\n

\r\n
\r\n
\r\n
De: \"PAYA Pierre\" <Pierre.Paya@cerema.fr>
\r\n À: \"CAZARD Yoan\" <yoan.cazard@cd66.fr>
\r\n Cc: \"JAN Didier\" <didier.jan@cerema.fr>,\r\n \"ddumas\" <ddumas@ardeche.fr>,\r\n \"Gérald LACROIX\" <glacroix@cg83.fr>,\r\n \"s labourasse\" <s.labourasse@cg04.fr>,\r\n \"Stephane roques\" <Stephane.roques@cg12.fr>,\r\n \"claude trelcat\" <claude.trelcat@cg84.fr>,\r\n \"benoit gaumet\" <benoit.gaumet@cg12.fr>,\r\n \"jm dao\" <jm.dao@cg04.fr>,\r\n \"a ferrer\" <a.ferrer@cg04.fr>,\r\n \"pierre david\" <pierre.david@cg05.fr>,\r\n \"philippe delorme\" <philippe.delorme@cg05.fr>,\r\n \"Morales Frederic\" <frederic.morales@vaucluse.fr>,\r\n \"CELLI Sylvain\" <sylvain.celli@cg-corsedusud.fr>,\r\n \"BOISSONNADE-CORP Pierre\" <pierre.boissonnade-corp@cg12.fr>,\r\n \"Richard BOREL\" <richard.borel@cg05.fr>,\r\n \"alain guiraud\" <alain.guiraud@cg12.fr>,\r\n \"raymond cayzac\" <raymond.cayzac@cg12.fr>,\r\n \"georges pouget\" <georges.pouget@cg12.fr>,\r\n \"noel sanchez\" <noel.sanchez@ct-corse.fr>,\r\n \"joseph pau\" <joseph.pau@cg-corsedusud.fr>,\r\n \"nicolas teisseire\" <nicolas.teisseire@cg11.fr>,\r\n mmohammedi@ardeche.fr,\r\n \"jerome gombault\" <jerome.gombault@cg11.fr>,\r\n \"alain nargeot\" <alain.nargeot@gard.fr>,\r\n \"bhilaire\" <bhilaire@ardeche.fr>,\r\n \"TEKATLIAN Annick\" <Annick.TEKATLIAN@cerema.fr>,\r\n \"CORDIER Nathalie - CEREMA/DTerMed/LABO AIX/SOAB\" <Nathalie.Cordier@cerema.fr>,\r\n \"GONTARD Lisa - CEREMA/DTerMed/LABO AIX/SOAB\" <lisa.gontard@cerema.fr>
\r\n Envoyé: Jeudi 23\r\n Avril 2020 10:17:43
\r\n Objet: Re: Ecrasements béton
\r\n
\r\n

\r\n
\r\n
bonjour Ă  tous,
\r\n
\r\n Je viens d'avoir Michael  Dierkens au téléphone et il\r\n m'a retransmis la réponse faite à BRG-Lab :
\r\n \"Si une seule valeur apparait, çà ne peut\r\n être que la valeur brute (non-corrigée).
\r\n Une autre solution peut être aussi, s'il y a assez de\r\n place sur le rapport d'essai, de faire apparaitre 2\r\n colonnes : 1 corrigée et 1 non-corrigée. Mais la\r\n valeur corrigée peut être vue comme une interprétation\r\n du résultat et poser des problèmes à un labo qui\r\n serait Cofrac.\"
\r\n
\r\n Sa réponse est cohérente (heureusement\r\n ...) avec celle que j'avais faite en décembre\r\n 2019 :
\r\n
\"Je rajoute également\r\n que doivent figurer dans le PV d'essais :
\r\n - la charge maximale Ă  la rupture en N,
\r\n - la résistance à la compression non\r\n corrigée en Mpa (c'est à dire sans prise en\r\n compte des corrections de l'EN 206 sur les 11x22\r\n notamment).\"
\r\n
\r\n Il faut retenir que :
\r\n - la norme impose d'afficher dans le PV la charge\r\n maximale à rupture non corrigée (en N) ainsi que la\r\n résistance non corrigée (en MPa) : ces données\r\n doivent donc figurer impérativement dans le PV,
\r\n - la norme n'interdit pas de rajouter des éléments\r\n dans le PV, en particulier la résistance corrigée\r\n pour des 11x22, si cette donnée vous parait utile\r\n (ou pour votre client) : dans ce cas le COFRAC peut\r\n considérer que l'affichage de cette valeur corrigée\r\n est une interprétation du résultat et demander à\r\n vérifier que l'interprétation des résultats a bien\r\n été définie clairement dans le contrat qui vous lie\r\n à votre client.
\r\n
\r\n Pour information nous faisons apparaitre les\r\n résistances brutes et corrigées sur nos PV (sous\r\n accréditation COFRAC).
\r\n
\r\n Je reste disponible pour toute précision.
\r\n
\r\n bien cordialement,
\r\n
\r\n
Pierre PAYA
\r\n
\r\n
\r\n Responsable de l'activité Matériaux,\r\n Construction et Certification
\r\n
Laboratoire -\r\n service Ouvrages d'Art et Bâtiment - Tél.: 04 42 24 78 30
\r\n Direction Territoriale\r\n Méditerranée
\r\n
\"\"
\r\n
Centre\r\n d’études et d’expertise sur les risques,\r\n l’environnement, la mobilité et l’aménagement\r\n
\r\n www.cerema.fr
\r\n

\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
Le 22/04/2020 à 10:11, >\r\n CAZARD Yoan (par Internet) a écrit :
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n

Bonjour Ă  tous,
\r\n

\r\n


\r\n

\r\n

J'espère que tout\r\n le monde va bien dans ce contexte particulier.

\r\n


\r\n

\r\n

Je vous fait\r\n remonter une problématique que nous avons\r\n rencontrée en passant sur la version web de\r\n BRG-LAB. Cela concerne les résultats d'essais\r\n des écrasements des éprouvettes 11x22. Les PV\r\n ou rapports d'essais n'affichent plus que les\r\n résistances brutes sans la correction de 1\r\n MPa. Je vous joins ci-dessous la réponse de\r\n CBAO. Je les ai contactés depuis afin de\r\n pouvoir ajouter une option à cocher pour\r\n choisir d'afficher cette résistance corrigée.\r\n Je pense que nous sommes nombreux dans ce cas.\r\n Nous sommes dans l'attente d'une solution de\r\n CBAO.

\r\n


\r\n

\r\n

Pierre Paya nous\r\n avait déjà indiqué de n'afficher que la\r\n résistance brute sur le PV d'essais, mais il\r\n me semble que nous prenons tous en compte que\r\n la résistance corrigée?
\r\n

\r\n


\r\n

\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n

\r\n
\r\n
Yoan CAZARD
\r\n Responsable Laboratoire Départemental Routes et Ouvrages d'Art
\r\n Conseil Départemental 66
\r\n Direction Infrastructures et Déplacements
\r\n Développement et Expertise Technique
\r\n 1265 avenue Julien Panchot
\r\n 66000 Perpignan
\r\n 04-68-68-36-90
\r\n 06-73-87-52-43
\r\n
\r\n
\r\n
De: \"Youness BENDEQ\"\r\n <youness.bendeq@cbao.fr>
\r\n À: \"Yohan CAZARD\" <yoan.cazard@cd66.fr>
\r\n Envoyé: Jeudi 23 Avril 2020 12:33:06
\r\n Objet: Re: [T0150] Problème d'impression des PV de\r\n compression des éprouvettes 11H22
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
Voir\r\n Tâche \"CBAO\r\n
\r\n
\r\n
\r\n
\r\n

Bonjour,
\r\n

\r\n


\r\n

\r\n
Ci-dessous les\r\n échanges avec Pierre Paya du Cerema d'Aix, qui s'est mis\r\n en relation avec M.Dierkens.
\r\n


\r\n

\r\n

Je ne vois pas l'échange\r\n complet, pouvez-vous me le renvoyer svp ?
\r\n

\r\n

Je reste à votre disposition\r\n pour toute explication ou demande supplémentaire.
\r\n

\r\n

L'objectif du Support\r\n Technique est de vous aider : n'hésitez jamais à nous\r\n contacter si vous rencontrez une difficulté, ou pour\r\n nous soumettre une ou des suggestions d'amélioration de\r\n nos logiciels ou de nos méthodes.
\r\n

\r\n

Cordialement.
\r\n

\r\n


\r\n

\r\n

Support Technique - CBAO
\r\n

\r\n

www.cbao.fr
\r\n

\r\n

80 rue Louis Braille
\r\n

\r\n

66000 PERPIGNAN
\r\n

\r\n

support@cbao.fr
\r\n

\r\n

Tél : 04 68 64 15 31
\r\n

\r\n

Fax : 04 68 64 31 69
\r\n

\r\n
\r\n
\r\n


\r\n

\r\n
\r\n

Envoyé \r\n par CBAO\r\n S.A.R.L. .\r\n

\r\n
\r\n \"\"
\r\n
\r\n
\r\n
\r\n